Move mbr implementation to seperate file

This commit is contained in:
stefiosif
2022-04-14 17:58:28 +03:00
parent 2e2f7b02b6
commit 04319456dd
5 changed files with 119 additions and 161 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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])