mirror of https://github.com/tidwall/rtred.git
removed iter/context. extra pointers
This commit is contained in:
parent
442f9f0d8e
commit
b71853025b
16
rtree.go
16
rtree.go
|
@ -152,13 +152,13 @@ func (tr *RTree) search1(min, max []float64, iter Iterator) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ended := false
|
ended := false
|
||||||
tr.tr1.Search(amin, amax, func(dataID, context interface{}) bool {
|
tr.tr1.Search(amin, amax, func(dataID interface{}) bool {
|
||||||
if !iter(dataID.(Item)) {
|
if !iter(dataID.(Item)) {
|
||||||
ended = true
|
ended = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil)
|
})
|
||||||
return !ended
|
return !ended
|
||||||
}
|
}
|
||||||
func (tr *RTree) search2(min, max []float64, iter Iterator) bool {
|
func (tr *RTree) search2(min, max []float64, iter Iterator) bool {
|
||||||
|
@ -173,13 +173,13 @@ func (tr *RTree) search2(min, max []float64, iter Iterator) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ended := false
|
ended := false
|
||||||
tr.tr2.Search(amin, amax, func(dataID, context interface{}) bool {
|
tr.tr2.Search(amin, amax, func(dataID interface{}) bool {
|
||||||
if !iter(dataID.(Item)) {
|
if !iter(dataID.(Item)) {
|
||||||
ended = true
|
ended = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil)
|
})
|
||||||
return !ended
|
return !ended
|
||||||
}
|
}
|
||||||
func (tr *RTree) search3(min, max []float64, iter Iterator) bool {
|
func (tr *RTree) search3(min, max []float64, iter Iterator) bool {
|
||||||
|
@ -194,13 +194,13 @@ func (tr *RTree) search3(min, max []float64, iter Iterator) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ended := false
|
ended := false
|
||||||
tr.tr3.Search(amin, amax, func(dataID, context interface{}) bool {
|
tr.tr3.Search(amin, amax, func(dataID interface{}) bool {
|
||||||
if !iter(dataID.(Item)) {
|
if !iter(dataID.(Item)) {
|
||||||
ended = true
|
ended = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil)
|
})
|
||||||
return !ended
|
return !ended
|
||||||
}
|
}
|
||||||
func (tr *RTree) search4(min, max []float64, iter Iterator) bool {
|
func (tr *RTree) search4(min, max []float64, iter Iterator) bool {
|
||||||
|
@ -215,12 +215,12 @@ func (tr *RTree) search4(min, max []float64, iter Iterator) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ended := false
|
ended := false
|
||||||
tr.tr4.Search(amin, amax, func(dataID, context interface{}) bool {
|
tr.tr4.Search(amin, amax, func(dataID interface{}) bool {
|
||||||
if !iter(dataID.(Item)) {
|
if !iter(dataID.(Item)) {
|
||||||
ended = true
|
ended = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}, nil)
|
})
|
||||||
return !ended
|
return !ended
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const (
|
||||||
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultCallback func(dataID, context interface{}) bool
|
type ResultCallback func(dataID interface{}) bool
|
||||||
|
|
||||||
var unitSphereVolume float64
|
var unitSphereVolume float64
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (tr *RTree) Remove(min, max [NUMDIMS]float64, dataId interface{}) {
|
||||||
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||||
/// \param a_context User context to pass as parameter to a_resultCallback
|
/// \param a_context User context to pass as parameter to a_resultCallback
|
||||||
/// \return Returns the number of entries found
|
/// \return Returns the number of entries found
|
||||||
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback, context interface{}) int {
|
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback) int {
|
||||||
if _DEBUG {
|
if _DEBUG {
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
ASSERT(min[index] <= max[index])
|
ASSERT(min[index] <= max[index])
|
||||||
|
@ -196,10 +196,7 @@ func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback
|
||||||
rect.min[axis] = min[axis]
|
rect.min[axis] = min[axis]
|
||||||
rect.max[axis] = max[axis]
|
rect.max[axis] = max[axis]
|
||||||
}
|
}
|
||||||
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
|
foundCount, _ := Search(tr.root, rect, 0, resultCallback)
|
||||||
|
|
||||||
foundCount := 0
|
|
||||||
Search(tr.root, &rect, &foundCount, resultCallback, context)
|
|
||||||
return foundCount
|
return foundCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +725,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
|
|
||||||
if node.IsInternalNode() { // not a leaf node
|
if node.IsInternalNode() { // not a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &(node.branch[index].rect)) {
|
if Overlap(*rect, node.branch[index].rect) {
|
||||||
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
||||||
if node.branch[index].child.count >= MINNODES {
|
if node.branch[index].child.count >= MINNODES {
|
||||||
// child removed, just resize parent rect
|
// child removed, just resize parent rect
|
||||||
|
@ -755,9 +752,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide whether two rectangles overlap.
|
// Decide whether two rectangles overlap.
|
||||||
func Overlap(rectA, rectB *Rect) bool {
|
func Overlap(rectA, rectB Rect) bool {
|
||||||
ASSERT(rectA != nil && rectB != nil)
|
|
||||||
|
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
if rectA.min[index] > rectB.max[index] ||
|
if rectA.min[index] > rectB.max[index] ||
|
||||||
rectB.min[index] > rectA.max[index] {
|
rectB.min[index] > rectA.max[index] {
|
||||||
|
@ -777,37 +772,34 @@ func ReInsert(node *Node, listNode **ListNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
||||||
func Search(node *Node, rect *Rect, foundCount *int, resultCallback ResultCallback, context interface{}) bool {
|
func Search(node *Node, rect Rect, foundCount int, resultCallback ResultCallback) (int, bool) {
|
||||||
ASSERT(node != nil)
|
ASSERT(node != nil)
|
||||||
ASSERT(node.level >= 0)
|
ASSERT(node.level >= 0)
|
||||||
ASSERT(rect != nil)
|
|
||||||
|
|
||||||
if node.IsInternalNode() {
|
if node.IsInternalNode() {
|
||||||
// This is an internal node in the tree
|
// This is an internal node in the tree
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
if !Search(node.branch[index].child, rect, foundCount, resultCallback, context) {
|
var ok bool
|
||||||
|
foundCount, ok = Search(node.branch[index].child, rect, foundCount, resultCallback)
|
||||||
|
if !ok {
|
||||||
// The callback indicated to stop searching
|
// The callback indicated to stop searching
|
||||||
return false
|
return foundCount, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a leaf node
|
// This is a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
id := node.branch[index].data
|
id := node.branch[index].data
|
||||||
|
foundCount++
|
||||||
// NOTE: There are different ways to return results. Here's where to modify
|
if !resultCallback(id) {
|
||||||
|
return foundCount, false // Don't continue searching
|
||||||
*foundCount++
|
|
||||||
if !resultCallback(id, context) {
|
|
||||||
return false // Don't continue searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return foundCount, true // Continue searching
|
||||||
return true // Continue searching
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const (
|
||||||
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultCallback func(dataID, context interface{}) bool
|
type ResultCallback func(dataID interface{}) bool
|
||||||
|
|
||||||
var unitSphereVolume float64
|
var unitSphereVolume float64
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (tr *RTree) Remove(min, max [NUMDIMS]float64, dataId interface{}) {
|
||||||
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||||
/// \param a_context User context to pass as parameter to a_resultCallback
|
/// \param a_context User context to pass as parameter to a_resultCallback
|
||||||
/// \return Returns the number of entries found
|
/// \return Returns the number of entries found
|
||||||
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback, context interface{}) int {
|
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback) int {
|
||||||
if _DEBUG {
|
if _DEBUG {
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
ASSERT(min[index] <= max[index])
|
ASSERT(min[index] <= max[index])
|
||||||
|
@ -196,10 +196,7 @@ func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback
|
||||||
rect.min[axis] = min[axis]
|
rect.min[axis] = min[axis]
|
||||||
rect.max[axis] = max[axis]
|
rect.max[axis] = max[axis]
|
||||||
}
|
}
|
||||||
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
|
foundCount, _ := Search(tr.root, rect, 0, resultCallback)
|
||||||
|
|
||||||
foundCount := 0
|
|
||||||
Search(tr.root, &rect, &foundCount, resultCallback, context)
|
|
||||||
return foundCount
|
return foundCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +725,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
|
|
||||||
if node.IsInternalNode() { // not a leaf node
|
if node.IsInternalNode() { // not a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &(node.branch[index].rect)) {
|
if Overlap(*rect, node.branch[index].rect) {
|
||||||
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
||||||
if node.branch[index].child.count >= MINNODES {
|
if node.branch[index].child.count >= MINNODES {
|
||||||
// child removed, just resize parent rect
|
// child removed, just resize parent rect
|
||||||
|
@ -755,9 +752,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide whether two rectangles overlap.
|
// Decide whether two rectangles overlap.
|
||||||
func Overlap(rectA, rectB *Rect) bool {
|
func Overlap(rectA, rectB Rect) bool {
|
||||||
ASSERT(rectA != nil && rectB != nil)
|
|
||||||
|
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
if rectA.min[index] > rectB.max[index] ||
|
if rectA.min[index] > rectB.max[index] ||
|
||||||
rectB.min[index] > rectA.max[index] {
|
rectB.min[index] > rectA.max[index] {
|
||||||
|
@ -777,37 +772,34 @@ func ReInsert(node *Node, listNode **ListNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
||||||
func Search(node *Node, rect *Rect, foundCount *int, resultCallback ResultCallback, context interface{}) bool {
|
func Search(node *Node, rect Rect, foundCount int, resultCallback ResultCallback) (int, bool) {
|
||||||
ASSERT(node != nil)
|
ASSERT(node != nil)
|
||||||
ASSERT(node.level >= 0)
|
ASSERT(node.level >= 0)
|
||||||
ASSERT(rect != nil)
|
|
||||||
|
|
||||||
if node.IsInternalNode() {
|
if node.IsInternalNode() {
|
||||||
// This is an internal node in the tree
|
// This is an internal node in the tree
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
if !Search(node.branch[index].child, rect, foundCount, resultCallback, context) {
|
var ok bool
|
||||||
|
foundCount, ok = Search(node.branch[index].child, rect, foundCount, resultCallback)
|
||||||
|
if !ok {
|
||||||
// The callback indicated to stop searching
|
// The callback indicated to stop searching
|
||||||
return false
|
return foundCount, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a leaf node
|
// This is a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
id := node.branch[index].data
|
id := node.branch[index].data
|
||||||
|
foundCount++
|
||||||
// NOTE: There are different ways to return results. Here's where to modify
|
if !resultCallback(id) {
|
||||||
|
return foundCount, false // Don't continue searching
|
||||||
*foundCount++
|
|
||||||
if !resultCallback(id, context) {
|
|
||||||
return false // Don't continue searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return foundCount, true // Continue searching
|
||||||
return true // Continue searching
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const (
|
||||||
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultCallback func(dataID, context interface{}) bool
|
type ResultCallback func(dataID interface{}) bool
|
||||||
|
|
||||||
var unitSphereVolume float64
|
var unitSphereVolume float64
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (tr *RTree) Remove(min, max [NUMDIMS]float64, dataId interface{}) {
|
||||||
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||||
/// \param a_context User context to pass as parameter to a_resultCallback
|
/// \param a_context User context to pass as parameter to a_resultCallback
|
||||||
/// \return Returns the number of entries found
|
/// \return Returns the number of entries found
|
||||||
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback, context interface{}) int {
|
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback) int {
|
||||||
if _DEBUG {
|
if _DEBUG {
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
ASSERT(min[index] <= max[index])
|
ASSERT(min[index] <= max[index])
|
||||||
|
@ -196,10 +196,7 @@ func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback
|
||||||
rect.min[axis] = min[axis]
|
rect.min[axis] = min[axis]
|
||||||
rect.max[axis] = max[axis]
|
rect.max[axis] = max[axis]
|
||||||
}
|
}
|
||||||
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
|
foundCount, _ := Search(tr.root, rect, 0, resultCallback)
|
||||||
|
|
||||||
foundCount := 0
|
|
||||||
Search(tr.root, &rect, &foundCount, resultCallback, context)
|
|
||||||
return foundCount
|
return foundCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +725,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
|
|
||||||
if node.IsInternalNode() { // not a leaf node
|
if node.IsInternalNode() { // not a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &(node.branch[index].rect)) {
|
if Overlap(*rect, node.branch[index].rect) {
|
||||||
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
||||||
if node.branch[index].child.count >= MINNODES {
|
if node.branch[index].child.count >= MINNODES {
|
||||||
// child removed, just resize parent rect
|
// child removed, just resize parent rect
|
||||||
|
@ -755,9 +752,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide whether two rectangles overlap.
|
// Decide whether two rectangles overlap.
|
||||||
func Overlap(rectA, rectB *Rect) bool {
|
func Overlap(rectA, rectB Rect) bool {
|
||||||
ASSERT(rectA != nil && rectB != nil)
|
|
||||||
|
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
if rectA.min[index] > rectB.max[index] ||
|
if rectA.min[index] > rectB.max[index] ||
|
||||||
rectB.min[index] > rectA.max[index] {
|
rectB.min[index] > rectA.max[index] {
|
||||||
|
@ -777,37 +772,34 @@ func ReInsert(node *Node, listNode **ListNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
||||||
func Search(node *Node, rect *Rect, foundCount *int, resultCallback ResultCallback, context interface{}) bool {
|
func Search(node *Node, rect Rect, foundCount int, resultCallback ResultCallback) (int, bool) {
|
||||||
ASSERT(node != nil)
|
ASSERT(node != nil)
|
||||||
ASSERT(node.level >= 0)
|
ASSERT(node.level >= 0)
|
||||||
ASSERT(rect != nil)
|
|
||||||
|
|
||||||
if node.IsInternalNode() {
|
if node.IsInternalNode() {
|
||||||
// This is an internal node in the tree
|
// This is an internal node in the tree
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
if !Search(node.branch[index].child, rect, foundCount, resultCallback, context) {
|
var ok bool
|
||||||
|
foundCount, ok = Search(node.branch[index].child, rect, foundCount, resultCallback)
|
||||||
|
if !ok {
|
||||||
// The callback indicated to stop searching
|
// The callback indicated to stop searching
|
||||||
return false
|
return foundCount, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a leaf node
|
// This is a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
id := node.branch[index].data
|
id := node.branch[index].data
|
||||||
|
foundCount++
|
||||||
// NOTE: There are different ways to return results. Here's where to modify
|
if !resultCallback(id) {
|
||||||
|
return foundCount, false // Don't continue searching
|
||||||
*foundCount++
|
|
||||||
if !resultCallback(id, context) {
|
|
||||||
return false // Don't continue searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return foundCount, true // Continue searching
|
||||||
return true // Continue searching
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const (
|
||||||
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultCallback func(dataID, context interface{}) bool
|
type ResultCallback func(dataID interface{}) bool
|
||||||
|
|
||||||
var unitSphereVolume float64
|
var unitSphereVolume float64
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (tr *RTree) Remove(min, max [NUMDIMS]float64, dataId interface{}) {
|
||||||
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||||
/// \param a_context User context to pass as parameter to a_resultCallback
|
/// \param a_context User context to pass as parameter to a_resultCallback
|
||||||
/// \return Returns the number of entries found
|
/// \return Returns the number of entries found
|
||||||
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback, context interface{}) int {
|
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback) int {
|
||||||
if _DEBUG {
|
if _DEBUG {
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
ASSERT(min[index] <= max[index])
|
ASSERT(min[index] <= max[index])
|
||||||
|
@ -196,10 +196,7 @@ func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback
|
||||||
rect.min[axis] = min[axis]
|
rect.min[axis] = min[axis]
|
||||||
rect.max[axis] = max[axis]
|
rect.max[axis] = max[axis]
|
||||||
}
|
}
|
||||||
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
|
foundCount, _ := Search(tr.root, rect, 0, resultCallback)
|
||||||
|
|
||||||
foundCount := 0
|
|
||||||
Search(tr.root, &rect, &foundCount, resultCallback, context)
|
|
||||||
return foundCount
|
return foundCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +725,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
|
|
||||||
if node.IsInternalNode() { // not a leaf node
|
if node.IsInternalNode() { // not a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &(node.branch[index].rect)) {
|
if Overlap(*rect, node.branch[index].rect) {
|
||||||
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
||||||
if node.branch[index].child.count >= MINNODES {
|
if node.branch[index].child.count >= MINNODES {
|
||||||
// child removed, just resize parent rect
|
// child removed, just resize parent rect
|
||||||
|
@ -755,9 +752,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide whether two rectangles overlap.
|
// Decide whether two rectangles overlap.
|
||||||
func Overlap(rectA, rectB *Rect) bool {
|
func Overlap(rectA, rectB Rect) bool {
|
||||||
ASSERT(rectA != nil && rectB != nil)
|
|
||||||
|
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
if rectA.min[index] > rectB.max[index] ||
|
if rectA.min[index] > rectB.max[index] ||
|
||||||
rectB.min[index] > rectA.max[index] {
|
rectB.min[index] > rectA.max[index] {
|
||||||
|
@ -777,37 +772,34 @@ func ReInsert(node *Node, listNode **ListNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
||||||
func Search(node *Node, rect *Rect, foundCount *int, resultCallback ResultCallback, context interface{}) bool {
|
func Search(node *Node, rect Rect, foundCount int, resultCallback ResultCallback) (int, bool) {
|
||||||
ASSERT(node != nil)
|
ASSERT(node != nil)
|
||||||
ASSERT(node.level >= 0)
|
ASSERT(node.level >= 0)
|
||||||
ASSERT(rect != nil)
|
|
||||||
|
|
||||||
if node.IsInternalNode() {
|
if node.IsInternalNode() {
|
||||||
// This is an internal node in the tree
|
// This is an internal node in the tree
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
if !Search(node.branch[index].child, rect, foundCount, resultCallback, context) {
|
var ok bool
|
||||||
|
foundCount, ok = Search(node.branch[index].child, rect, foundCount, resultCallback)
|
||||||
|
if !ok {
|
||||||
// The callback indicated to stop searching
|
// The callback indicated to stop searching
|
||||||
return false
|
return foundCount, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a leaf node
|
// This is a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
id := node.branch[index].data
|
id := node.branch[index].data
|
||||||
|
foundCount++
|
||||||
// NOTE: There are different ways to return results. Here's where to modify
|
if !resultCallback(id) {
|
||||||
|
return foundCount, false // Don't continue searching
|
||||||
*foundCount++
|
|
||||||
if !resultCallback(id, context) {
|
|
||||||
return false // Don't continue searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return foundCount, true // Continue searching
|
||||||
return true // Continue searching
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ const (
|
||||||
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
USE_SPHERICAL_VOLUME = true // Better split classification, may be slower on some systems
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResultCallback func(dataID, context interface{}) bool
|
type ResultCallback func(dataID interface{}) bool
|
||||||
|
|
||||||
var unitSphereVolume float64
|
var unitSphereVolume float64
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (tr *RTree) Remove(min, max [NUMDIMS]float64, dataId interface{}) {
|
||||||
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||||
/// \param a_context User context to pass as parameter to a_resultCallback
|
/// \param a_context User context to pass as parameter to a_resultCallback
|
||||||
/// \return Returns the number of entries found
|
/// \return Returns the number of entries found
|
||||||
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback, context interface{}) int {
|
func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback) int {
|
||||||
if _DEBUG {
|
if _DEBUG {
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
ASSERT(min[index] <= max[index])
|
ASSERT(min[index] <= max[index])
|
||||||
|
@ -196,10 +196,7 @@ func (tr *RTree) Search(min, max [NUMDIMS]float64, resultCallback ResultCallback
|
||||||
rect.min[axis] = min[axis]
|
rect.min[axis] = min[axis]
|
||||||
rect.max[axis] = max[axis]
|
rect.max[axis] = max[axis]
|
||||||
}
|
}
|
||||||
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
|
foundCount, _ := Search(tr.root, rect, 0, resultCallback)
|
||||||
|
|
||||||
foundCount := 0
|
|
||||||
Search(tr.root, &rect, &foundCount, resultCallback, context)
|
|
||||||
return foundCount
|
return foundCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +725,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
|
|
||||||
if node.IsInternalNode() { // not a leaf node
|
if node.IsInternalNode() { // not a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &(node.branch[index].rect)) {
|
if Overlap(*rect, node.branch[index].rect) {
|
||||||
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
if !RemoveRectRec(rect, id, node.branch[index].child, listNode) {
|
||||||
if node.branch[index].child.count >= MINNODES {
|
if node.branch[index].child.count >= MINNODES {
|
||||||
// child removed, just resize parent rect
|
// child removed, just resize parent rect
|
||||||
|
@ -755,9 +752,7 @@ func RemoveRectRec(rect *Rect, id interface{}, node *Node, listNode **ListNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide whether two rectangles overlap.
|
// Decide whether two rectangles overlap.
|
||||||
func Overlap(rectA, rectB *Rect) bool {
|
func Overlap(rectA, rectB Rect) bool {
|
||||||
ASSERT(rectA != nil && rectB != nil)
|
|
||||||
|
|
||||||
for index := 0; index < NUMDIMS; index++ {
|
for index := 0; index < NUMDIMS; index++ {
|
||||||
if rectA.min[index] > rectB.max[index] ||
|
if rectA.min[index] > rectB.max[index] ||
|
||||||
rectB.min[index] > rectA.max[index] {
|
rectB.min[index] > rectA.max[index] {
|
||||||
|
@ -777,37 +772,34 @@ func ReInsert(node *Node, listNode **ListNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
|
||||||
func Search(node *Node, rect *Rect, foundCount *int, resultCallback ResultCallback, context interface{}) bool {
|
func Search(node *Node, rect Rect, foundCount int, resultCallback ResultCallback) (int, bool) {
|
||||||
ASSERT(node != nil)
|
ASSERT(node != nil)
|
||||||
ASSERT(node.level >= 0)
|
ASSERT(node.level >= 0)
|
||||||
ASSERT(rect != nil)
|
|
||||||
|
|
||||||
if node.IsInternalNode() {
|
if node.IsInternalNode() {
|
||||||
// This is an internal node in the tree
|
// This is an internal node in the tree
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
if !Search(node.branch[index].child, rect, foundCount, resultCallback, context) {
|
var ok bool
|
||||||
|
foundCount, ok = Search(node.branch[index].child, rect, foundCount, resultCallback)
|
||||||
|
if !ok {
|
||||||
// The callback indicated to stop searching
|
// The callback indicated to stop searching
|
||||||
return false
|
return foundCount, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a leaf node
|
// This is a leaf node
|
||||||
for index := 0; index < node.count; index++ {
|
for index := 0; index < node.count; index++ {
|
||||||
if Overlap(rect, &node.branch[index].rect) {
|
if Overlap(rect, node.branch[index].rect) {
|
||||||
id := node.branch[index].data
|
id := node.branch[index].data
|
||||||
|
foundCount++
|
||||||
// NOTE: There are different ways to return results. Here's where to modify
|
if !resultCallback(id) {
|
||||||
|
return foundCount, false // Don't continue searching
|
||||||
*foundCount++
|
|
||||||
if !resultCallback(id, context) {
|
|
||||||
return false // Don't continue searching
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return foundCount, true // Continue searching
|
||||||
return true // Continue searching
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue