| OLD | NEW |
| (Empty) |
| 1 # 2008 Feb 19 | |
| 2 # | |
| 3 # The author disclaims copyright to this source code. In place of | |
| 4 # a legal notice, here is a blessing: | |
| 5 # | |
| 6 # May you do good and not evil. | |
| 7 # May you find forgiveness for yourself and forgive others. | |
| 8 # May you share freely, never taking more than you give. | |
| 9 # | |
| 10 #*********************************************************************** | |
| 11 # | |
| 12 # This file contains Tcl code that may be useful for testing or | |
| 13 # analyzing r-tree structures created with this module. It is | |
| 14 # used by both test procedures and the r-tree viewer application. | |
| 15 # | |
| 16 # $Id: rtree_util.tcl,v 1.1 2008/05/26 18:41:54 danielk1977 Exp $ | |
| 17 # | |
| 18 | |
| 19 | |
| 20 #-------------------------------------------------------------------------- | |
| 21 # PUBLIC API: | |
| 22 # | |
| 23 # rtree_depth | |
| 24 # rtree_ndim | |
| 25 # rtree_node | |
| 26 # rtree_mincells | |
| 27 # rtree_check | |
| 28 # rtree_dump | |
| 29 # rtree_treedump | |
| 30 # | |
| 31 | |
| 32 proc rtree_depth {db zTab} { | |
| 33 $db one "SELECT rtreedepth(data) FROM ${zTab}_node WHERE nodeno=1" | |
| 34 } | |
| 35 | |
| 36 proc rtree_nodedepth {db zTab iNode} { | |
| 37 set iDepth [rtree_depth $db $zTab] | |
| 38 | |
| 39 set ii $iNode | |
| 40 while {$ii != 1} { | |
| 41 set sql "SELECT parentnode FROM ${zTab}_parent WHERE nodeno = $ii" | |
| 42 set ii [db one $sql] | |
| 43 incr iDepth -1 | |
| 44 } | |
| 45 | |
| 46 return $iDepth | |
| 47 } | |
| 48 | |
| 49 # Return the number of dimensions of the rtree. | |
| 50 # | |
| 51 proc rtree_ndim {db zTab} { | |
| 52 set nDim [expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}] | |
| 53 } | |
| 54 | |
| 55 # Return the contents of rtree node $iNode. | |
| 56 # | |
| 57 proc rtree_node {db zTab iNode {iPrec 6}} { | |
| 58 set nDim [rtree_ndim $db $zTab] | |
| 59 set sql " | |
| 60 SELECT rtreenode($nDim, data) FROM ${zTab}_node WHERE nodeno = $iNode | |
| 61 " | |
| 62 set node [db one $sql] | |
| 63 | |
| 64 set nCell [llength $node] | |
| 65 set nCoord [expr $nDim*2] | |
| 66 for {set ii 0} {$ii < $nCell} {incr ii} { | |
| 67 for {set jj 1} {$jj <= $nCoord} {incr jj} { | |
| 68 set newval [format "%.${iPrec}f" [lindex $node $ii $jj]] | |
| 69 lset node $ii $jj $newval | |
| 70 } | |
| 71 } | |
| 72 set node | |
| 73 } | |
| 74 | |
| 75 proc rtree_mincells {db zTab} { | |
| 76 set n [$db one "select length(data) FROM ${zTab}_node LIMIT 1"] | |
| 77 set nMax [expr {int(($n-4)/(8+[rtree_ndim $db $zTab]*2*4))}] | |
| 78 return [expr {int($nMax/3)}] | |
| 79 } | |
| 80 | |
| 81 # An integrity check for the rtree $zTab accessible via database | |
| 82 # connection $db. | |
| 83 # | |
| 84 proc rtree_check {db zTab} { | |
| 85 array unset ::checked | |
| 86 | |
| 87 # Check each r-tree node. | |
| 88 set rc [catch { | |
| 89 rtree_node_check $db $zTab 1 [rtree_depth $db $zTab] | |
| 90 } msg] | |
| 91 if {$rc && $msg ne ""} { error $msg } | |
| 92 | |
| 93 # Check that the _rowid and _parent tables have the right | |
| 94 # number of entries. | |
| 95 set nNode [$db one "SELECT count(*) FROM ${zTab}_node"] | |
| 96 set nRow [$db one "SELECT count(*) FROM ${zTab}"] | |
| 97 set nRowid [$db one "SELECT count(*) FROM ${zTab}_rowid"] | |
| 98 set nParent [$db one "SELECT count(*) FROM ${zTab}_parent"] | |
| 99 | |
| 100 if {$nNode != ($nParent+1)} { | |
| 101 error "Wrong number of entries in ${zTab}_parent" | |
| 102 } | |
| 103 if {$nRow != $nRowid} { | |
| 104 error "Wrong number of entries in ${zTab}_rowid" | |
| 105 } | |
| 106 | |
| 107 return $rc | |
| 108 } | |
| 109 | |
| 110 proc rtree_node_check {db zTab iNode iDepth} { | |
| 111 if {[info exists ::checked($iNode)]} { error "Second ref to $iNode" } | |
| 112 set ::checked($iNode) 1 | |
| 113 | |
| 114 set node [rtree_node $db $zTab $iNode] | |
| 115 if {$iNode!=1 && [llength $node]==0} { error "No such node: $iNode" } | |
| 116 | |
| 117 if {$iNode != 1 && [llength $node]<[rtree_mincells $db $zTab]} { | |
| 118 puts "Node $iNode: Has only [llength $node] cells" | |
| 119 error "" | |
| 120 } | |
| 121 if {$iNode == 1 && [llength $node]==1 && [rtree_depth $db $zTab]>0} { | |
| 122 set depth [rtree_depth $db $zTab] | |
| 123 puts "Node $iNode: Has only 1 child (tree depth is $depth)" | |
| 124 error "" | |
| 125 } | |
| 126 | |
| 127 set nDim [expr {([llength [lindex $node 0]]-1)/2}] | |
| 128 | |
| 129 if {$iDepth > 0} { | |
| 130 set d [expr $iDepth-1] | |
| 131 foreach cell $node { | |
| 132 set shouldbe [rtree_node_check $db $zTab [lindex $cell 0] $d] | |
| 133 if {$cell ne $shouldbe} { | |
| 134 puts "Node $iNode: Cell is: {$cell}, should be {$shouldbe}" | |
| 135 error "" | |
| 136 } | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 set mapping_table "${zTab}_parent" | |
| 141 set mapping_sql "SELECT parentnode FROM $mapping_table WHERE rowid = \$rowid" | |
| 142 if {$iDepth==0} { | |
| 143 set mapping_table "${zTab}_rowid" | |
| 144 set mapping_sql "SELECT nodeno FROM $mapping_table WHERE rowid = \$rowid" | |
| 145 } | |
| 146 foreach cell $node { | |
| 147 set rowid [lindex $cell 0] | |
| 148 set mapping [db one $mapping_sql] | |
| 149 if {$mapping != $iNode} { | |
| 150 puts "Node $iNode: $mapping_table entry for cell $rowid is $mapping" | |
| 151 error "" | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 set ret [list $iNode] | |
| 156 for {set ii 1} {$ii <= $nDim*2} {incr ii} { | |
| 157 set f [lindex $node 0 $ii] | |
| 158 foreach cell $node { | |
| 159 set f2 [lindex $cell $ii] | |
| 160 if {($ii%2)==1 && $f2<$f} {set f $f2} | |
| 161 if {($ii%2)==0 && $f2>$f} {set f $f2} | |
| 162 } | |
| 163 lappend ret $f | |
| 164 } | |
| 165 return $ret | |
| 166 } | |
| 167 | |
| 168 proc rtree_dump {db zTab} { | |
| 169 set zRet "" | |
| 170 set nDim [expr {(([llength [$db eval "pragma table_info($zTab)"]]/6)-1)/2}] | |
| 171 set sql "SELECT nodeno, rtreenode($nDim, data) AS node FROM ${zTab}_node" | |
| 172 $db eval $sql { | |
| 173 append zRet [format "% -10s %s\n" $nodeno $node] | |
| 174 } | |
| 175 set zRet | |
| 176 } | |
| 177 | |
| 178 proc rtree_nodetreedump {db zTab zIndent iDepth iNode} { | |
| 179 set ret "" | |
| 180 set node [rtree_node $db $zTab $iNode 1] | |
| 181 append ret [format "%-3d %s%s\n" $iNode $zIndent $node] | |
| 182 if {$iDepth>0} { | |
| 183 foreach cell $node { | |
| 184 set i [lindex $cell 0] | |
| 185 append ret [rtree_nodetreedump $db $zTab "$zIndent " [expr $iDepth-1] $i] | |
| 186 } | |
| 187 } | |
| 188 set ret | |
| 189 } | |
| 190 | |
| 191 proc rtree_treedump {db zTab} { | |
| 192 set d [rtree_depth $db $zTab] | |
| 193 rtree_nodetreedump $db $zTab "" $d 1 | |
| 194 } | |
| 195 | |
| OLD | NEW |