Skip to content

Commit

Permalink
fix: properly insert first element into tree
Browse files Browse the repository at this point in the history
  • Loading branch information
emma-k-alexandra committed Jan 29, 2022
1 parent e2f0d25 commit d058564
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 158 deletions.
26 changes: 9 additions & 17 deletions Sources/RTree/DirectoryNodeData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,26 @@ extension DirectoryNodeData {

/// Updates MBR of this node with another bounding box
mutating func updateMBRWithElement(_ elementBoundingBox: BoundingRectangle<T.Point>) {
if let _ = self.boundingBox {
self.boundingBox!.add(elementBoundingBox)

if self.boundingBox != nil {
self.boundingBox?.add(elementBoundingBox)
} else {
self.boundingBox = elementBoundingBox

}

}

/// Inserts an element into this node
public mutating func insert(_ t: RTreeNode<T>, state: inout InsertionState) throws -> InsertionResult<T>
{
self.updateMBRWithElement(t.minimumBoundingRectangle())
mutating func insert(_ t: RTreeNode<T>, state: inout InsertionState) throws -> InsertionResult<T> {
updateMBRWithElement(t.minimumBoundingRectangle())

if t.depth() + 1 == self.depth {
if t.depth() + 1 == depth {
var newChildren = [t]

self.addChildren(&newChildren)
self.childrenOffsets = []
return self.resolveOverflow(&state)

addChildren(&newChildren)
childrenOffsets = []
return resolveOverflow(&state)
}

var (follow, index) = self.chooseSubtree(t)
var (follow, index) = chooseSubtree(t)
let expand = try follow.insert(t, state: &state)
self.children![index] = .directoryNode(follow)

Expand All @@ -131,14 +126,11 @@ extension DirectoryNodeData {
self.addChildren(&children)
self.childrenOffsets = []
return self.resolveOverflow(&state)

case .reinsert:
self.updateMBR()
return expand

case .complete:
return .complete

}

}
Expand Down
16 changes: 6 additions & 10 deletions Sources/RTree/Insertion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,28 @@
import Foundation

/// Stores the reinsertion state
public struct InsertionState {
public var reinsertions: [Bool]
struct InsertionState {
var reinsertions: [Bool]

init(maxDepth: Int) {
assert(maxDepth > -1, "maxDepth must be non-negative")
self.reinsertions = [Bool](repeating: false, count: maxDepth)

reinsertions = [Bool](repeating: false, count: maxDepth)
}

}

extension InsertionState {
public func didReinsert(depth: Int) -> Bool {
func didReinsert(depth: Int) -> Bool {
self.reinsertions[depth]

}

public mutating func markReinsertion(depth: Int) {
mutating func markReinsertion(depth: Int) {
self.reinsertions[depth] = true

}

}

/// The result of an insertion
public enum InsertionResult<T>
enum InsertionResult<T>
where
T: SpatialObject
{
Expand Down
81 changes: 27 additions & 54 deletions Sources/RTree/RTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ where
if storage.isEmpty() {
if readOnly {
throw RTreeError.treeMarkedReadOnly

}

self.path = path
Expand All @@ -63,15 +62,11 @@ where
self.isReadOnly = readOnly

try self.save()

} else {
self = try storage.loadRoot()
self.isReadOnly = readOnly

}

}

}

extension RTree {
Expand All @@ -82,12 +77,10 @@ extension RTree {
public mutating func insert(_ t: T) throws {
if self.isReadOnly {
throw RTreeError.treeMarkedReadOnly

}

if self.root == nil {
try self.load()

}

var state = InsertionState(maxDepth: self.root!.depth + 1)
Expand All @@ -104,95 +97,77 @@ extension RTree {

var newChildren = [RTreeNode.directoryNode(oldRoot), node]
self.root!.addChildren(&newChildren)

case .reinsert(let nodes):
insertionStack.append(contentsOf: nodes)

case .complete:
continue

}

}

self.size += 1

try self.save()
size += 1

try save()
}

}

extension RTree {
/// Finds the nearest neighbor to the given point. `nil` if tree is empty.
public mutating func nearestNeighbor(_ queryPoint: T.Point) throws -> T? {
if self.root == nil {
try self.load()

if root == nil {
try load()
}

let result = self.root!.nearestNeighbor(queryPoint)
let result = root!.nearestNeighbor(queryPoint)

if result == nil, self.size > 0 {
var iterator = try self.nearestNeighborIterator(queryPoint)
if result == nil, size > 0 {
var iterator = try nearestNeighborIterator(queryPoint)

return iterator.next()

}

return result

}

public mutating func nearestNeighborIterator(_ queryPoint: T.Point) throws -> NearestNeighborIterator<T> {
if self.root == nil {
try self.load()

if root == nil {
try load()
}

return NearestNeighborIterator(root: self.root!, queryPoint: queryPoint)

return NearestNeighborIterator(root: root!, queryPoint: queryPoint)
}

}

extension RTree {
/// Saves this tree to disk
mutating func save() throws {
guard let storage = self.storage else {
guard let storage = storage else {
throw RTreeError.storageNotPresent

}

if self.root == nil {
try self.load()

if root == nil {
try load()
}

if storage.isEmpty() {
try storage.initialize()

}
// if storage.isEmpty() {
// try storage.initialize()
// }

self.rootOffset = try self.root!.save()
self.rootOffset = try root!.save()
try storage.save(self)

}

mutating func load() throws {
if self.storage == nil {
self.storage = try Storage<T>(
path: self.path!,
readOnly: self.isReadOnly,
if storage == nil {
storage = try Storage<T>(
path: path!,
readOnly: isReadOnly,
encoder: encoder,
decoder: decoder
)
}

self.root = try self.storage!.loadDirectoryNodeData(withOffset: self.rootOffset)

root = try storage!.loadDirectoryNodeData(withOffset: rootOffset)
}

}

extension RTree: Codable {
Expand All @@ -204,25 +179,23 @@ extension RTree: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(self.rootOffset.toPaddedString(), forKey: .root)
try container.encode(self.size, forKey: .size)

try container.encode(rootOffset.toPaddedString(), forKey: .root)
try container.encode(size, forKey: .size)
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

self.size = try container.decode(Int.self, forKey: .size)
size = try container.decode(Int.self, forKey: .size)

let rootNodeOffsetString = try container.decode(String.self, forKey: .root)

guard let rootNodeOffset = UInt64(rootNodeOffsetString) else {
throw RTreeError.invalidRecord

}

self.rootOffset = rootNodeOffset
rootOffset = rootNodeOffset

self.isReadOnly = false
isReadOnly = false
}
}
Loading

0 comments on commit d058564

Please sign in to comment.