Refactored paint_connect() and path_connect() to receive and return FlatCAMRTreeStorage objects. Updated unittests acordingly.
This commit is contained in:
@@ -1565,6 +1565,12 @@ class App(QtCore.QObject):
|
|||||||
app_obj.inform.emit("[error] Failed to open file: " + filename)
|
app_obj.inform.emit("[error] Failed to open file: " + filename)
|
||||||
app_obj.progress.emit(0)
|
app_obj.progress.emit(0)
|
||||||
raise IOError('Failed to open file: ' + filename)
|
raise IOError('Failed to open file: ' + filename)
|
||||||
|
except ParseError, e:
|
||||||
|
app_obj.inform.emit("[error] Failed to parse file: " + filename)
|
||||||
|
app_obj.progress.emit(0)
|
||||||
|
self.log.error(str(e))
|
||||||
|
raise
|
||||||
|
return
|
||||||
|
|
||||||
# Further parsing
|
# Further parsing
|
||||||
self.progress.emit(70) # TODO: Note the mixture of self and app_obj used here
|
self.progress.emit(70) # TODO: Note the mixture of self and app_obj used here
|
||||||
|
|||||||
148
camlib.py
148
camlib.py
@@ -6,6 +6,7 @@
|
|||||||
# MIT Licence #
|
# MIT Licence #
|
||||||
############################################################
|
############################################################
|
||||||
#from __future__ import division
|
#from __future__ import division
|
||||||
|
from scipy import optimize
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, dot, float32, \
|
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, dot, float32, \
|
||||||
@@ -337,7 +338,8 @@ class Geometry(object):
|
|||||||
break
|
break
|
||||||
return poly_cuts
|
return poly_cuts
|
||||||
|
|
||||||
def clear_polygon2(self, polygon, tooldia, seedpoint=None, overlap=0.15):
|
@staticmethod
|
||||||
|
def clear_polygon2(polygon, tooldia, seedpoint=None, overlap=0.15):
|
||||||
"""
|
"""
|
||||||
Creates geometry inside a polygon for a tool to cover
|
Creates geometry inside a polygon for a tool to cover
|
||||||
the whole area.
|
the whole area.
|
||||||
@@ -357,8 +359,12 @@ class Geometry(object):
|
|||||||
# Current buffer radius
|
# Current buffer radius
|
||||||
radius = tooldia / 2 * (1 - overlap)
|
radius = tooldia / 2 * (1 - overlap)
|
||||||
|
|
||||||
# The toolpaths
|
## The toolpaths
|
||||||
geoms = []
|
# Index first and last points in paths
|
||||||
|
def get_pts(o):
|
||||||
|
return [o.coords[0], o.coords[-1]]
|
||||||
|
geoms = FlatCAMRTreeStorage()
|
||||||
|
geoms.get_points = get_pts
|
||||||
|
|
||||||
# Path margin
|
# Path margin
|
||||||
path_margin = polygon.buffer(-tooldia / 2)
|
path_margin = polygon.buffer(-tooldia / 2)
|
||||||
@@ -367,7 +373,8 @@ class Geometry(object):
|
|||||||
if seedpoint is None:
|
if seedpoint is None:
|
||||||
seedpoint = path_margin.representative_point()
|
seedpoint = path_margin.representative_point()
|
||||||
|
|
||||||
# Grow from seed until outside the box.
|
# Grow from seed until outside the box. The polygons will
|
||||||
|
# never have an interior, so take the exterior LinearRing.
|
||||||
while 1:
|
while 1:
|
||||||
path = Point(seedpoint).buffer(radius).exterior
|
path = Point(seedpoint).buffer(radius).exterior
|
||||||
path = path.intersection(path_margin)
|
path = path.intersection(path_margin)
|
||||||
@@ -376,36 +383,30 @@ class Geometry(object):
|
|||||||
if path.is_empty:
|
if path.is_empty:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
geoms.append(path)
|
#geoms.append(path)
|
||||||
|
geoms.insert(path)
|
||||||
|
|
||||||
radius += tooldia * (1 - overlap)
|
radius += tooldia * (1 - overlap)
|
||||||
|
|
||||||
# Clean edges
|
# Clean inside edges of the original polygon
|
||||||
outer_edges = [x.exterior for x in autolist(polygon.buffer(-tooldia / 2))]
|
outer_edges = [x.exterior for x in autolist(polygon.buffer(-tooldia / 2))]
|
||||||
inner_edges = []
|
inner_edges = []
|
||||||
for x in autolist(polygon.buffer(-tooldia / 2)): # Over resulting polygons
|
for x in autolist(polygon.buffer(-tooldia / 2)): # Over resulting polygons
|
||||||
for y in x.interiors: # Over interiors of each polygon
|
for y in x.interiors: # Over interiors of each polygon
|
||||||
inner_edges.append(y)
|
inner_edges.append(y)
|
||||||
geoms += outer_edges + inner_edges
|
#geoms += outer_edges + inner_edges
|
||||||
|
for g in outer_edges + inner_edges:
|
||||||
|
geoms.insert(g)
|
||||||
|
|
||||||
# Optimization: Join paths
|
# Optimization connect touching paths
|
||||||
# TODO: Re-architecture?
|
|
||||||
# log.debug("Simplifying paths...")
|
|
||||||
g = Geometry()
|
|
||||||
g.solid_geometry = geoms
|
|
||||||
# g.path_connect()
|
|
||||||
#return g.flat_geometry
|
|
||||||
|
|
||||||
g.flatten(pathonly=True)
|
|
||||||
|
|
||||||
# Optimization: Reduce lifts
|
# Optimization: Reduce lifts
|
||||||
log.debug("Reducing tool lifts...")
|
log.debug("Reducing tool lifts...")
|
||||||
p = self.paint_connect(g.flat_geometry, polygon, tooldia)
|
p = Geometry.paint_connect(g.flat_geometry, polygon, tooldia)
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
|
||||||
#return geoms
|
|
||||||
|
|
||||||
def scale(self, factor):
|
def scale(self, factor):
|
||||||
"""
|
"""
|
||||||
Scales all of the object's geometry by a given factor. Override
|
Scales all of the object's geometry by a given factor. Override
|
||||||
@@ -428,7 +429,7 @@ class Geometry(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def paint_connect(geolist, boundary, tooldia):
|
def paint_connect(storage, boundary, tooldia):
|
||||||
"""
|
"""
|
||||||
Connects paths that results in a connection segment that is
|
Connects paths that results in a connection segment that is
|
||||||
within the paint area. This avoids unnecessary tool lifting.
|
within the paint area. This avoids unnecessary tool lifting.
|
||||||
@@ -442,34 +443,39 @@ class Geometry(object):
|
|||||||
def get_pts(o):
|
def get_pts(o):
|
||||||
return [o.coords[0], o.coords[-1]]
|
return [o.coords[0], o.coords[-1]]
|
||||||
|
|
||||||
storage = FlatCAMRTreeStorage()
|
# storage = FlatCAMRTreeStorage()
|
||||||
storage.get_points = get_pts
|
# storage.get_points = get_pts
|
||||||
|
#
|
||||||
for shape in geolist:
|
# for shape in geolist:
|
||||||
if shape is not None: # TODO: This shouldn't have happened.
|
# if shape is not None: # TODO: This shouldn't have happened.
|
||||||
# Make LlinearRings into linestrings otherwise
|
# # Make LlinearRings into linestrings otherwise
|
||||||
# When chaining the coordinates path is messed up.
|
# # When chaining the coordinates path is messed up.
|
||||||
storage.insert(LineString(shape))
|
# storage.insert(LineString(shape))
|
||||||
#storage.insert(shape)
|
# #storage.insert(shape)
|
||||||
|
|
||||||
## Iterate over geometry paths getting the nearest each time.
|
## Iterate over geometry paths getting the nearest each time.
|
||||||
optimized_paths = []
|
#optimized_paths = []
|
||||||
|
optimized_paths = FlatCAMRTreeStorage()
|
||||||
|
optimized_paths.get_points = get_pts
|
||||||
path_count = 0
|
path_count = 0
|
||||||
current_pt = (0, 0)
|
current_pt = (0, 0)
|
||||||
pt, geo = storage.nearest(current_pt)
|
pt, geo = storage.nearest(current_pt)
|
||||||
|
storage.remove(geo)
|
||||||
|
geo = LineString(geo)
|
||||||
|
current_pt = geo.coords[-1]
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
path_count += 1
|
path_count += 1
|
||||||
log.debug("Path %d" % path_count)
|
log.debug("Path %d" % path_count)
|
||||||
|
|
||||||
# Remove before modifying, otherwise
|
pt, candidate = storage.nearest(current_pt)
|
||||||
# deletion will fail.
|
storage.remove(candidate)
|
||||||
storage.remove(geo)
|
candidate = LineString(candidate)
|
||||||
|
|
||||||
# If last point in geometry is the nearest
|
# If last point in geometry is the nearest
|
||||||
# then reverse coordinates.
|
# then reverse coordinates.
|
||||||
if list(pt) == list(geo.coords[-1]):
|
if list(pt) == list(candidate.coords[-1]):
|
||||||
geo.coords = list(geo.coords)[::-1]
|
candidate.coords = list(candidate.coords)[::-1]
|
||||||
|
|
||||||
# Straight line from current_pt to pt.
|
# Straight line from current_pt to pt.
|
||||||
# Is the toolpath inside the geometry?
|
# Is the toolpath inside the geometry?
|
||||||
@@ -479,35 +485,35 @@ class Geometry(object):
|
|||||||
log.debug("Jump to path #%d is inside. Joining." % path_count)
|
log.debug("Jump to path #%d is inside. Joining." % path_count)
|
||||||
|
|
||||||
# Completely inside. Append...
|
# Completely inside. Append...
|
||||||
try:
|
geo.coords = list(geo.coords) + list(candidate.coords)
|
||||||
last = optimized_paths[-1]
|
# try:
|
||||||
last.coords = list(last.coords) + list(geo.coords)
|
# last = optimized_paths[-1]
|
||||||
except IndexError:
|
# last.coords = list(last.coords) + list(geo.coords)
|
||||||
optimized_paths.append(geo)
|
# except IndexError:
|
||||||
|
# optimized_paths.append(geo)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# Have to lift tool. End path.
|
# Have to lift tool. End path.
|
||||||
log.debug("Path #%d not within boundary. Next." % path_count)
|
log.debug("Path #%d not within boundary. Next." % path_count)
|
||||||
optimized_paths.append(geo)
|
#optimized_paths.append(geo)
|
||||||
|
optimized_paths.insert(geo)
|
||||||
|
geo = candidate
|
||||||
|
|
||||||
current_pt = geo.coords[-1]
|
current_pt = geo.coords[-1]
|
||||||
|
|
||||||
# Next
|
# Next
|
||||||
pt, geo = storage.nearest(current_pt)
|
#pt, geo = storage.nearest(current_pt)
|
||||||
|
|
||||||
except StopIteration: # Nothing left in storage.
|
except StopIteration: # Nothing left in storage.
|
||||||
pass
|
#pass
|
||||||
|
optimized_paths.insert(geo)
|
||||||
|
|
||||||
return optimized_paths
|
return optimized_paths
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def path_connect(pathlist, origin=(0, 0)):
|
def path_connect(storage, origin=(0, 0)):
|
||||||
"""
|
"""
|
||||||
Simplifies a list of paths by joining those whose ends touch.
|
|
||||||
The list of paths of generated from the geometry.flatten()
|
|
||||||
method which writes to geometry.flat_geometry. This list
|
|
||||||
if overwritten by this method with the optimized result.
|
|
||||||
|
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
@@ -515,18 +521,21 @@ class Geometry(object):
|
|||||||
## Index first and last points in paths
|
## Index first and last points in paths
|
||||||
def get_pts(o):
|
def get_pts(o):
|
||||||
return [o.coords[0], o.coords[-1]]
|
return [o.coords[0], o.coords[-1]]
|
||||||
|
#
|
||||||
storage = FlatCAMRTreeStorage()
|
# storage = FlatCAMRTreeStorage()
|
||||||
storage.get_points = get_pts
|
# storage.get_points = get_pts
|
||||||
|
#
|
||||||
for shape in pathlist:
|
# for shape in pathlist:
|
||||||
if shape is not None: # TODO: This shouldn't have happened.
|
# if shape is not None: # TODO: This shouldn't have happened.
|
||||||
storage.insert(shape)
|
# storage.insert(shape)
|
||||||
|
|
||||||
path_count = 0
|
path_count = 0
|
||||||
pt, geo = storage.nearest(origin)
|
pt, geo = storage.nearest(origin)
|
||||||
storage.remove(geo)
|
storage.remove(geo)
|
||||||
optimized_geometry = [geo]
|
#optimized_geometry = [geo]
|
||||||
|
optimized_geometry = FlatCAMRTreeStorage()
|
||||||
|
optimized_geometry.get_points = get_pts
|
||||||
|
#optimized_geometry.insert(geo)
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
path_count += 1
|
path_count += 1
|
||||||
@@ -536,6 +545,8 @@ class Geometry(object):
|
|||||||
_, left = storage.nearest(geo.coords[0])
|
_, left = storage.nearest(geo.coords[0])
|
||||||
print "left is", left
|
print "left is", left
|
||||||
|
|
||||||
|
# If left touches geo, remove left from original
|
||||||
|
# storage and append to geo.
|
||||||
if type(left) == LineString:
|
if type(left) == LineString:
|
||||||
if left.coords[0] == geo.coords[0]:
|
if left.coords[0] == geo.coords[0]:
|
||||||
storage.remove(left)
|
storage.remove(left)
|
||||||
@@ -560,6 +571,8 @@ class Geometry(object):
|
|||||||
_, right = storage.nearest(geo.coords[-1])
|
_, right = storage.nearest(geo.coords[-1])
|
||||||
print "right is", right
|
print "right is", right
|
||||||
|
|
||||||
|
# If right touches geo, remove left from original
|
||||||
|
# storage and append to geo.
|
||||||
if type(right) == LineString:
|
if type(right) == LineString:
|
||||||
if right.coords[0] == geo.coords[-1]:
|
if right.coords[0] == geo.coords[-1]:
|
||||||
storage.remove(right)
|
storage.remove(right)
|
||||||
@@ -581,23 +594,22 @@ class Geometry(object):
|
|||||||
geo.coords = list(left.coords) + list(geo.coords)
|
geo.coords = list(left.coords) + list(geo.coords)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# No matches on either end
|
# right is either a LinearRing or it does not connect
|
||||||
#optimized_geometry.append(geo)
|
# to geo (nothing left to connect to geo), so we continue
|
||||||
|
# with right as geo.
|
||||||
storage.remove(right)
|
storage.remove(right)
|
||||||
|
|
||||||
if type(right) == LinearRing:
|
if type(right) == LinearRing:
|
||||||
# Put the linearring at the beginning so it does
|
optimized_geometry.insert(right)
|
||||||
# not iterfere.
|
|
||||||
optimized_geometry = [right] + optimized_geometry
|
|
||||||
geo = optimized_geometry[-1]
|
|
||||||
print "right was LinearRing, getting previous"
|
|
||||||
else:
|
else:
|
||||||
optimized_geometry.append(right)
|
# Cannot exteng geo any further. Put it away.
|
||||||
|
optimized_geometry.insert(geo)
|
||||||
|
|
||||||
|
# Continue with right.
|
||||||
geo = right
|
geo = right
|
||||||
print "stored right, now geo<-right"
|
|
||||||
|
|
||||||
except StopIteration: # Nothing found in storage.
|
except StopIteration: # Nothing found in storage.
|
||||||
pass
|
optimized_geometry.insert(geo)
|
||||||
|
|
||||||
print path_count
|
print path_count
|
||||||
|
|
||||||
@@ -1838,7 +1850,7 @@ class Gerber (Geometry):
|
|||||||
|
|
||||||
## --- Buffered ---
|
## --- Buffered ---
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
geo = LineString(path).buffer(width/2)
|
geo = LineString(path).buffer(width / 2)
|
||||||
poly_buffer.append(geo)
|
poly_buffer.append(geo)
|
||||||
|
|
||||||
# --- Apply buffer ---
|
# --- Apply buffer ---
|
||||||
@@ -1850,7 +1862,7 @@ class Gerber (Geometry):
|
|||||||
except Exception, err:
|
except Exception, err:
|
||||||
#print traceback.format_exc()
|
#print traceback.format_exc()
|
||||||
log.error("PARSING FAILED. Line %d: %s" % (line_num, gline))
|
log.error("PARSING FAILED. Line %d: %s" % (line_num, gline))
|
||||||
raise
|
raise ParseError("%s\nLine %d: %s" % (repr(err), line_num, gline))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_flash_geometry(location, aperture):
|
def create_flash_geometry(location, aperture):
|
||||||
|
|||||||
@@ -4,6 +4,16 @@ from shapely.geometry import LineString, Polygon
|
|||||||
from shapely.ops import cascaded_union, unary_union
|
from shapely.ops import cascaded_union, unary_union
|
||||||
from matplotlib.pyplot import plot, subplot, show, cla, clf, xlim, ylim, title
|
from matplotlib.pyplot import plot, subplot, show, cla, clf, xlim, ylim, title
|
||||||
from camlib import *
|
from camlib import *
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
def mkstorage(paths):
|
||||||
|
def get_pts(o):
|
||||||
|
return [o.coords[0], o.coords[-1]]
|
||||||
|
storage = FlatCAMRTreeStorage()
|
||||||
|
storage.get_points = get_pts
|
||||||
|
for p in paths:
|
||||||
|
storage.insert(p)
|
||||||
|
return storage
|
||||||
|
|
||||||
|
|
||||||
def plotg2(geo, solid_poly=False, color="black", linestyle='solid'):
|
def plotg2(geo, solid_poly=False, color="black", linestyle='solid'):
|
||||||
@@ -75,19 +85,14 @@ class PaintConnectTest(PaintTestCase):
|
|||||||
tooldia = 1.0
|
tooldia = 1.0
|
||||||
|
|
||||||
print "--"
|
print "--"
|
||||||
result = Geometry.paint_connect(paths, self.boundary, tooldia)
|
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
for r in result:
|
for r in result:
|
||||||
print r
|
print r
|
||||||
|
|
||||||
self.assertEqual(len(result), 1)
|
self.assertEqual(len(result), 1)
|
||||||
|
|
||||||
# plotg(self.boundary, solid_poly=True)
|
|
||||||
# plotg(paths, color="red")
|
|
||||||
# plotg([r.buffer(tooldia / 2) for r in result], solid_poly=True)
|
|
||||||
# show()
|
|
||||||
# #cla()
|
|
||||||
# clf()
|
|
||||||
|
|
||||||
self.plot_summary_A(paths, tooldia, result, "WALK expected.")
|
self.plot_summary_A(paths, tooldia, result, "WALK expected.")
|
||||||
|
|
||||||
def test_no_jump1(self):
|
def test_no_jump1(self):
|
||||||
@@ -102,7 +107,9 @@ class PaintConnectTest(PaintTestCase):
|
|||||||
tooldia = 1.0
|
tooldia = 1.0
|
||||||
|
|
||||||
print "--"
|
print "--"
|
||||||
result = Geometry.paint_connect(paths, self.boundary, tooldia)
|
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
for r in result:
|
for r in result:
|
||||||
print r
|
print r
|
||||||
|
|
||||||
@@ -122,7 +129,9 @@ class PaintConnectTest(PaintTestCase):
|
|||||||
tooldia = 1.1
|
tooldia = 1.1
|
||||||
|
|
||||||
print "--"
|
print "--"
|
||||||
result = Geometry.paint_connect(paths, self.boundary, tooldia)
|
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
for r in result:
|
for r in result:
|
||||||
print r
|
print r
|
||||||
|
|
||||||
@@ -154,7 +163,9 @@ class PaintConnectTest2(PaintTestCase):
|
|||||||
tooldia = 1.0
|
tooldia = 1.0
|
||||||
|
|
||||||
print "--"
|
print "--"
|
||||||
result = Geometry.paint_connect(paths, self.boundary, tooldia)
|
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
for r in result:
|
for r in result:
|
||||||
print r
|
print r
|
||||||
|
|
||||||
@@ -170,6 +181,7 @@ class PaintConnectTest3(PaintTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.boundary = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
self.boundary = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||||
|
print "TEST w/ LinearRings"
|
||||||
|
|
||||||
def test_jump2(self):
|
def test_jump2(self):
|
||||||
print "Test: WALK Expected"
|
print "Test: WALK Expected"
|
||||||
@@ -184,7 +196,9 @@ class PaintConnectTest3(PaintTestCase):
|
|||||||
tooldia = 1.0
|
tooldia = 1.0
|
||||||
|
|
||||||
print "--"
|
print "--"
|
||||||
result = Geometry.paint_connect(paths, self.boundary, tooldia)
|
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
for r in result:
|
for r in result:
|
||||||
print r
|
print r
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,20 @@ from camlib import *
|
|||||||
from random import random
|
from random import random
|
||||||
|
|
||||||
|
|
||||||
|
def mkstorage(paths):
|
||||||
|
def get_pts(o):
|
||||||
|
return [o.coords[0], o.coords[-1]]
|
||||||
|
storage = FlatCAMRTreeStorage()
|
||||||
|
storage.get_points = get_pts
|
||||||
|
for p in paths:
|
||||||
|
storage.insert(p)
|
||||||
|
return storage
|
||||||
|
|
||||||
|
|
||||||
class PathConnectTest1(unittest.TestCase):
|
class PathConnectTest1(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
print "PathConnectTest1.setUp()"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_simple_connect(self):
|
def test_simple_connect(self):
|
||||||
@@ -18,8 +29,9 @@ class PathConnectTest1(unittest.TestCase):
|
|||||||
LineString([[1, 1], [2, 1]])
|
LineString([[1, 1], [2, 1]])
|
||||||
]
|
]
|
||||||
|
|
||||||
result = Geometry.path_connect(paths)
|
result = Geometry.path_connect(mkstorage(paths))
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
self.assertEqual(len(result), 1)
|
self.assertEqual(len(result), 1)
|
||||||
self.assertTrue(result[0].equals(LineString([[0, 0], [1, 1], [2, 1]])))
|
self.assertTrue(result[0].equals(LineString([[0, 0], [1, 1], [2, 1]])))
|
||||||
|
|
||||||
@@ -30,8 +42,9 @@ class PathConnectTest1(unittest.TestCase):
|
|||||||
LineString([[-0.5, 0.5], [0.5, 0]])
|
LineString([[-0.5, 0.5], [0.5, 0]])
|
||||||
]
|
]
|
||||||
|
|
||||||
result = Geometry.path_connect(paths)
|
result = Geometry.path_connect(mkstorage(paths))
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
self.assertEqual(len(result), 2)
|
self.assertEqual(len(result), 2)
|
||||||
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
||||||
self.assertEqual(len(matches), 1)
|
self.assertEqual(len(matches), 1)
|
||||||
@@ -46,8 +59,9 @@ class PathConnectTest1(unittest.TestCase):
|
|||||||
LineString([[1 + offset_x, 1 + offset_y], [2 + offset_x, 1 + offset_y]])
|
LineString([[1 + offset_x, 1 + offset_y], [2 + offset_x, 1 + offset_y]])
|
||||||
]
|
]
|
||||||
|
|
||||||
result = Geometry.path_connect(paths)
|
result = Geometry.path_connect(mkstorage(paths))
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
self.assertEqual(len(result), 1)
|
self.assertEqual(len(result), 1)
|
||||||
self.assertTrue(result[0].equals(LineString([[0 + offset_x, 0 + offset_y],
|
self.assertTrue(result[0].equals(LineString([[0 + offset_x, 0 + offset_y],
|
||||||
[1 + offset_x, 1 + offset_y],
|
[1 + offset_x, 1 + offset_y],
|
||||||
@@ -63,8 +77,9 @@ class PathConnectTest1(unittest.TestCase):
|
|||||||
LinearRing([[1, 1], [2, 2], [1, 3], [0, 2]])
|
LinearRing([[1, 1], [2, 2], [1, 3], [0, 2]])
|
||||||
]
|
]
|
||||||
|
|
||||||
result = Geometry.path_connect(paths)
|
result = Geometry.path_connect(mkstorage(paths))
|
||||||
|
|
||||||
|
result = list(result.get_objects())
|
||||||
self.assertEqual(len(result), 2)
|
self.assertEqual(len(result), 2)
|
||||||
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
||||||
self.assertEqual(len(matches), 1)
|
self.assertEqual(len(matches), 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user