Using FlatCAMRTreeStorage in DrawingTool.
This commit is contained in:
parent
e547386649
commit
c20c6b0abf
|
@ -0,0 +1 @@
|
||||||
|
*.pyc
|
222
FlatCAMDraw.py
222
FlatCAMDraw.py
|
@ -21,12 +21,52 @@ from rtree import index as rtindex
|
||||||
|
|
||||||
class DrawToolShape(object):
|
class DrawToolShape(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_pts(o):
|
||||||
|
"""
|
||||||
|
Returns a list of all points in the object, where
|
||||||
|
the object can be a Polygon, Not a polygon, or a list
|
||||||
|
of such. Search is done recursively.
|
||||||
|
|
||||||
|
:param: geometric object
|
||||||
|
:return: List of points
|
||||||
|
:rtype: list
|
||||||
|
"""
|
||||||
|
pts = []
|
||||||
|
|
||||||
|
## Iterable: descend into each item.
|
||||||
|
try:
|
||||||
|
for subo in o:
|
||||||
|
pts += DrawToolShape.get_pts(subo)
|
||||||
|
|
||||||
|
## Non-iterable
|
||||||
|
except TypeError:
|
||||||
|
|
||||||
|
## DrawToolShape: descend into .geo.
|
||||||
|
if isinstance(o, DrawToolShape):
|
||||||
|
pts += DrawToolShape.get_pts(o.geo)
|
||||||
|
|
||||||
|
## Descend into .exerior and .interiors
|
||||||
|
elif type(o) == Polygon:
|
||||||
|
pts += DrawToolShape.get_pts(o.exterior)
|
||||||
|
for i in o.interiors:
|
||||||
|
pts += DrawToolShape.get_pts(i)
|
||||||
|
|
||||||
|
## Has .coords: list them.
|
||||||
|
else:
|
||||||
|
pts += list(o.coords)
|
||||||
|
|
||||||
|
return pts
|
||||||
|
|
||||||
def __init__(self, geo=[]):
|
def __init__(self, geo=[]):
|
||||||
|
|
||||||
# Shapely type or list of such
|
# Shapely type or list of such
|
||||||
self.geo = geo
|
self.geo = geo
|
||||||
self.utility = False
|
self.utility = False
|
||||||
|
|
||||||
|
def get_all_points(self):
|
||||||
|
return DrawToolShape.get_pts(self)
|
||||||
|
|
||||||
|
|
||||||
class DrawToolUtilityShape(DrawToolShape):
|
class DrawToolUtilityShape(DrawToolShape):
|
||||||
|
|
||||||
|
@ -383,39 +423,26 @@ class FCPath(FCPolygon):
|
||||||
class FCSelect(DrawTool):
|
class FCSelect(DrawTool):
|
||||||
def __init__(self, draw_app):
|
def __init__(self, draw_app):
|
||||||
DrawTool.__init__(self, draw_app)
|
DrawTool.__init__(self, draw_app)
|
||||||
self.shape_buffer = self.draw_app.shape_buffer
|
self.storage = self.draw_app.storage
|
||||||
|
#self.shape_buffer = self.draw_app.shape_buffer
|
||||||
self.selected = self.draw_app.selected
|
self.selected = self.draw_app.selected
|
||||||
self.start_msg = "Click on geometry to select"
|
self.start_msg = "Click on geometry to select"
|
||||||
|
|
||||||
def click(self, point):
|
def click(self, point):
|
||||||
min_distance = Inf
|
_, closest_shape = self.storage.nearest(point)
|
||||||
closest_shape = None
|
|
||||||
|
|
||||||
for shape in self.shape_buffer:
|
if self.draw_app.key != 'control':
|
||||||
|
self.draw_app.selected = []
|
||||||
|
|
||||||
# Remove all if 'control' is not help
|
self.draw_app.set_selected(closest_shape)
|
||||||
if self.draw_app.key != 'control':
|
|
||||||
#shape["selected"] = False
|
|
||||||
self.draw_app.set_unselected(shape)
|
|
||||||
|
|
||||||
# TODO: Do this with rtree?
|
return ""
|
||||||
dist = Point(point).distance(cascaded_union(shape.geo))
|
|
||||||
if dist < min_distance:
|
|
||||||
closest_shape = shape
|
|
||||||
min_distance = dist
|
|
||||||
|
|
||||||
if closest_shape is not None:
|
|
||||||
#closest_shape["selected"] = True
|
|
||||||
self.draw_app.set_selected(closest_shape)
|
|
||||||
return "Shape selected."
|
|
||||||
|
|
||||||
return "Nothing selected."
|
|
||||||
|
|
||||||
|
|
||||||
class FCMove(FCShapeTool):
|
class FCMove(FCShapeTool):
|
||||||
def __init__(self, draw_app):
|
def __init__(self, draw_app):
|
||||||
FCShapeTool.__init__(self, draw_app)
|
FCShapeTool.__init__(self, draw_app)
|
||||||
self.shape_buffer = self.draw_app.shape_buffer
|
#self.shape_buffer = self.draw_app.shape_buffer
|
||||||
self.origin = None
|
self.origin = None
|
||||||
self.destination = None
|
self.destination = None
|
||||||
self.start_msg = "Click on reference point."
|
self.start_msg = "Click on reference point."
|
||||||
|
@ -565,12 +592,8 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
### Data
|
### Data
|
||||||
self.active_tool = None
|
self.active_tool = None
|
||||||
|
|
||||||
## List of shapes, None for removed ones. List
|
self.storage = FlatCAMDraw.make_storage()
|
||||||
## never decreases size.
|
self.utility = []
|
||||||
self.main_index = []
|
|
||||||
|
|
||||||
## List of shapes.
|
|
||||||
self.shape_buffer = []
|
|
||||||
|
|
||||||
## List of selected shapes.
|
## List of selected shapes.
|
||||||
self.selected = []
|
self.selected = []
|
||||||
|
@ -580,9 +603,9 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
|
|
||||||
self.key = None # Currently pressed key
|
self.key = None # Currently pressed key
|
||||||
|
|
||||||
def make_callback(tool):
|
def make_callback(thetool):
|
||||||
def f():
|
def f():
|
||||||
self.on_tool_select(tool)
|
self.on_tool_select(thetool)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
for tool in self.tools:
|
for tool in self.tools:
|
||||||
|
@ -624,11 +647,42 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
def activate(self):
|
def activate(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_shape(self, shape):
|
||||||
|
"""
|
||||||
|
Adds a shape to the shape storage.
|
||||||
|
|
||||||
|
:param shape: Shape to be added.
|
||||||
|
:type shape: DrawToolShape
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of DrawToolShape?
|
||||||
|
if isinstance(shape, list):
|
||||||
|
for subshape in shape:
|
||||||
|
self.add_shape(subshape)
|
||||||
|
return
|
||||||
|
|
||||||
|
assert isinstance(shape, DrawToolShape)
|
||||||
|
assert shape.geo is not None
|
||||||
|
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or not isinstance(shape.geo, list)
|
||||||
|
|
||||||
|
if isinstance(shape, DrawToolUtilityShape):
|
||||||
|
self.utility.append(shape)
|
||||||
|
else:
|
||||||
|
self.storage.insert(shape)
|
||||||
|
|
||||||
def deactivate(self):
|
def deactivate(self):
|
||||||
self.clear()
|
self.clear()
|
||||||
self.drawing_toolbar.setDisabled(True)
|
self.drawing_toolbar.setDisabled(True)
|
||||||
self.snap_toolbar.setDisabled(True) # TODO: Combine and move into tool
|
self.snap_toolbar.setDisabled(True) # TODO: Combine and move into tool
|
||||||
|
|
||||||
|
def delete_utility_geometry(self):
|
||||||
|
#for_deletion = [shape for shape in self.shape_buffer if shape.utility]
|
||||||
|
#for_deletion = [shape for shape in self.storage.get_objects() if shape.utility]
|
||||||
|
for_deletion = [shape for shape in self.utility]
|
||||||
|
for shape in for_deletion:
|
||||||
|
self.delete_shape(shape)
|
||||||
|
|
||||||
def cutpath(self):
|
def cutpath(self):
|
||||||
selected = self.get_selected()
|
selected = self.get_selected()
|
||||||
tools = selected[1:]
|
tools = selected[1:]
|
||||||
|
@ -653,7 +707,9 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.active_tool = None
|
self.active_tool = None
|
||||||
self.shape_buffer = []
|
#self.shape_buffer = []
|
||||||
|
self.selected = []
|
||||||
|
self.storage = FlatCAMDraw.make_storage()
|
||||||
self.replot()
|
self.replot()
|
||||||
|
|
||||||
def edit_fcgeometry(self, fcgeometry):
|
def edit_fcgeometry(self, fcgeometry):
|
||||||
|
@ -675,14 +731,13 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
geometry = [fcgeometry.solid_geometry]
|
geometry = [fcgeometry.solid_geometry]
|
||||||
|
|
||||||
# Delete contents of editor.
|
# Delete contents of editor.
|
||||||
self.shape_buffer = []
|
#self.shape_buffer = []
|
||||||
|
self.clear()
|
||||||
|
|
||||||
# Link shapes into editor.
|
# Link shapes into editor.
|
||||||
for shape in geometry:
|
for shape in geometry:
|
||||||
# self.shape_buffer.append({'geometry': shape,
|
#self.shape_buffer.append(DrawToolShape(geometry))
|
||||||
# # 'selected': False,
|
self.add_shape(DrawToolShape(shape.flatten()))
|
||||||
# 'utility': False})
|
|
||||||
self.shape_buffer.append(DrawToolShape(geometry))
|
|
||||||
|
|
||||||
self.replot()
|
self.replot()
|
||||||
self.drawing_toolbar.setDisabled(False)
|
self.drawing_toolbar.setDisabled(False)
|
||||||
|
@ -795,9 +850,7 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
if isinstance(geo, DrawToolShape) and geo.geo is not None:
|
if isinstance(geo, DrawToolShape) and geo.geo is not None:
|
||||||
|
|
||||||
# Remove any previous utility shape
|
# Remove any previous utility shape
|
||||||
for shape in self.shape_buffer:
|
self.delete_utility_geometry()
|
||||||
if shape.utility:
|
|
||||||
self.shape_buffer.remove(shape)
|
|
||||||
|
|
||||||
# Add the new utility shape
|
# Add the new utility shape
|
||||||
self.add_shape(geo)
|
self.add_shape(geo)
|
||||||
|
@ -841,9 +894,8 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
# TODO: ...?
|
# TODO: ...?
|
||||||
self.on_tool_select("select")
|
self.on_tool_select("select")
|
||||||
self.app.info("Cancelled.")
|
self.app.info("Cancelled.")
|
||||||
for_deletion = [shape for shape in self.shape_buffer if shape.utility]
|
|
||||||
for shape in for_deletion:
|
self.delete_utility_geometry()
|
||||||
self.shape_buffer.remove(shape)
|
|
||||||
|
|
||||||
self.replot()
|
self.replot()
|
||||||
self.select_btn.setChecked(True)
|
self.select_btn.setChecked(True)
|
||||||
|
@ -961,49 +1013,24 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
return plot_elements
|
return plot_elements
|
||||||
# self.canvas.auto_adjust_axes()
|
# self.canvas.auto_adjust_axes()
|
||||||
|
|
||||||
def add_shape(self, shape):
|
|
||||||
"""
|
|
||||||
Adds a shape to the shape buffer and the rtree index.
|
|
||||||
|
|
||||||
:param shape: Shape to be added.
|
|
||||||
:type shape: DrawToolShape
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
|
|
||||||
# List of DrawToolShape?
|
|
||||||
if isinstance(shape, list):
|
|
||||||
for subshape in shape:
|
|
||||||
self.add_shape(subshape)
|
|
||||||
return
|
|
||||||
|
|
||||||
assert isinstance(shape, DrawToolShape)
|
|
||||||
assert shape.geo is not None
|
|
||||||
assert (isinstance(shape.geo, list) and len(shape.geo) > 0) or not isinstance(shape.geo, list)
|
|
||||||
|
|
||||||
self.shape_buffer.append(shape)
|
|
||||||
|
|
||||||
# Do not add utility shapes to the index.
|
|
||||||
if not isinstance(shape, DrawToolUtilityShape):
|
|
||||||
self.main_index.append(shape)
|
|
||||||
self.add2index(len(self.main_index) - 1, shape)
|
|
||||||
|
|
||||||
def plot_all(self):
|
def plot_all(self):
|
||||||
self.app.log.debug("plot_all()")
|
self.app.log.debug("plot_all()")
|
||||||
self.axes.cla()
|
self.axes.cla()
|
||||||
for shape in self.shape_buffer:
|
#for shape in self.shape_buffer:
|
||||||
|
for shape in self.storage.get_objects():
|
||||||
if shape.geo is None: # TODO: This shouldn't have happened
|
if shape.geo is None: # TODO: This shouldn't have happened
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if shape.utility:
|
|
||||||
self.plot_shape(geometry=shape.geo, linespec='k--', linewidth=1)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if shape in self.selected:
|
if shape in self.selected:
|
||||||
self.plot_shape(geometry=shape.geo, linespec='k-', linewidth=2)
|
self.plot_shape(geometry=shape.geo, linespec='k-', linewidth=2)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.plot_shape(geometry=shape.geo)
|
self.plot_shape(geometry=shape.geo)
|
||||||
|
|
||||||
|
for shape in self.utility:
|
||||||
|
self.plot_shape(geometry=shape.geo, linespec='k--', linewidth=1)
|
||||||
|
continue
|
||||||
|
|
||||||
self.canvas.auto_adjust_axes()
|
self.canvas.auto_adjust_axes()
|
||||||
|
|
||||||
def add2index(self, id, geo):
|
def add2index(self, id, geo):
|
||||||
|
@ -1076,26 +1103,29 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
self.add_shape(self.active_tool.geometry)
|
self.add_shape(self.active_tool.geometry)
|
||||||
|
|
||||||
# Remove any utility shapes
|
# Remove any utility shapes
|
||||||
for shape in self.shape_buffer:
|
self.delete_utility_geometry()
|
||||||
if shape.utility:
|
|
||||||
self.shape_buffer.remove(shape)
|
|
||||||
|
|
||||||
self.replot()
|
self.replot()
|
||||||
self.active_tool = type(self.active_tool)(self)
|
self.active_tool = type(self.active_tool)(self)
|
||||||
|
|
||||||
def delete_shape(self, shape):
|
def delete_shape(self, shape):
|
||||||
try:
|
# try:
|
||||||
# Remove from index list
|
# # Remove from index list
|
||||||
shp_idx = self.main_index.index(shape)
|
# shp_idx = self.main_index.index(shape)
|
||||||
self.main_index[shp_idx] = None
|
# self.main_index[shp_idx] = None
|
||||||
|
#
|
||||||
|
# # Remove from rtree index
|
||||||
|
# self.remove_from_index(shp_idx, shape)
|
||||||
|
# except ValueError:
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
# if shape in self.shape_buffer:
|
||||||
|
# self.shape_buffer.remove(shape)
|
||||||
|
if shape in self.utility:
|
||||||
|
self.utility.remove(shape)
|
||||||
|
return
|
||||||
|
|
||||||
# Remove from rtree index
|
self.storage.remove(shape)
|
||||||
self.remove_from_index(shp_idx, shape)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if shape in self.shape_buffer:
|
|
||||||
self.shape_buffer.remove(shape)
|
|
||||||
|
|
||||||
if shape in self.selected:
|
if shape in self.selected:
|
||||||
self.selected.remove(shape)
|
self.selected.remove(shape)
|
||||||
|
@ -1105,6 +1135,15 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
self.axes = self.canvas.new_axes("draw")
|
self.axes = self.canvas.new_axes("draw")
|
||||||
self.plot_all()
|
self.plot_all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def make_storage():
|
||||||
|
|
||||||
|
## Shape storage.
|
||||||
|
storage = FlatCAMRTreeStorage()
|
||||||
|
storage.get_points = DrawToolShape.get_pts
|
||||||
|
|
||||||
|
return storage
|
||||||
|
|
||||||
def set_selected(self, shape):
|
def set_selected(self, shape):
|
||||||
|
|
||||||
# Remove and add to the end.
|
# Remove and add to the end.
|
||||||
|
@ -1134,14 +1173,13 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
### in the index.
|
### in the index.
|
||||||
if self.options["corner_snap"]:
|
if self.options["corner_snap"]:
|
||||||
try:
|
try:
|
||||||
bbox = self.rtree_index.nearest((x, y), objects=True).next().bbox
|
nearest_pt, shape = self.storage.nearest((x, y))
|
||||||
nearest_pt = (bbox[0], bbox[1])
|
|
||||||
|
|
||||||
nearest_pt_distance = distance((x, y), nearest_pt)
|
nearest_pt_distance = distance((x, y), nearest_pt)
|
||||||
if nearest_pt_distance <= self.options["snap_max"]:
|
if nearest_pt_distance <= self.options["snap_max"]:
|
||||||
snap_distance = nearest_pt_distance
|
snap_distance = nearest_pt_distance
|
||||||
snap_x, snap_y = nearest_pt
|
snap_x, snap_y = nearest_pt
|
||||||
except StopIteration:
|
except (StopIteration, AssertionError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
### Grid snap
|
### Grid snap
|
||||||
|
@ -1170,7 +1208,8 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
fcgeometry.solid_geometry = []
|
fcgeometry.solid_geometry = []
|
||||||
for shape in self.shape_buffer:
|
#for shape in self.shape_buffer:
|
||||||
|
for shape in self.storage.get_objects():
|
||||||
fcgeometry.solid_geometry.append(shape.geo)
|
fcgeometry.solid_geometry.append(shape.geo)
|
||||||
|
|
||||||
def union(self):
|
def union(self):
|
||||||
|
@ -1185,7 +1224,8 @@ class FlatCAMDraw(QtCore.QObject):
|
||||||
|
|
||||||
# Delete originals.
|
# Delete originals.
|
||||||
for shape in self.get_selected():
|
for shape in self.get_selected():
|
||||||
self.shape_buffer.remove(shape)
|
#self.shape_buffer.remove(shape)
|
||||||
|
self.delete_shape(shape) # TODO: This will crash
|
||||||
|
|
||||||
# Selected geometry is now gone!
|
# Selected geometry is now gone!
|
||||||
self.selected = []
|
self.selected = []
|
||||||
|
|
63
camlib.py
63
camlib.py
|
@ -138,6 +138,47 @@ class Geometry(object):
|
||||||
else:
|
else:
|
||||||
return self.solid_geometry.bounds
|
return self.solid_geometry.bounds
|
||||||
|
|
||||||
|
def flatten(self, geometry=None, reset=True):
|
||||||
|
if geometry is None:
|
||||||
|
geometry = self.solid_geometry
|
||||||
|
|
||||||
|
if reset:
|
||||||
|
self.flat_geometry = []
|
||||||
|
|
||||||
|
## If iterable, expand recursively.
|
||||||
|
try:
|
||||||
|
for geo in geometry:
|
||||||
|
self.flatten(geometry=geo, reset=False)
|
||||||
|
|
||||||
|
## Not iterable, do the actual indexing and add.
|
||||||
|
except TypeError:
|
||||||
|
if type(geometry) == Polygon:
|
||||||
|
self.flat_geometry.append(geometry)
|
||||||
|
|
||||||
|
return self.flat_geometry
|
||||||
|
|
||||||
|
def make2Dindex(self):
|
||||||
|
|
||||||
|
self.flatten()
|
||||||
|
|
||||||
|
def get_pts(o):
|
||||||
|
pts = []
|
||||||
|
if type(o) == Polygon:
|
||||||
|
g = o.exterior
|
||||||
|
pts += list(g.coords)
|
||||||
|
for i in o.interiors:
|
||||||
|
pts += list(i.coords)
|
||||||
|
else:
|
||||||
|
pts += list(o.coords)
|
||||||
|
return pts
|
||||||
|
|
||||||
|
idx = FlatCAMRTreeStorage()
|
||||||
|
idx.get_points = get_pts
|
||||||
|
for shape in self.flat_geometry:
|
||||||
|
idx.insert(shape)
|
||||||
|
return idx
|
||||||
|
|
||||||
|
|
||||||
def flatten_to_paths(self, geometry=None, reset=True):
|
def flatten_to_paths(self, geometry=None, reset=True):
|
||||||
"""
|
"""
|
||||||
Creates a list of non-iterable linear geometry elements and
|
Creates a list of non-iterable linear geometry elements and
|
||||||
|
@ -3188,11 +3229,14 @@ def distance(pt1, pt2):
|
||||||
|
|
||||||
|
|
||||||
class FlatCAMRTree(object):
|
class FlatCAMRTree(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.rti = rtindex.Index()
|
self.rti = rtindex.Index()
|
||||||
self.obj2points = []
|
self.obj2points = []
|
||||||
self.points2obj = []
|
self.points2obj = []
|
||||||
|
|
||||||
|
self.get_points = lambda go: go.coords
|
||||||
|
|
||||||
def grow_obj2points(self, idx):
|
def grow_obj2points(self, idx):
|
||||||
if len(self.obj2points) > idx:
|
if len(self.obj2points) > idx:
|
||||||
# len == 2, idx == 1, ok.
|
# len == 2, idx == 1, ok.
|
||||||
|
@ -3207,15 +3251,18 @@ class FlatCAMRTree(object):
|
||||||
self.grow_obj2points(objid)
|
self.grow_obj2points(objid)
|
||||||
self.obj2points[objid] = []
|
self.obj2points[objid] = []
|
||||||
|
|
||||||
for pt in obj.coords:
|
#for pt in obj.coords:
|
||||||
|
for pt in self.get_points(obj):
|
||||||
self.rti.insert(len(self.points2obj), (pt[0], pt[1], pt[0], pt[1]), obj=objid)
|
self.rti.insert(len(self.points2obj), (pt[0], pt[1], pt[0], pt[1]), obj=objid)
|
||||||
self.obj2points[objid].append(len(self.points2obj))
|
self.obj2points[objid].append(len(self.points2obj))
|
||||||
self.points2obj.append(objid)
|
self.points2obj.append(objid)
|
||||||
|
|
||||||
def remove_obj(self, objid, obj):
|
def remove_obj(self, objid, obj):
|
||||||
# Use all ptids to delete from index
|
# Use all ptids to delete from index
|
||||||
for i in range(len(self.obj2points[objid])):
|
#for i in range(len(self.obj2points[objid])):
|
||||||
pt = obj.coords[i]
|
for i, pt in enumerate(self.get_points(obj)):
|
||||||
|
#pt = obj.coords[i]
|
||||||
|
#pt = self.get_points(obj)[i]
|
||||||
self.rti.delete(self.obj2points[objid][i], (pt[0], pt[1], pt[0], pt[1]))
|
self.rti.delete(self.obj2points[objid][i], (pt[0], pt[1], pt[0], pt[1]))
|
||||||
|
|
||||||
def nearest(self, pt):
|
def nearest(self, pt):
|
||||||
|
@ -3241,9 +3288,19 @@ class FlatCAMRTreeStorage(FlatCAMRTree):
|
||||||
return (o for o in self.objects if o is not None)
|
return (o for o in self.objects if o is not None)
|
||||||
|
|
||||||
def nearest(self, pt):
|
def nearest(self, pt):
|
||||||
|
"""
|
||||||
|
Returns the nearest matching points and the object
|
||||||
|
it belongs to.
|
||||||
|
|
||||||
|
:param pt: Query point.
|
||||||
|
:return: (match_x, match_y), Object owner of
|
||||||
|
matching point.
|
||||||
|
:rtype: tuple
|
||||||
|
"""
|
||||||
tidx = super(FlatCAMRTreeStorage, self).nearest(pt)
|
tidx = super(FlatCAMRTreeStorage, self).nearest(pt)
|
||||||
return (tidx.bbox[0], tidx.bbox[1]), self.objects[tidx.object]
|
return (tidx.bbox[0], tidx.bbox[1]), self.objects[tidx.object]
|
||||||
|
|
||||||
|
|
||||||
class myO:
|
class myO:
|
||||||
def __init__(self, coords):
|
def __init__(self, coords):
|
||||||
self.coords = coords
|
self.coords = coords
|
||||||
|
|
Loading…
Reference in New Issue