Move mbr implementation to seperate file
This commit is contained in:
2
Makefile
2
Makefile
@@ -5,7 +5,7 @@ range:
|
|||||||
py src/rangequeries.py output/rtree.txt data/ranges.txt
|
py src/rangequeries.py output/rtree.txt data/ranges.txt
|
||||||
|
|
||||||
knn:
|
knn:
|
||||||
py src/knnqueries.py output/rtree.txt data/knn.txt 10
|
py src/knnqueries.py output/rtree.txt data/knn.txt $(k)
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -1,74 +1,31 @@
|
|||||||
from os import write
|
|
||||||
from os import path, makedirs
|
|
||||||
import sys
|
import sys
|
||||||
import csv
|
import csv
|
||||||
|
from mbr import MBR
|
||||||
|
from os import path, makedirs
|
||||||
|
|
||||||
if not path.exists('output'):
|
if not path.exists('output'):
|
||||||
makedirs('output')
|
makedirs('output')
|
||||||
|
|
||||||
_DIVISORS = [180.0 / 2 ** n for n in range(32)]
|
|
||||||
|
|
||||||
class MBR:
|
|
||||||
def __init__(self, id, xlow, xhigh, ylow, yhigh):
|
|
||||||
self.xlow = xlow
|
|
||||||
self.xhigh = xhigh
|
|
||||||
self.ylow = ylow
|
|
||||||
self.yhigh = yhigh
|
|
||||||
self.id = id
|
|
||||||
self.zcurve = self.findZcurve()
|
|
||||||
|
|
||||||
def findZcurve(self):
|
|
||||||
x_median = (self.xlow + self.xhigh) / 2
|
|
||||||
y_median = (self.ylow + self.yhigh) / 2
|
|
||||||
return interleave_latlng(y_median, x_median)
|
|
||||||
|
|
||||||
def interleave_latlng(lat, lng):
|
|
||||||
if lng > 180:
|
|
||||||
x = (lng % 180) + 180.0
|
|
||||||
elif lng < -180:
|
|
||||||
x = (-((-lng) % 180)) + 180.0
|
|
||||||
else:
|
|
||||||
x = lng + 180.0
|
|
||||||
if lat > 90:
|
|
||||||
y = (lat % 90) + 90.0
|
|
||||||
elif lat < -90:
|
|
||||||
y = (-((-lat) % 90)) + 90.0
|
|
||||||
else:
|
|
||||||
y = lat + 90.0
|
|
||||||
|
|
||||||
morton_code = ""
|
|
||||||
for dx in _DIVISORS:
|
|
||||||
digit = 0
|
|
||||||
if y >= dx:
|
|
||||||
digit |= 2
|
|
||||||
y -= dx
|
|
||||||
if x >= dx:
|
|
||||||
digit |= 1
|
|
||||||
x -= dx
|
|
||||||
morton_code += str(digit)
|
|
||||||
|
|
||||||
return morton_code
|
|
||||||
|
|
||||||
# Given a set of coordinates find the MBR
|
# Given a set of coordinates find the MBR
|
||||||
def findMBR(objId, points):
|
def find_mbr(obj_id, points):
|
||||||
x_min = min(points, key=lambda p: p[0])[0]
|
xlow = min(points, key=lambda p: p[0])[0]
|
||||||
x_max = max(points, key=lambda p: p[0])[0]
|
xhigh = max(points, key=lambda p: p[0])[0]
|
||||||
y_min = min(points, key=lambda p: p[1])[1]
|
ylow = min(points, key=lambda p: p[1])[1]
|
||||||
y_max = max(points, key=lambda p: p[1])[1]
|
yhigh = max(points, key=lambda p: p[1])[1]
|
||||||
|
|
||||||
return MBR(objId, x_min, x_max, y_min, y_max)
|
return MBR(obj_id, xlow, xhigh, ylow, yhigh)
|
||||||
|
|
||||||
# Given a set of MBRs find the MBR
|
# Given a set of MBRs find their MBR
|
||||||
def createMBR(nodeId, mbrs):
|
def create_mbr(node_id, mbrs):
|
||||||
x_min = min(mbr.xlow for mbr in mbrs)
|
xlow = min(mbr.xlow for mbr in mbrs)
|
||||||
x_max = max(mbr.xhigh for mbr in mbrs)
|
xhigh = max(mbr.xhigh for mbr in mbrs)
|
||||||
y_min = min(mbr.ylow for mbr in mbrs)
|
ylow = min(mbr.ylow for mbr in mbrs)
|
||||||
y_max = max(mbr.yhigh for mbr in mbrs)
|
yhigh = max(mbr.yhigh for mbr in mbrs)
|
||||||
|
|
||||||
return MBR(nodeId, x_min, x_max, y_min, y_max)
|
return MBR(node_id, xlow, xhigh, ylow, yhigh)
|
||||||
|
|
||||||
# Read data from input files
|
# Read data from input files
|
||||||
def inputReader(filename1, filename2):
|
def input_reader(filename1, filename2):
|
||||||
set_of_points = []
|
set_of_points = []
|
||||||
with open(filename1, 'r') as offsets, open(filename2, 'r') as coords:
|
with open(filename1, 'r') as offsets, open(filename2, 'r') as coords:
|
||||||
reader = csv.reader(offsets, delimiter=',', quoting=csv.QUOTE_NONE)
|
reader = csv.reader(offsets, delimiter=',', quoting=csv.QUOTE_NONE)
|
||||||
@@ -81,26 +38,26 @@ def inputReader(filename1, filename2):
|
|||||||
return set_of_points
|
return set_of_points
|
||||||
|
|
||||||
# Write data into output file
|
# Write data into output file
|
||||||
def outputWriter(filename, rTree):
|
def output_writer(filename, RTREE):
|
||||||
with open(filename, 'w+') as rtree:
|
with open(filename, 'w+') as rtree:
|
||||||
numNode = 0
|
node_num = 0
|
||||||
leaves = 0
|
leaves = 0
|
||||||
for level in rTree:
|
for level in RTREE:
|
||||||
for node in level:
|
for node in level:
|
||||||
rtree.write("[{}, {}, [[".format(leaves, numNode))
|
rtree.write("[{}, {}, [[".format(leaves, node_num))
|
||||||
for i in range(len(node) - 1):
|
for i in range(len(node) - 1):
|
||||||
rtree.write("{}, [{}, {}, {}, {}]],[".format(
|
rtree.write("{}, [{}, {}, {}, {}]],[".format(
|
||||||
node[i].id, node[i].xlow, node[i].xhigh, node[i].ylow, node[i].yhigh))
|
node[i].id, node[i].xlow, node[i].xhigh, node[i].ylow, node[i].yhigh))
|
||||||
rtree.write("{}, [{}, {}, {}, {}]]]]".format(
|
rtree.write("{}, [{}, {}, {}, {}]]]]".format(
|
||||||
node[-1].id, node[-1].xlow, node[-1].xhigh, node[-1].ylow, node[-1].yhigh))
|
node[-1].id, node[-1].xlow, node[-1].xhigh, node[-1].ylow, node[-1].yhigh))
|
||||||
rtree.write("\n")
|
rtree.write("\n")
|
||||||
numNode += 1
|
node_num += 1
|
||||||
leaves = 1
|
leaves = 1
|
||||||
|
|
||||||
#
|
# Bulk load R-Tree
|
||||||
def makeRtree(collection):
|
def construct(collection):
|
||||||
level = [] # list of levels(of nodes) of nodes(of mbrs) of mbrs(of points)
|
level = [] # list of levels(of nodes) of nodes(of mbrs) of mbrs(of points)
|
||||||
nodeId = 0
|
node_id = 0
|
||||||
rank = 0
|
rank = 0
|
||||||
# Until we reach the root node
|
# Until we reach the root node
|
||||||
while len(collection) > 1:
|
while len(collection) > 1:
|
||||||
@@ -117,8 +74,8 @@ def makeRtree(collection):
|
|||||||
# Make the new MBRs based on the corners of each 20-piece
|
# Make the new MBRs based on the corners of each 20-piece
|
||||||
collection = []
|
collection = []
|
||||||
for node in nodes: #for every 20 MBRs in 500 MBRs
|
for node in nodes: #for every 20 MBRs in 500 MBRs
|
||||||
collection.append(createMBR(nodeId, node))
|
collection.append(create_mbr(node_id, node))
|
||||||
nodeId += 1
|
node_id += 1
|
||||||
|
|
||||||
level.append(nodes)
|
level.append(nodes)
|
||||||
print("{} nodes at level {}".format(len(nodes), rank))
|
print("{} nodes at level {}".format(len(nodes), rank))
|
||||||
@@ -128,16 +85,16 @@ def makeRtree(collection):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Read the coordinates of the polygons points
|
# Read the coordinates of the polygons points
|
||||||
set_of_points = inputReader(filename1=sys.argv[1], filename2=sys.argv[2])
|
set_of_points = input_reader(filename1=sys.argv[1], filename2=sys.argv[2])
|
||||||
|
|
||||||
# Create the mbrs of the polygons
|
# Create the mbrs of the polygons
|
||||||
mbrs = []
|
mbrs = []
|
||||||
for sp in set_of_points:
|
for sp in set_of_points:
|
||||||
mbrs.append(findMBR(sp[0], sp[1]))
|
mbrs.append(find_mbr(sp[0], sp[1]))
|
||||||
|
|
||||||
# Sort the mbrs based on the Z curve
|
# Sort the mbrs based on the Z curve
|
||||||
mbrs.sort(key=lambda ld: ld.zcurve)
|
mbrs.sort(key=lambda ld: ld.zcurve)
|
||||||
|
|
||||||
# Make the Rtree
|
# Make the Rtree
|
||||||
rTree = makeRtree(mbrs)
|
rTree = construct(mbrs)
|
||||||
outputWriter("output/rtree.txt", rTree)
|
output_writer("output/rtree.txt", rTree)
|
||||||
|
|||||||
@@ -1,57 +1,10 @@
|
|||||||
import sys
|
import sys
|
||||||
import ast
|
import ast
|
||||||
|
from mbr import MBR, Node, Point
|
||||||
import heapq as hq
|
import heapq as hq
|
||||||
from math import sqrt
|
|
||||||
|
|
||||||
class Point:
|
# Read R-Tree from data
|
||||||
def __init__(self, x, y):
|
def parse_tree(filename):
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
|
|
||||||
class MBR:
|
|
||||||
def __init__(self, id, xlow, xhigh, ylow, yhigh):
|
|
||||||
self.xlow = xlow
|
|
||||||
self.xhigh = xhigh
|
|
||||||
self.ylow = ylow
|
|
||||||
self.yhigh = yhigh
|
|
||||||
self.id = id
|
|
||||||
self.obj = False
|
|
||||||
|
|
||||||
def setDistance(self, qp):
|
|
||||||
self.distance = self.findDistance(qp)
|
|
||||||
|
|
||||||
def findDistance(self, qp):
|
|
||||||
dx = dy = 0
|
|
||||||
if qp.x < self.xlow:
|
|
||||||
dx = self.xlow - qp.x
|
|
||||||
elif qp.x > self.xhigh:
|
|
||||||
dx = qp.x - self.xhigh
|
|
||||||
else:
|
|
||||||
dx = 0
|
|
||||||
|
|
||||||
if qp.y < self.ylow:
|
|
||||||
dy = self.ylow - qp.y
|
|
||||||
elif qp.y > self.yhigh:
|
|
||||||
dy = qp.y - self.yhigh
|
|
||||||
else:
|
|
||||||
dy = 0
|
|
||||||
return sqrt(dx**2 + dy**2)
|
|
||||||
|
|
||||||
def makeObject(self):
|
|
||||||
self.obj = True
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
if self.distance < other.distance:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
class Node:
|
|
||||||
def __init__(self, leaf, id, list_of_mbrs):
|
|
||||||
self.leaf = leaf
|
|
||||||
self.id = id
|
|
||||||
self.list_of_mbrs = list_of_mbrs
|
|
||||||
|
|
||||||
def parseRtree(filename):
|
|
||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
nodes = []
|
nodes = []
|
||||||
for line in f:
|
for line in f:
|
||||||
@@ -64,17 +17,17 @@ def parseRtree(filename):
|
|||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
# Read and execute all the NN queries assigned to the r tree
|
# Read and execute all the NN queries
|
||||||
def parseQuery(rtree, filename, k):
|
def parse_query(rtree, filename, k):
|
||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
num = 0
|
num = 0
|
||||||
for line in f:
|
for line in f:
|
||||||
[x, y] = line.split()
|
[x, y] = line.split()
|
||||||
findKNN(rtree, Point(float(x), float(y)), k, num)
|
find_knn(rtree, Point(float(x), float(y)), k, num)
|
||||||
num += 1
|
num += 1
|
||||||
|
|
||||||
# Search for the neareset k neighboors
|
# Search and print the neareset k neighboors
|
||||||
def findKNN(rtree, qp, k, num):
|
def find_knn(rtree, qp, k, num):
|
||||||
# List to put our k nn objects
|
# List to put our k nn objects
|
||||||
results = []
|
results = []
|
||||||
# Initialize a priority queue
|
# Initialize a priority queue
|
||||||
@@ -112,5 +65,5 @@ def findKNN(rtree, qp, k, num):
|
|||||||
print(nn.id)
|
print(nn.id)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
rtree = parseRtree(sys.argv[1])
|
rtree = parse_tree(sys.argv[1])
|
||||||
parseQuery(rtree, sys.argv[2], int(sys.argv[3]))
|
parse_query(rtree, sys.argv[2], int(sys.argv[3]))
|
||||||
|
|||||||
67
src/mbr.py
Normal file
67
src/mbr.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import sys
|
||||||
|
from os import path
|
||||||
|
from math import sqrt
|
||||||
|
|
||||||
|
sys.path.insert(0, path.dirname(path.dirname(path.abspath(__file__))))
|
||||||
|
from pymorton.pymorton.pymorton import interleave_latlng
|
||||||
|
|
||||||
|
class Point:
|
||||||
|
def __init__(self, x, y):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
class MBR:
|
||||||
|
def __init__(self, id, xlow, xhigh, ylow, yhigh):
|
||||||
|
self.xlow = xlow
|
||||||
|
self.xhigh = xhigh
|
||||||
|
self.ylow = ylow
|
||||||
|
self.yhigh = yhigh
|
||||||
|
self.id = id
|
||||||
|
self.obj = False
|
||||||
|
self.zcurve = self.findZcurve()
|
||||||
|
|
||||||
|
def findZcurve(self):
|
||||||
|
x_median = (self.xlow + self.xhigh) / 2
|
||||||
|
y_median = (self.ylow + self.yhigh) / 2
|
||||||
|
return interleave_latlng(y_median, x_median)
|
||||||
|
|
||||||
|
def setDistance(self, p):
|
||||||
|
self.distance = self.findDistance(p)
|
||||||
|
|
||||||
|
def findDistance(self, p):
|
||||||
|
dx = dy = 0
|
||||||
|
if p.x < self.xlow:
|
||||||
|
dx = self.xlow - p.x
|
||||||
|
elif p.x > self.xhigh:
|
||||||
|
dx = p.x - self.xhigh
|
||||||
|
else:
|
||||||
|
dx = 0
|
||||||
|
|
||||||
|
if p.y < self.ylow:
|
||||||
|
dy = self.ylow - p.y
|
||||||
|
elif p.y > self.yhigh:
|
||||||
|
dy = p.y - self.yhigh
|
||||||
|
else:
|
||||||
|
dy = 0
|
||||||
|
return sqrt(dx**2 + dy**2)
|
||||||
|
|
||||||
|
def makeObject(self):
|
||||||
|
self.obj = True
|
||||||
|
|
||||||
|
def intersects(self, other):
|
||||||
|
if self.xlow > other.xhigh or self.xhigh < other.xlow:
|
||||||
|
return False
|
||||||
|
if self.ylow > other.yhigh or self.yhigh < other.ylow:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if self.distance < other.distance:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
def __init__(self, leaf, id, list_of_mbrs):
|
||||||
|
self.leaf = leaf
|
||||||
|
self.id = id
|
||||||
|
self.list_of_mbrs = list_of_mbrs
|
||||||
@@ -1,28 +1,9 @@
|
|||||||
import sys
|
import sys
|
||||||
import ast
|
import ast
|
||||||
|
from mbr import MBR, Node
|
||||||
|
|
||||||
class MBR:
|
# Read R-Tree from data
|
||||||
def __init__(self, id, xlow, xhigh, ylow, yhigh):
|
def parse_tree(filename):
|
||||||
self.xlow = xlow
|
|
||||||
self.xhigh = xhigh
|
|
||||||
self.ylow = ylow
|
|
||||||
self.yhigh = yhigh
|
|
||||||
self.id = id
|
|
||||||
|
|
||||||
def intersects(self, other):
|
|
||||||
if self.xlow > other.xhigh or self.xhigh < other.xlow:
|
|
||||||
return False
|
|
||||||
if self.ylow > other.yhigh or self.yhigh < other.ylow:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
class Node:
|
|
||||||
def __init__(self, leaf, id, list_of_mbrs):
|
|
||||||
self.leaf = leaf
|
|
||||||
self.id = id
|
|
||||||
self.list_of_mbrs = list_of_mbrs
|
|
||||||
|
|
||||||
def parseRtree(filename):
|
|
||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
nodes = []
|
nodes = []
|
||||||
for line in f:
|
for line in f:
|
||||||
@@ -35,14 +16,14 @@ def parseRtree(filename):
|
|||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
# Read and execute all the range queries assigned to the r tree
|
# Read and execute all the range queries
|
||||||
def parseQuery(rtree, filename):
|
def parse_query(rtree, filename):
|
||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
i = 0
|
i = 0
|
||||||
for line in f:
|
for line in f:
|
||||||
[xlow, ylow, xhigh, yhigh] = line.split()
|
[xlow, ylow, xhigh, yhigh] = line.split()
|
||||||
results = []
|
results = []
|
||||||
rangeQuery(rtree, MBR(int(i), float(xlow), float(xhigh),
|
range_query(rtree, MBR(int(i), float(xlow), float(xhigh),
|
||||||
float(ylow), float(yhigh)), results)
|
float(ylow), float(yhigh)), results)
|
||||||
|
|
||||||
print("{} ({}):".format(i, len(results)), end=' ')
|
print("{} ({}):".format(i, len(results)), end=' ')
|
||||||
@@ -55,18 +36,18 @@ def parseQuery(rtree, filename):
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# Find the intersecting rectangles
|
# Find the intersecting rectangles
|
||||||
def rangeQuery(rtree, window, results, node=None):
|
def range_query(rtree, window, results, node=None):
|
||||||
# At the root node
|
# At the root node
|
||||||
if node == None:
|
if node == None:
|
||||||
node = rtree[-1]
|
node = rtree[-1]
|
||||||
for n in node.list_of_mbrs:
|
for n in node.list_of_mbrs:
|
||||||
if window.intersects(n) or n.intersects(window):
|
if window.intersects(n) or n.intersects(window):
|
||||||
rangeQuery(rtree, window, results, rtree[n.id])
|
range_query(rtree, window, results, rtree[n.id])
|
||||||
# At an intermediate node
|
# At an intermediate node
|
||||||
elif node.leaf == 1:
|
elif node.leaf == 1:
|
||||||
for n in node.list_of_mbrs:
|
for n in node.list_of_mbrs:
|
||||||
if window.intersects(n) or n.intersects(window):
|
if window.intersects(n) or n.intersects(window):
|
||||||
rangeQuery(rtree, window, results, rtree[n.id])
|
range_query(rtree, window, results, rtree[n.id])
|
||||||
# At a leaf node
|
# At a leaf node
|
||||||
else:
|
else:
|
||||||
for mbr in node.list_of_mbrs:
|
for mbr in node.list_of_mbrs:
|
||||||
@@ -74,5 +55,5 @@ def rangeQuery(rtree, window, results, node=None):
|
|||||||
results.append(mbr)
|
results.append(mbr)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
rtree = parseRtree(sys.argv[1])
|
rtree = parse_tree(sys.argv[1])
|
||||||
parseQuery(rtree, sys.argv[2])
|
parse_query(rtree, sys.argv[2])
|
||||||
|
|||||||
Reference in New Issue
Block a user