OCC based tag line generation by extruding the edges cutting through a tag and retreiving the common with the tag solid.
This commit is contained in:
parent
9eca75e673
commit
b26a7ad794
|
@ -47,7 +47,7 @@ except AttributeError:
|
||||||
def translate(context, text, disambig=None):
|
def translate(context, text, disambig=None):
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
debugDressup = True
|
debugDressup = False
|
||||||
debugComponents = ['P0', 'P1', 'P2', 'P3']
|
debugComponents = ['P0', 'P1', 'P2', 'P3']
|
||||||
|
|
||||||
def debugPrint(comp, msg):
|
def debugPrint(comp, msg):
|
||||||
|
@ -59,7 +59,7 @@ def debugEdge(edge, prefix, comp = None):
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
pl = edge.valueAt(edge.LastParameter)
|
||||||
if comp:
|
if comp:
|
||||||
debugPrint(comp, "%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
debugPrint(comp, "%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
||||||
else:
|
elif debugDressup:
|
||||||
print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
||||||
|
|
||||||
def debugMarker(vector, label, color = None, radius = 0.5):
|
def debugMarker(vector, label, color = None, radius = 0.5):
|
||||||
|
@ -127,9 +127,6 @@ class Tag:
|
||||||
def top(self):
|
def top(self):
|
||||||
return self.z + self.actualHeight
|
return self.z + self.actualHeight
|
||||||
|
|
||||||
def centerLine(self):
|
|
||||||
return Part.LineSegment(self.originAt(self.bottom() - 1), self.originAt(self.top() + 1))
|
|
||||||
|
|
||||||
def createSolidsAt(self, z):
|
def createSolidsAt(self, z):
|
||||||
self.z = z
|
self.z = z
|
||||||
r1 = self.width / 2
|
r1 = self.width / 2
|
||||||
|
@ -160,288 +157,6 @@ class Tag:
|
||||||
if self.core:
|
if self.core:
|
||||||
self.core.translate(self.originAt(z))
|
self.core.translate(self.originAt(z))
|
||||||
|
|
||||||
class Intersection:
|
|
||||||
# An intersection with a tag has 4 markant points, where one might be optional.
|
|
||||||
#
|
|
||||||
# P1---P2 P1---P2 P2
|
|
||||||
# | | / \ /\
|
|
||||||
# | | / \ / \
|
|
||||||
# | | / \ / \
|
|
||||||
# ---P0 P3--- ---P0 P3--- ---P0 P3---
|
|
||||||
#
|
|
||||||
# If no intersection occured the Intersection can be viewed as being
|
|
||||||
# at P3 with no additional edges.
|
|
||||||
Pnone = 1
|
|
||||||
P0 = 2
|
|
||||||
P1 = 3
|
|
||||||
P2 = 4
|
|
||||||
P3 = 5
|
|
||||||
|
|
||||||
def __init__(self, tag):
|
|
||||||
self.tag = tag
|
|
||||||
self.state = self.Pnone
|
|
||||||
self.edges = []
|
|
||||||
self.tail = None
|
|
||||||
|
|
||||||
def isComplete(self):
|
|
||||||
return self.state == self.Pnone or self.state == self.P3
|
|
||||||
|
|
||||||
def hasEdges(self):
|
|
||||||
return self.state != self.Pnone
|
|
||||||
|
|
||||||
def moveEdgeToPlateau(self, edge):
|
|
||||||
if type(edge.Curve) is Part.Line or type(edge.Curve) is Part.LineSegment:
|
|
||||||
e = copy.copy(edge)
|
|
||||||
z = edge.valueAt(edge.FirstParameter).z
|
|
||||||
elif type(edge.Curve) is Part.Circle:
|
|
||||||
# it's an arc
|
|
||||||
e = copy.copy(edge)
|
|
||||||
z = edge.Curve.Center.z
|
|
||||||
else:
|
|
||||||
# it's a helix -> transform to arc
|
|
||||||
z = 0
|
|
||||||
p1 = PathGeom.xy(edge.valueAt(edge.FirstParameter))
|
|
||||||
p2 = PathGeom.xy(edge.valueAt((edge.FirstParameter + edge.LastParameter)/2))
|
|
||||||
p3 = PathGeom.xy(edge.valueAt(edge.LastParameter))
|
|
||||||
e = Part.Edge(Part.Arc(p1, p2, p3))
|
|
||||||
print("-------- moveEdgeToPlateau")
|
|
||||||
e.translate(Vector(0, 0, self.tag.top() - z))
|
|
||||||
return e
|
|
||||||
|
|
||||||
def intersectP0Core(self, edge):
|
|
||||||
debugPrint('P0', "----- P0-core")
|
|
||||||
|
|
||||||
i = self.tag.nextIntersectionClosestTo(edge, self.tag.core, edge.valueAt(edge.FirstParameter))
|
|
||||||
if i:
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
|
|
||||||
# if P0 and P1 are the same, we need to insert a segment for the rise
|
|
||||||
debugPrint('P0', "------- insert vertical rise (%s)" % i)
|
|
||||||
self.edges.append(Part.Edge(Part.LineSegment(i, FreeCAD.Vector(i.x, i.y, self.tag.top()))))
|
|
||||||
self.p1 = i
|
|
||||||
self.state = self.P1
|
|
||||||
return edge
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)):
|
|
||||||
debugPrint('P0', "------- consumed (%s)" % i)
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
else:
|
|
||||||
debugPrint('P0', "------- split at (%s)" % i)
|
|
||||||
e, tail = PathGeom.splitEdgeAt(edge, i)
|
|
||||||
self.p1 = e.valueAt(edge.LastParameter)
|
|
||||||
self.edges.extend(self.tag.mapEdgeToSolid(e, 'P0-core-1'))
|
|
||||||
self.state = self.P1
|
|
||||||
return tail
|
|
||||||
# no intersection, the entire edge fits between P0 and P1
|
|
||||||
debugPrint('P0', "------- no intersection")
|
|
||||||
self.edges.extend(self.tag.mapEdgeToSolid(edge, 'P0-core-2'))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def intersectP0(self, edge):
|
|
||||||
pf = edge.valueAt(edge.FirstParameter)
|
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
|
||||||
debugPrint('P0', "----- P0 %s(%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
|
|
||||||
if self.tag.core:
|
|
||||||
return self.intersectP0Core(edge)
|
|
||||||
|
|
||||||
# if we have no core the tip is the origin of the Tag
|
|
||||||
line = Part.Edge(self.tag.centerLine())
|
|
||||||
debugEdge(line, "------- center line", 'P0')
|
|
||||||
if type(edge.Curve) != Part.Circle and type(edge.Curve) != Part.Line:
|
|
||||||
p1 = edge.valueAt(edge.FirstParameter)
|
|
||||||
p2 = edge.valueAt((edge.FirstParameter + edge.LastParameter)/2)
|
|
||||||
p3 = edge.valueAt(edge.LastParameter)
|
|
||||||
p1.z = 0
|
|
||||||
p2.z = 0
|
|
||||||
p3.z = 0
|
|
||||||
arc = Part.Edge(Part.Arc(p1, p2, p3))
|
|
||||||
aps = DraftGeomUtils.findIntersection(line, arc)
|
|
||||||
paramScale = (edge.LastParameter - edge.FirstParameter) / (arc.LastParameter - arc.FirstParameter)
|
|
||||||
for p in aps:
|
|
||||||
print("%s - p=%.2f" % (p, arc.Curve.parameter(p)))
|
|
||||||
i = [edge.valueAt(arc.Curve.parameter(p) * paramScale) for p in aps]
|
|
||||||
else:
|
|
||||||
i = DraftGeomUtils.findIntersection(line, edge)
|
|
||||||
#i = line.Curve.intersect(edge)
|
|
||||||
if i:
|
|
||||||
debugPrint('P0', '------- P0 split @ (%.2f, %.2f, %.2f)' % (i[0].x, i[0].y, i[0].z))
|
|
||||||
if PathGeom.pointsCoincide(i[0], edge.valueAt(edge.LastParameter)):
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
else:
|
|
||||||
e, tail = PathGeom.splitEdgeAt(edge, i[0])
|
|
||||||
self.state = self.P2 # P1 and P2 are identical for triangular tags
|
|
||||||
self.p1 = i[0]
|
|
||||||
self.p2 = i[0]
|
|
||||||
else:
|
|
||||||
debugPrint('P0', '------- P0 no intersect')
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
self.edges.extend(self.tag.mapEdgeToSolid(e, 'P0'))
|
|
||||||
return tail
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def intersectP1(self, edge):
|
|
||||||
pf = edge.valueAt(edge.FirstParameter)
|
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
|
||||||
debugPrint('P1', "----- P1 (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
i = self.tag.nextIntersectionClosestTo(edge, self.tag.core, edge.valueAt(edge.LastParameter))
|
|
||||||
if i:
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
|
|
||||||
debugPrint('P1', "----- P1 edge too short")
|
|
||||||
#self.edges.extend(self.tag.mapEdgeToSolid(edge, 'P1'))
|
|
||||||
self.edges.append(self.moveEdgeToPlateau(edge))
|
|
||||||
return None
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)):
|
|
||||||
debugPrint('P1', "----- P1 edge at end")
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
else:
|
|
||||||
debugPrint('P1', "----- P1 split edge @ (%.2f, %.2f, %.2f)" % (i.x, i.y, i.z))
|
|
||||||
e, tail = PathGeom.splitEdgeAt(edge, i)
|
|
||||||
f = e.valueAt(e.FirstParameter)
|
|
||||||
l = e.valueAt(e.LastParameter)
|
|
||||||
debugPrint('P1', "----- P1 (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (f.x, f.y, f.z, l.x, l.y, l.z))
|
|
||||||
self.p2 = e.valueAt(e.LastParameter)
|
|
||||||
self.state = self.P2
|
|
||||||
else:
|
|
||||||
debugPrint('P1', "----- P1 no intersect")
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
f = e.valueAt(e.FirstParameter)
|
|
||||||
l = e.valueAt(e.LastParameter)
|
|
||||||
debugPrint('P1', "----- P1 (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (f.x, f.y, f.z, l.x, l.y, l.z))
|
|
||||||
self.edges.append(self.moveEdgeToPlateau(e))
|
|
||||||
return tail
|
|
||||||
|
|
||||||
def intersectP2(self, edge):
|
|
||||||
pf = edge.valueAt(edge.FirstParameter)
|
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
|
||||||
debugPrint('P2', "----- P2 (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
i = self.tag.nextIntersectionClosestTo(edge, self.tag.solid, edge.valueAt(edge.LastParameter))
|
|
||||||
if i:
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
|
|
||||||
debugPrint('P2', "------- insert exit plunge (%s)" % i)
|
|
||||||
self.edges.append(Part.Edge(Part.LineSegment(FreeCAD.Vector(i.x, i.y, self.tag.top()), i)))
|
|
||||||
e = None
|
|
||||||
tail = edge
|
|
||||||
elif PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)):
|
|
||||||
debugPrint('P2', "------- entire segment added (%s)" % i)
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
else:
|
|
||||||
e, tail = PathGeom.splitEdgeAt(edge, i)
|
|
||||||
if tail:
|
|
||||||
pf = tail.valueAt(tail.FirstParameter)
|
|
||||||
pl = tail.valueAt(tail.LastParameter)
|
|
||||||
debugPrint('P3', "----- P3 (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
else:
|
|
||||||
debugPrint('P3', "----- P3 (---)")
|
|
||||||
self.state = self.P3
|
|
||||||
self.tail = tail
|
|
||||||
else:
|
|
||||||
debugPrint('P2', "----- P2 no intersection")
|
|
||||||
e = edge
|
|
||||||
tail = None
|
|
||||||
if e:
|
|
||||||
pf = e.valueAt(e.FirstParameter)
|
|
||||||
pl = e.valueAt(e.LastParameter)
|
|
||||||
s = 'P2' if self.state == self.P2 else 'P3'
|
|
||||||
debugPrint(s, "----- %s (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (s, pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
self.edges.extend(self.tag.mapEdgeToSolid(e, 'P2'))
|
|
||||||
return tail
|
|
||||||
|
|
||||||
def intersect(self, edge):
|
|
||||||
#print("")
|
|
||||||
#print(" >>> (%s - %s)" % (edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter)))
|
|
||||||
if edge and self.state == self.P0:
|
|
||||||
edge = self.intersectP0(edge)
|
|
||||||
if edge and self.state == self.P1:
|
|
||||||
edge = self.intersectP1(edge)
|
|
||||||
if edge and self.state == self.P2:
|
|
||||||
edge = self.intersectP2(edge)
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def mapEdgeToSolid(self, edge, label):
|
|
||||||
pf = edge.valueAt(edge.FirstParameter)
|
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
|
||||||
print("--------- mapEdgeToSolid-%s: %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (label, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
|
|
||||||
p1a = edge.valueAt(edge.FirstParameter)
|
|
||||||
p1a.z = self.bottom()
|
|
||||||
p1b = FreeCAD.Vector(p1a.x, p1a.y, self.height * 1.01)
|
|
||||||
e1 = Part.Edge(Part.LineSegment(p1a, p1b))
|
|
||||||
p1 = self.nextIntersectionClosestTo(e1, self.solid, p1b) # top most intersection
|
|
||||||
print("---------- p1: (%s %s) -> %s %d" % (p1a, p1b, p1, self.solid.isInside(p1, 0.0000001, True)))
|
|
||||||
if not p1:
|
|
||||||
raise Exception('no p1')
|
|
||||||
return []
|
|
||||||
|
|
||||||
p2a = edge.valueAt(edge.LastParameter)
|
|
||||||
p2a.z = self.bottom()
|
|
||||||
p2b = FreeCAD.Vector(p2a.x, p2a.y, self.height * 1.01)
|
|
||||||
e2 = Part.Edge(Part.LineSegment(p2a, p2b))
|
|
||||||
p2 = self.nextIntersectionClosestTo(e2, self.solid, p2b) # top most intersection
|
|
||||||
if not p2:
|
|
||||||
p1 = edge.valueAt(edge.FirstParameter)
|
|
||||||
p2 = edge.valueAt(edge.LastParameter)
|
|
||||||
print("---------- p1: %d%d" % (self.solid.isInside(p1, 0.0000001, True), self.solid.isInside(p1, 0.0000001, False)))
|
|
||||||
print("---------- p2: %d%d" % (self.solid.isInside(p2, 0.0000001, True), self.solid.isInside(p2, 0.0000001, False)))
|
|
||||||
#if not self.solid.isInside(p1, 0.0000001, False):
|
|
||||||
# p1 is on the solid -
|
|
||||||
raise Exception('no p2')
|
|
||||||
return []
|
|
||||||
|
|
||||||
print("---------- %s - %s" % (p1, p2))
|
|
||||||
print("---------- (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (p2.x, p2.y, p2.z, p1.x, p1.y, p1.z))
|
|
||||||
|
|
||||||
if PathGeom.pointsCoincide(p1, p2):
|
|
||||||
return []
|
|
||||||
|
|
||||||
if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment:
|
|
||||||
e = Part.Edge(Part.LineSegment(p1, p2))
|
|
||||||
debugEdge(e, "-------- >>")
|
|
||||||
return [e]
|
|
||||||
|
|
||||||
m = FreeCAD.Matrix()
|
|
||||||
m.unity()
|
|
||||||
pd = p2 - p1
|
|
||||||
|
|
||||||
if type(edge.Curve) == Part.Circle:
|
|
||||||
m.A32 = pd.z / pd.y
|
|
||||||
m.A34 = - m.A32
|
|
||||||
if pd.z < 0:
|
|
||||||
m.A34 *= p2.y
|
|
||||||
else:
|
|
||||||
m.A34 *= p1.y
|
|
||||||
e = edge.transformGeometry(m).Edges[0]
|
|
||||||
debugEdge(e, "-------- >>")
|
|
||||||
return [e]
|
|
||||||
|
|
||||||
# it's already a helix, just need to lift it to the plateau
|
|
||||||
m.A33 = pd.z / (edge.valueAt(edge.LastParameter).z - edge.valueAt(edge.FirstParameter).z)
|
|
||||||
m.A34 = (1 - m.A33)
|
|
||||||
if pd.z < 0:
|
|
||||||
m.A34 *= edge.valueAt(edge.LastParameter).z
|
|
||||||
else:
|
|
||||||
m.A34 *= edge.valueAt(edge.FirstParameter).z
|
|
||||||
|
|
||||||
#print
|
|
||||||
pf = edge.valueAt(edge.FirstParameter)
|
|
||||||
pl = edge.valueAt(edge.LastParameter)
|
|
||||||
#print("(%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f): %.2f" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z, m.A33))
|
|
||||||
#print("**** %.2f %.2f (%.2f - %.2f)" % (pd.z, p2a.z-p1a.z, p2a.z, p1a.z))
|
|
||||||
e = edge.transformGeometry(m).Edges[0]
|
|
||||||
pf = e.valueAt(e.FirstParameter)
|
|
||||||
pl = e.valueAt(e.LastParameter)
|
|
||||||
#print("(%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
#raise Exception("mensch")
|
|
||||||
debugEdge(e, "-------- >>")
|
|
||||||
return [e]
|
|
||||||
|
|
||||||
|
|
||||||
def filterIntersections(self, pts, face):
|
def filterIntersections(self, pts, face):
|
||||||
if type(face.Surface) == Part.Cone or type(face.Surface) == Part.Cylinder:
|
if type(face.Surface) == Part.Cone or type(face.Surface) == Part.Cylinder:
|
||||||
#print("it's a cone/cylinder, checking z")
|
#print("it's a cone/cylinder, checking z")
|
||||||
|
@ -451,7 +166,7 @@ class Tag:
|
||||||
c = face.Edges[0].Curve
|
c = face.Edges[0].Curve
|
||||||
if (type(c) == Part.Circle):
|
if (type(c) == Part.Circle):
|
||||||
return filter(lambda pt: (pt - c.Center).Length <= c.Radius or PathGeom.isRoughly((pt - c.Center).Length, c.Radius), pts)
|
return filter(lambda pt: (pt - c.Center).Length <= c.Radius or PathGeom.isRoughly((pt - c.Center).Length, c.Radius), pts)
|
||||||
print("==== we got a %s" % face.Surface)
|
#print("==== we got a %s" % face.Surface)
|
||||||
|
|
||||||
def isPointOnEdge(self, pt, edge):
|
def isPointOnEdge(self, pt, edge):
|
||||||
param = edge.Curve.parameter(pt)
|
param = edge.Curve.parameter(pt)
|
||||||
|
@ -461,13 +176,11 @@ class Tag:
|
||||||
return True
|
return True
|
||||||
if PathGeom.isRoughly(edge.FirstParameter, param) or PathGeom.isRoughly(edge.LastParameter, param):
|
if PathGeom.isRoughly(edge.FirstParameter, param) or PathGeom.isRoughly(edge.LastParameter, param):
|
||||||
return True
|
return True
|
||||||
print("-------- X %.2f <= %.2f <=%.2f (%.2f, %.2f, %.2f) %.2f:%.2f" % (edge.FirstParameter, param, edge.LastParameter, pt.x, pt.y, pt.z, edge.Curve.parameter(edge.valueAt(edge.FirstParameter)), edge.Curve.parameter(edge.valueAt(edge.LastParameter))))
|
#print("-------- X %.2f <= %.2f <=%.2f (%.2f, %.2f, %.2f) %.2f:%.2f" % (edge.FirstParameter, param, edge.LastParameter, pt.x, pt.y, pt.z, edge.Curve.parameter(edge.valueAt(edge.FirstParameter)), edge.Curve.parameter(edge.valueAt(edge.LastParameter))))
|
||||||
p1 = edge.Vertexes[0]
|
p1 = edge.Vertexes[0]
|
||||||
f1 = edge.Curve.parameter(FreeCAD.Vector(p1.X, p1.Y, p1.Z))
|
f1 = edge.Curve.parameter(FreeCAD.Vector(p1.X, p1.Y, p1.Z))
|
||||||
p2 = edge.Vertexes[1]
|
p2 = edge.Vertexes[1]
|
||||||
f2 = edge.Curve.parameter(FreeCAD.Vector(p2.X, p2.Y, p2.Z))
|
f2 = edge.Curve.parameter(FreeCAD.Vector(p2.X, p2.Y, p2.Z))
|
||||||
print("-------- (%.2f, %.2f, %.2f):%.2f (%.2f, %.2f, %.2f):%.2f" % (p1.X, p1.Y, p1.Z, f1, p2.X, p2.Y, p2.Z, f2))
|
|
||||||
print("-------- %s %s" % (edge.Placement, edge.Orientation))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -475,62 +188,144 @@ class Tag:
|
||||||
ef = edge.valueAt(edge.FirstParameter)
|
ef = edge.valueAt(edge.FirstParameter)
|
||||||
em = edge.valueAt((edge.FirstParameter+edge.LastParameter)/2)
|
em = edge.valueAt((edge.FirstParameter+edge.LastParameter)/2)
|
||||||
el = edge.valueAt(edge.LastParameter)
|
el = edge.valueAt(edge.LastParameter)
|
||||||
print("-------- intersect %s (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) refp=(%.2f, %.2f, %.2f)" % (type(edge.Curve), ef.x, ef.y, ef.z, em.x, em.y, em.z, el.x, el.y, el.z, refPt.x, refPt.y, refPt.z))
|
#print("-------- intersect %s (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) refp=(%.2f, %.2f, %.2f)" % (type(edge.Curve), ef.x, ef.y, ef.z, em.x, em.y, em.z, el.x, el.y, el.z, refPt.x, refPt.y, refPt.z))
|
||||||
|
|
||||||
pts = []
|
pts = []
|
||||||
for index, face in enumerate(solid.Faces):
|
for index, face in enumerate(solid.Faces):
|
||||||
i = edge.Curve.intersect(face.Surface)[0]
|
i = edge.Curve.intersect(face.Surface)[0]
|
||||||
print i
|
#print i
|
||||||
ps = self.filterIntersections([FreeCAD.Vector(p.X, p.Y, p.Z) for p in i], face)
|
ps = self.filterIntersections([FreeCAD.Vector(p.X, p.Y, p.Z) for p in i], face)
|
||||||
pts.extend(filter(lambda pt: self.isPointOnEdge(pt, edge), ps))
|
pts.extend(filter(lambda pt: self.isPointOnEdge(pt, edge), ps))
|
||||||
if len(ps) != len(filter(lambda pt: self.isPointOnEdge(pt, edge), ps)):
|
if len(ps) != len(filter(lambda pt: self.isPointOnEdge(pt, edge), ps)):
|
||||||
filtered = filter(lambda pt: self.isPointOnEdge(pt, edge), ps)
|
filtered = filter(lambda pt: self.isPointOnEdge(pt, edge), ps)
|
||||||
print("-------- ++ len(ps)=%d, len(filtered)=%d" % (len(ps), len(filtered)))
|
#print("-------- ++ len(ps)=%d, len(filtered)=%d" % (len(ps), len(filtered)))
|
||||||
for p in ps:
|
for p in ps:
|
||||||
included = '+' if p in filtered else '-'
|
included = '+' if p in filtered else '-'
|
||||||
print("-------- %s (%.2f, %.2f, %.2f)" % (included, p.x, p.y, p.z))
|
#print("-------- %s (%.2f, %.2f, %.2f)" % (included, p.x, p.y, p.z))
|
||||||
if pts:
|
if pts:
|
||||||
closest = sorted(pts, key=lambda pt: (pt - refPt).Length)[0]
|
closest = sorted(pts, key=lambda pt: (pt - refPt).Length)[0]
|
||||||
for p in pts:
|
#for p in pts:
|
||||||
print("-------- - intersect pt : (%.2f, %.2f, %.2f)" % (p.x, p.y, p.z))
|
# print("-------- - intersect pt : (%.2f, %.2f, %.2f)" % (p.x, p.y, p.z))
|
||||||
print("-------- -> (%.2f, %.2f, %.2f)" % (closest.x, closest.y, closest.z))
|
#print("-------- -> (%.2f, %.2f, %.2f)" % (closest.x, closest.y, closest.z))
|
||||||
return closest
|
return closest
|
||||||
|
|
||||||
print("-------- -> None")
|
#print("-------- -> None")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def intersect(self, edge, check = True):
|
def intersects(self, edge, param):
|
||||||
print("--- intersect")
|
|
||||||
inters = self.Intersection(self)
|
|
||||||
if check:
|
|
||||||
if edge.valueAt(edge.FirstParameter).z < self.top() or edge.valueAt(edge.LastParameter).z < self.top():
|
if edge.valueAt(edge.FirstParameter).z < self.top() or edge.valueAt(edge.LastParameter).z < self.top():
|
||||||
i = self.nextIntersectionClosestTo(edge, self.solid, edge.valueAt(edge.FirstParameter))
|
return self.nextIntersectionClosestTo(edge, self.solid, edge.valueAt(param))
|
||||||
if i:
|
return None
|
||||||
print("---- (%.2f, %.2f, %.2f)" % (i.x, i.y, i.z))
|
|
||||||
inters.state = self.Intersection.P0
|
class MapWireToTag:
|
||||||
inters.p0 = i
|
def __init__(self, edge, tag, i):
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)):
|
self.tag = tag
|
||||||
print("---- entire edge consumed.")
|
if PathGeom.pointsCoincide(edge.valueAt(edge.FirstParameter), i):
|
||||||
inters.edges.append(edge)
|
|
||||||
return inters
|
|
||||||
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
|
|
||||||
print("---- nothing of edge consumed.")
|
|
||||||
tail = edge
|
tail = edge
|
||||||
|
self.commands = []
|
||||||
|
elif PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), i):
|
||||||
|
debugEdge(edge, '++++++++ .')
|
||||||
|
self.commands = PathGeom.cmdsForEdge(edge)
|
||||||
|
tail = None
|
||||||
else:
|
else:
|
||||||
print("---- split edge")
|
|
||||||
e, tail = PathGeom.splitEdgeAt(edge, i)
|
e, tail = PathGeom.splitEdgeAt(edge, i)
|
||||||
inters.edges.append(e)
|
debugEdge(e, '++++++++ .')
|
||||||
return inters.intersect(tail)
|
self.commands = PathGeom.cmdsForEdge(e)
|
||||||
|
self.tail = tail
|
||||||
|
self.edges = []
|
||||||
|
self.entry = i
|
||||||
|
self.complete = False
|
||||||
|
self.wire = None
|
||||||
|
|
||||||
|
def addEdge(self, edge):
|
||||||
|
if self.wire:
|
||||||
|
self.wire.add(edge)
|
||||||
else:
|
else:
|
||||||
print("---- No intersection found.")
|
self.wire = Part.Wire(edge)
|
||||||
|
|
||||||
|
def needToFlipEdge(self, edge, p):
|
||||||
|
if PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), p):
|
||||||
|
return True, edge.valueAt(edge.FirstParameter)
|
||||||
|
return False, edge.valueAt(edge.LastParameter)
|
||||||
|
|
||||||
|
def cleanupEdges(self, edges):
|
||||||
|
# first remove all internal struts
|
||||||
|
inputEdges = copy.copy(edges)
|
||||||
|
plinths = []
|
||||||
|
for e in edges:
|
||||||
|
p1 = e.valueAt(e.FirstParameter)
|
||||||
|
p2 = e.valueAt(e.LastParameter)
|
||||||
|
if p1.x == p2.x and p1.y == p2.y:
|
||||||
|
if not (PathGeom.edgeConnectsTo(e, self.entry) or PathGeom.edgeConnectsTo(e, self.exit)):
|
||||||
|
inputEdges.remove(e)
|
||||||
|
if p1.z > p2.z:
|
||||||
|
plinths.append(p2)
|
||||||
else:
|
else:
|
||||||
print("---- Fly by")
|
plinths.append(p1)
|
||||||
|
# remove all edges that are connected to the plinths of the (former) internal struts
|
||||||
|
# including the edge that connects the entry and exit point directly
|
||||||
|
for e in copy.copy(inputEdges):
|
||||||
|
if PathGeom.edgeConnectsTo(e, self.entry) and PathGeom.edgeConnectsTo(e, self.exit):
|
||||||
|
inputEdges.remove(e)
|
||||||
|
continue
|
||||||
|
for p in plinths:
|
||||||
|
if PathGeom.edgeConnectsTo(e, p):
|
||||||
|
inputEdges.remove(e)
|
||||||
|
break
|
||||||
|
# the remaining edges form walk around the tag
|
||||||
|
# they need to be ordered and potentially flipped though
|
||||||
|
outputEdges = []
|
||||||
|
p = self.entry
|
||||||
|
lastP = p
|
||||||
|
while inputEdges:
|
||||||
|
for e in inputEdges:
|
||||||
|
p1 = e.valueAt(e.FirstParameter)
|
||||||
|
p2 = e.valueAt(e.LastParameter)
|
||||||
|
if PathGeom.pointsCoincide(p1, p):
|
||||||
|
outputEdges.append((e,False))
|
||||||
|
inputEdges.remove(e)
|
||||||
|
lastP = p
|
||||||
|
p = p2
|
||||||
|
debugEdge(e, ">>>>> no flip")
|
||||||
|
break
|
||||||
|
elif PathGeom.pointsCoincide(p2, p):
|
||||||
|
outputEdges.append((e,True))
|
||||||
|
inputEdges.remove(e)
|
||||||
|
lastP = p
|
||||||
|
p = p1
|
||||||
|
debugEdge(e, ">>>>> flip")
|
||||||
|
break
|
||||||
|
#else:
|
||||||
|
# debugEdge(e, "<<<<< (%.2f, %.2f, %.2f)" % (p.x, p.y, p.z))
|
||||||
|
if lastP == p:
|
||||||
|
raise ValueError("No connection to %s" % (p))
|
||||||
|
#else:
|
||||||
|
# print("xxxxxx (%.2f, %.2f, %.2f)" % (p.x, p.y, p.z))
|
||||||
|
return outputEdges
|
||||||
|
|
||||||
|
def add(self, edge):
|
||||||
|
self.tail = None
|
||||||
|
if self.tag.solid.isInside(edge.valueAt(edge.LastParameter), 0.000001, True):
|
||||||
|
self.addEdge(edge)
|
||||||
else:
|
else:
|
||||||
print("---- skipped")
|
i = self.tag.intersects(edge, edge.LastParameter)
|
||||||
# if we get here there is no intersection with the tag
|
if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)):
|
||||||
inters.state = self.Intersection.Pnone
|
self.tail = edge
|
||||||
inters.tail = edge
|
else:
|
||||||
return inters
|
e, tail = PathGeom.splitEdgeAt(edge, i)
|
||||||
|
self.addEdge(e)
|
||||||
|
self.tail = tail
|
||||||
|
self.exit = i
|
||||||
|
shell = self.wire.extrude(FreeCAD.Vector(0, 0, 10))
|
||||||
|
face = shell.common(self.tag.solid)
|
||||||
|
|
||||||
|
for e,flip in self.cleanupEdges(face.Edges):
|
||||||
|
debugEdge(e, '++++++++ %s' % ('.' if not flip else '@'))
|
||||||
|
self.commands.extend(PathGeom.cmdsForEdge(e, flip, False))
|
||||||
|
self.complete = True
|
||||||
|
|
||||||
|
def mappingComplete(self):
|
||||||
|
return self.complete
|
||||||
|
|
||||||
class PathData:
|
class PathData:
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
|
@ -548,36 +343,11 @@ class PathData:
|
||||||
bottom = [e for e in edges if e.Vertexes[0].Point.z == minZ and e.Vertexes[1].Point.z == minZ]
|
bottom = [e for e in edges if e.Vertexes[0].Point.z == minZ and e.Vertexes[1].Point.z == minZ]
|
||||||
wire = Part.Wire(bottom)
|
wire = Part.Wire(bottom)
|
||||||
if wire.isClosed():
|
if wire.isClosed():
|
||||||
#return Part.Wire(self.sortedBase(bottom))
|
|
||||||
return wire
|
return wire
|
||||||
# if we get here there are already holding tags, or we're not looking at a profile
|
# if we get here there are already holding tags, or we're not looking at a profile
|
||||||
# let's try and insert the missing pieces - another day
|
# let's try and insert the missing pieces - another day
|
||||||
raise ValueError("Selected path doesn't seem to be a Profile operation.")
|
raise ValueError("Selected path doesn't seem to be a Profile operation.")
|
||||||
|
|
||||||
def sortedBase(self, base):
|
|
||||||
# first find the exit point, where base wire is closed
|
|
||||||
edges = [e for e in self.edges if e.valueAt(e.FirstParameter).z == self.minZ and e.valueAt(e.LastParameter).z != self.maxZ]
|
|
||||||
exit = sorted(edges, key=lambda e: -e.valueAt(e.LastParameter).z)[0]
|
|
||||||
pt = exit.valueAt(exit.FirstParameter)
|
|
||||||
# then find the first base edge, and sort them until done
|
|
||||||
ordered = []
|
|
||||||
while base:
|
|
||||||
edges = [e for e in base if e.valueAt(e.FirstParameter) == pt]
|
|
||||||
if not edges:
|
|
||||||
print ordered
|
|
||||||
print base
|
|
||||||
print("(%.2f, %.2f, %.2f)" % (pt.x, pt.y, pt.z))
|
|
||||||
for e in base:
|
|
||||||
pf = e.valueAt(e.FirstParameter)
|
|
||||||
pl = e.valueAt(e.LastParameter)
|
|
||||||
print("(%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (pf.x, pf.y, pf.z, pl.x, pl.y, pl.z))
|
|
||||||
edge = edges[0]
|
|
||||||
ordered.append(edge)
|
|
||||||
base.remove(edge)
|
|
||||||
pt = edge.valueAt(edge.LastParameter)
|
|
||||||
return ordered
|
|
||||||
|
|
||||||
|
|
||||||
def findZLimits(self, edges):
|
def findZLimits(self, edges):
|
||||||
# not considering arcs and spheres in Z direction, find the highes and lowest Z values
|
# not considering arcs and spheres in Z direction, find the highes and lowest Z values
|
||||||
minZ = edges[0].Vertexes[0].Point.z
|
minZ = edges[0].Vertexes[0].Point.z
|
||||||
|
@ -721,14 +491,6 @@ class ObjectDressup:
|
||||||
return self.pathData.generateTags(obj, count, width, height, angle, spacing)
|
return self.pathData.generateTags(obj, count, width, height, angle, spacing)
|
||||||
|
|
||||||
|
|
||||||
def tagIntersection(self, face, edge):
|
|
||||||
p1 = edge.valueAt(edge.FirstParameter)
|
|
||||||
pts = edge.Curve.intersect(face.Surface)
|
|
||||||
if pts[0]:
|
|
||||||
closest = sorted(pts[0], key=lambda pt: (pt - p1).Length)[0]
|
|
||||||
return closest
|
|
||||||
return None
|
|
||||||
|
|
||||||
def createPath(self, edges, tags):
|
def createPath(self, edges, tags):
|
||||||
commands = []
|
commands = []
|
||||||
lastEdge = 0
|
lastEdge = 0
|
||||||
|
@ -738,36 +500,39 @@ class ObjectDressup:
|
||||||
inters = None
|
inters = None
|
||||||
edge = None
|
edge = None
|
||||||
|
|
||||||
|
mapper = None
|
||||||
|
|
||||||
while edge or lastEdge < len(edges):
|
while edge or lastEdge < len(edges):
|
||||||
print("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags)))
|
#print("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags)))
|
||||||
if not edge:
|
if not edge:
|
||||||
edge = edges[lastEdge]
|
edge = edges[lastEdge]
|
||||||
debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(edges)))
|
debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(edges)))
|
||||||
lastEdge += 1
|
lastEdge += 1
|
||||||
sameTag = None
|
sameTag = None
|
||||||
|
|
||||||
if inters:
|
if mapper:
|
||||||
inters = inters.intersect(edge)
|
mapper.add(edge)
|
||||||
|
if mapper.mappingComplete():
|
||||||
|
commands.extend(mapper.commands)
|
||||||
|
edge = mapper.tail
|
||||||
|
mapper = None
|
||||||
else:
|
else:
|
||||||
|
edge = None
|
||||||
|
|
||||||
|
if edge:
|
||||||
tIndex = (t + lastTag) % len(tags)
|
tIndex = (t + lastTag) % len(tags)
|
||||||
t += 1
|
t += 1
|
||||||
print("<<<<< lastTag=%d, t=%d, tIndex=%d, sameTag=%s >>>>>>" % (lastTag, t, tIndex, sameTag))
|
i = tags[tIndex].intersects(edge, edge.FirstParameter)
|
||||||
inters = tags[tIndex].intersect(edge, True or tIndex != sameTag)
|
if i:
|
||||||
edge = inters.tail
|
mapper = MapWireToTag(edge, tags[tIndex], i)
|
||||||
|
edge = mapper.tail
|
||||||
|
|
||||||
if inters.isComplete():
|
|
||||||
if inters.hasEdges():
|
|
||||||
sameTag = (t + lastTag - 1) % len(tags)
|
|
||||||
lastTag = sameTag
|
|
||||||
t = 1
|
|
||||||
for e in inters.edges:
|
|
||||||
commands.append(PathGeom.cmdForEdge(e))
|
|
||||||
inters = None
|
|
||||||
|
|
||||||
if t >= len(tags):
|
if not mapper and t >= len(tags):
|
||||||
# gone through all tags, consume edge and move on
|
# gone through all tags, consume edge and move on
|
||||||
if edge:
|
if edge:
|
||||||
commands.append(PathGeom.cmdForEdge(edge))
|
debugEdge(edge, '++++++++')
|
||||||
|
commands.extend(PathGeom.cmdsForEdge(edge))
|
||||||
edge = None
|
edge = None
|
||||||
t = 0
|
t = 0
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,14 @@ class PathGeom:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cmdsForEdge(cls, edge, flip = False, useHelixForBSpline = True):
|
def cmdsForEdge(cls, edge, flip = False, useHelixForBSpline = True):
|
||||||
|
"""(edge, flip = False, useHelixForBSpline = True) -> List(Path.Command)
|
||||||
|
Returns a list of Path.Command representing the given edge.
|
||||||
|
If flip is True the edge is considered to be backwards.
|
||||||
|
If useHelixForBSpline is True an Edge based on a BSplineCurve is considered
|
||||||
|
to represent a helix and results in G2 or G3 command. Otherwise edge has
|
||||||
|
no direct Path.Command mapping and will be approximated by straight segments.
|
||||||
|
Approximation is also the approach for edges that are neither straight lines
|
||||||
|
nor arcs (nor helixes)."""
|
||||||
pt = edge.valueAt(edge.LastParameter) if not flip else edge.valueAt(edge.FirstParameter)
|
pt = edge.valueAt(edge.LastParameter) if not flip else edge.valueAt(edge.FirstParameter)
|
||||||
params = {'X': pt.x, 'Y': pt.y, 'Z': pt.z}
|
params = {'X': pt.x, 'Y': pt.y, 'Z': pt.z}
|
||||||
if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment:
|
if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment:
|
||||||
|
@ -147,7 +155,7 @@ class PathGeom:
|
||||||
cmd = 'G3'
|
cmd = 'G3'
|
||||||
else:
|
else:
|
||||||
cmd = 'G2'
|
cmd = 'G2'
|
||||||
print("**** (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z))
|
#print("**** (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z))
|
||||||
pd = Part.Circle(PathGeom.xy(p1), PathGeom.xy(p2), PathGeom.xy(p3)).Center
|
pd = Part.Circle(PathGeom.xy(p1), PathGeom.xy(p2), PathGeom.xy(p3)).Center
|
||||||
|
|
||||||
pa = PathGeom.xy(p1)
|
pa = PathGeom.xy(p1)
|
||||||
|
@ -168,7 +176,7 @@ class PathGeom:
|
||||||
# at this point pixellation is all we can do
|
# at this point pixellation is all we can do
|
||||||
commands = []
|
commands = []
|
||||||
segments = int(math.ceil((deviation / eStraight.Length) * 1000))
|
segments = int(math.ceil((deviation / eStraight.Length) * 1000))
|
||||||
print("**** pixellation with %d segments" % segments)
|
#print("**** pixellation with %d segments" % segments)
|
||||||
dParameter = (edge.LastParameter - edge.FirstParameter) / segments
|
dParameter = (edge.LastParameter - edge.FirstParameter) / segments
|
||||||
for i in range(0, segments):
|
for i in range(0, segments):
|
||||||
if flip:
|
if flip:
|
||||||
|
@ -176,7 +184,7 @@ class PathGeom:
|
||||||
else:
|
else:
|
||||||
p = edge.valueAt(edge.FirstParameter + (i + 1) * dParameter)
|
p = edge.valueAt(edge.FirstParameter + (i + 1) * dParameter)
|
||||||
cmd = Path.Command('G1', {'X': p.x, 'Y': p.y, 'Z': p.z})
|
cmd = Path.Command('G1', {'X': p.x, 'Y': p.y, 'Z': p.z})
|
||||||
print("***** %s" % cmd)
|
#print("***** %s" % cmd)
|
||||||
commands.append(cmd)
|
commands.append(cmd)
|
||||||
#print commands
|
#print commands
|
||||||
return commands
|
return commands
|
||||||
|
@ -280,8 +288,8 @@ class PathGeom:
|
||||||
params.update({'Z': z1, 'K': (z1 - z0)/2})
|
params.update({'Z': z1, 'K': (z1 - z0)/2})
|
||||||
command = Path.Command(cmd.Name, params)
|
command = Path.Command(cmd.Name, params)
|
||||||
|
|
||||||
print("- (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f): %.2f:%.2f" % (edge.Vertexes[0].X, edge.Vertexes[0].Y, edge.Vertexes[0].Z, edge.Vertexes[1].X, edge.Vertexes[1].Y, edge.Vertexes[1].Z, z0, z1))
|
#print("- (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f): %.2f:%.2f" % (edge.Vertexes[0].X, edge.Vertexes[0].Y, edge.Vertexes[0].Z, edge.Vertexes[1].X, edge.Vertexes[1].Y, edge.Vertexes[1].Z, z0, z1))
|
||||||
print("- %s -> %s" % (cmd, command))
|
#print("- %s -> %s" % (cmd, command))
|
||||||
|
|
||||||
return cls.edgeForCmd(command, FreeCAD.Vector(p1.x, p1.y, z0))
|
return cls.edgeForCmd(command, FreeCAD.Vector(p1.x, p1.y, z0))
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ from FreeCAD import Vector
|
||||||
from PathScripts.PathDressupHoldingTags import *
|
from PathScripts.PathDressupHoldingTags import *
|
||||||
from PathTests.PathTestUtils import PathTestBase
|
from PathTests.PathTestUtils import PathTestBase
|
||||||
|
|
||||||
class TestTag01BasicTag(PathTestBase): # =============
|
class TestHoldingTags(PathTestBase):
|
||||||
"""Unit tests for the HoldingTags dressup."""
|
"""Unit tests for the HoldingTags dressup."""
|
||||||
|
|
||||||
def test00(self):
|
def test00(self):
|
||||||
|
@ -89,577 +89,3 @@ class TestTag01BasicTag(PathTestBase): # =============
|
||||||
|
|
||||||
self.assertIsNone(tag.core)
|
self.assertIsNone(tag.core)
|
||||||
|
|
||||||
class TestTag02SquareTag(PathTestBase): # =============
|
|
||||||
"""Unit tests for square tags."""
|
|
||||||
|
|
||||||
def test00(self):
|
|
||||||
"""Verify no intersection."""
|
|
||||||
tag = Tag( 0, 0, 4, 7, 90, True, 0)
|
|
||||||
pt1 = Vector(+5, 5, 0)
|
|
||||||
pt2 = Vector(-5, 5, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(pt1, pt2))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertIsNotNone(i)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertIsNotNone(i.edges)
|
|
||||||
self.assertFalse(i.edges)
|
|
||||||
self.assertLine(i.tail, pt1, pt2)
|
|
||||||
|
|
||||||
def test01(self):
|
|
||||||
"""Verify intersection of square tag with line ending at tag start."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(4, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 1)
|
|
||||||
self.assertLine(i.edges[0], edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test02(self):
|
|
||||||
"""Verify intersection of square tag with line ending between P1 and P2."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(1, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P1)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(4, 0, 3)
|
|
||||||
p3 = Vector(1, 0, 3)
|
|
||||||
self.assertLine(i.edges[0], edge.valueAt(edge.FirstParameter), p1)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# verify we stay in P1 if we add another segment
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(0, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P1)
|
|
||||||
self.assertEqual(len(i.edges), 4)
|
|
||||||
p4 = Vector(0, 0, 3)
|
|
||||||
self.assertLine(i.edges[3], p3, p4)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test03(self):
|
|
||||||
"""Verify intesection of square tag with line ending on P2."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-4, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
p0 = edge.valueAt(edge.FirstParameter)
|
|
||||||
p1 = Vector( 4, 0, 0)
|
|
||||||
p2 = Vector( 4, 0, 3)
|
|
||||||
p3 = Vector(-4, 0, 3)
|
|
||||||
self.assertLine(i.edges[0], p0, p1)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# make sure it also works if we get there not directly
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(0, 0, 0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(-4, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertEqual(len(i.edges), 4)
|
|
||||||
p2a = Vector( 0, 0, 3)
|
|
||||||
self.assertLine(i.edges[0], p0, p1)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertLine(i.edges[2], p2, p2a)
|
|
||||||
self.assertLine(i.edges[3], p2a, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test04(self):
|
|
||||||
"""Verify plunge down is inserted for square tag on exit."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-5, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P3)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertEqual(len(i.edges), 4)
|
|
||||||
p0 = edge.valueAt(edge.FirstParameter)
|
|
||||||
p1 = Vector( 4, 0, 0)
|
|
||||||
p2 = Vector( 4, 0, 3)
|
|
||||||
p3 = Vector(-4, 0, 3)
|
|
||||||
p4 = Vector(-4, 0, 0)
|
|
||||||
p5 = edge.valueAt(edge.LastParameter)
|
|
||||||
self.assertLine(i.edges[0], p0, p1)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertLine(i.edges[3], p3, p4)
|
|
||||||
self.assertIsNotNone(i.tail)
|
|
||||||
self.assertLine(i.tail, p4, p5)
|
|
||||||
|
|
||||||
def test05(self):
|
|
||||||
"""Verify all lines between P0 and P3 are added."""
|
|
||||||
tag = Tag( 0, 0, 4, 7, 90, True, 0)
|
|
||||||
e0 = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(+2, 0, 0)))
|
|
||||||
e1 = Part.Edge(Part.LineSegment(e0.valueAt(e0.LastParameter), Vector(+1, 0, 0)))
|
|
||||||
e2 = Part.Edge(Part.LineSegment(e1.valueAt(e1.LastParameter), Vector(+0.5, 0, 0)))
|
|
||||||
e3 = Part.Edge(Part.LineSegment(e2.valueAt(e2.LastParameter), Vector(-0.5, 0, 0)))
|
|
||||||
e4 = Part.Edge(Part.LineSegment(e3.valueAt(e3.LastParameter), Vector(-1, 0, 0)))
|
|
||||||
e5 = Part.Edge(Part.LineSegment(e4.valueAt(e4.LastParameter), Vector(-2, 0, 0)))
|
|
||||||
e6 = Part.Edge(Part.LineSegment(e5.valueAt(e5.LastParameter), Vector(-5, 0, 0)))
|
|
||||||
|
|
||||||
i = tag
|
|
||||||
for e in [e0, e1, e2, e3, e4, e5]:
|
|
||||||
i = i.intersect(e)
|
|
||||||
self.assertFalse(i.isComplete())
|
|
||||||
i = i.intersect(e6)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
|
|
||||||
pt0 = Vector(2, 0, 0)
|
|
||||||
pt1 = Vector(2, 0, 7)
|
|
||||||
pt2 = Vector(1, 0, 7)
|
|
||||||
pt3 = Vector(0.5, 0, 7)
|
|
||||||
pt4 = Vector(-0.5, 0, 7)
|
|
||||||
pt5 = Vector(-1, 0, 7)
|
|
||||||
pt6 = Vector(-2, 0, 7)
|
|
||||||
|
|
||||||
self.assertEqual(len(i.edges), 8)
|
|
||||||
self.assertLines(i.edges, i.tail, [e0.valueAt(e0.FirstParameter), pt0, pt1, pt2, pt3, pt4, pt5, pt6, e6.valueAt(e6.FirstParameter), e6.valueAt(e6.LastParameter)])
|
|
||||||
self.assertIsNotNone(i.tail)
|
|
||||||
|
|
||||||
def test06(self):
|
|
||||||
"""Verify intersection of different z levels."""
|
|
||||||
tag = Tag( 0, 0, 4, 7, 90, True, 0)
|
|
||||||
# for all lines below 7 we get the trapezoid
|
|
||||||
for i in range(0, 7):
|
|
||||||
p0 = Vector(5, 0, i)
|
|
||||||
p1 = Vector(2, 0, i)
|
|
||||||
p2 = Vector(2, 0, 7)
|
|
||||||
p3 = Vector(-2, 0, 7)
|
|
||||||
p4 = Vector(-2, 0, i)
|
|
||||||
p5 = Vector(-5, 0, i)
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, p5))
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertLines(s.edges, s.tail, [p0, p1, p2, p3, p4, p5])
|
|
||||||
|
|
||||||
# for all edges at height or above the original line is used
|
|
||||||
for i in range(7, 9):
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, i), Vector(-5, 0, i)))
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertLine(s.tail, edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))
|
|
||||||
|
|
||||||
def test10(self):
|
|
||||||
"""Verify intersection of square tag with an arc."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 0)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.8, -3.919184, 0)
|
|
||||||
pj = Vector(0.8, +3.919184, 0)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 4)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.486010, -8.342417, 0), pi)
|
|
||||||
self.assertLine(s.edges[1], pi, pi + Vector(0, 0, 3))
|
|
||||||
self.assertCurve(s.edges[2], pi + Vector(0, 0, 3), Vector(0, 0, 3), pj + Vector(0, 0, 3))
|
|
||||||
self.assertLine(s.edges[3], pj + Vector(0, 0, 3), pj)
|
|
||||||
self.assertCurve(s.tail, pj, Vector(4.486010, +8.342417, 0), p2)
|
|
||||||
|
|
||||||
def test20(self):
|
|
||||||
"""Verify intersection of square tag with a helix."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 90, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 2)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10, 'K': 1}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.8, -3.919184, 0.743623)
|
|
||||||
pj = Vector(0.8, +3.919184, 1.256377)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 4)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.486010, -8.342417, 0.371812), pi)
|
|
||||||
self.assertLine(s.edges[1], pi, pi + Vector(0, 0, 3-pi.z))
|
|
||||||
self.assertCurve(s.edges[2], pi + Vector(0, 0, 3-pi.z), Vector(0, 0, 3), pj + Vector(0, 0, 3-pj.z))
|
|
||||||
self.assertLine(s.edges[3], pj + Vector(0, 0, 3-pj.z), pj)
|
|
||||||
self.assertCurve(s.tail, pj, Vector(4.486010, +8.342417, 1.628188), p2)
|
|
||||||
|
|
||||||
|
|
||||||
class TestTag03TrapezoidTag(PathTestBase): # =============
|
|
||||||
"""Unit tests for trapezoid tags."""
|
|
||||||
|
|
||||||
def test00(self):
|
|
||||||
"""Verify no intersection."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
pt1 = Vector(+5, 5, 0)
|
|
||||||
pt2 = Vector(-5, 5, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(pt1, pt2))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertIsNotNone(i)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertIsNotNone(i.edges)
|
|
||||||
self.assertFalse(i.edges)
|
|
||||||
self.assertLine(i.tail, pt1, pt2)
|
|
||||||
|
|
||||||
def test01(self):
|
|
||||||
"""Veify intersection of trapezoid tag with line ending before P1."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(4, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 1)
|
|
||||||
self.assertLine(i.edges[0], edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# now add another segment that doesn't reach the top of the cone
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(3, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
# still a P0 and edge fully consumed
|
|
||||||
p1 = Vector(edge.valueAt(edge.FirstParameter))
|
|
||||||
p1.z = 0
|
|
||||||
p2 = Vector(edge.valueAt(edge.LastParameter))
|
|
||||||
p2.z = 1 # height of cone @ (3,0)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 2)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# add another segment to verify starting point offset
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(2, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
# still a P0 and edge fully consumed
|
|
||||||
p3 = Vector(edge.valueAt(edge.LastParameter))
|
|
||||||
p3.z = 2 # height of cone @ (2,0)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test02(self):
|
|
||||||
"""Verify intersection of trapezoid tag with line ending between P1 and P2"""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(1, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P1)
|
|
||||||
self.assertEqual(len(i.edges), 2)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(1, 0, 3)
|
|
||||||
self.assertLine(i.edges[0], edge.valueAt(edge.FirstParameter), p1)
|
|
||||||
self.assertLine(i.edges[1], p1, p2)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# verify we stay in P1 if we add another segment
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(0, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P1)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
p3 = Vector(0, 0, 3)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test03(self):
|
|
||||||
"""Verify intersection of trapezoid tag with edge ending on P2."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-1, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
p0 = Vector(edge.valueAt(edge.FirstParameter))
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(1, 0, 3)
|
|
||||||
p3 = Vector(-1, 0, 3)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# make sure we get the same result if there's another edge
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(1, 0, 0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(-1, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# and also if the last segment doesn't cross the entire plateau
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(0.5, 0, 0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(-1, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
p2a = Vector(0.5, 0, 3)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p2a, p3])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test04(self):
|
|
||||||
"""Verify proper down plunge on trapezoid tag exit."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-2, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
p0 = Vector(5, 0, 0)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(1, 0, 3)
|
|
||||||
p3 = Vector(-1, 0, 3)
|
|
||||||
p4 = Vector(-2, 0, 2)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3, p4])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# make sure adding another segment doesn't change the state
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(-3, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertEqual(len(i.edges), 5)
|
|
||||||
p5 = Vector(-3, 0, 1)
|
|
||||||
self.assertLine(i.edges[4], p4, p5)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# now if we complete to P3 ....
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(-4, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P3)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertEqual(len(i.edges), 6)
|
|
||||||
p6 = Vector(-4, 0, 0)
|
|
||||||
self.assertLine(i.edges[5], p5, p6)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# verify proper operation if there is a single edge going through all
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-4, 0, 0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P3)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3, p6])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# verify tail is added as well
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(-5, 0, 0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P3)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3, p6, edge.valueAt(edge.LastParameter)])
|
|
||||||
self.assertIsNotNone(i.tail)
|
|
||||||
|
|
||||||
def test05(self):
|
|
||||||
"""Verify all lines between P0 and P3 are added."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
e0 = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(+4, 0, 0)))
|
|
||||||
e1 = Part.Edge(Part.LineSegment(e0.valueAt(e0.LastParameter), Vector(+2, 0, 0)))
|
|
||||||
e2 = Part.Edge(Part.LineSegment(e1.valueAt(e1.LastParameter), Vector(+0.5, 0, 0)))
|
|
||||||
e3 = Part.Edge(Part.LineSegment(e2.valueAt(e2.LastParameter), Vector(-0.5, 0, 0)))
|
|
||||||
e4 = Part.Edge(Part.LineSegment(e3.valueAt(e3.LastParameter), Vector(-1, 0, 0)))
|
|
||||||
e5 = Part.Edge(Part.LineSegment(e4.valueAt(e4.LastParameter), Vector(-2, 0, 0)))
|
|
||||||
e6 = Part.Edge(Part.LineSegment(e5.valueAt(e5.LastParameter), Vector(-5, 0, 0)))
|
|
||||||
|
|
||||||
i = tag
|
|
||||||
for e in [e0, e1, e2, e3, e4, e5]:
|
|
||||||
i = i.intersect(e)
|
|
||||||
self.assertFalse(i.isComplete())
|
|
||||||
i = i.intersect(e6)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
|
|
||||||
p0 = Vector(4, 0, 0)
|
|
||||||
p1 = Vector(2, 0, 2)
|
|
||||||
p2 = Vector(1, 0, 3)
|
|
||||||
p3 = Vector(0.5, 0, 3)
|
|
||||||
p4 = Vector(-0.5, 0, 3)
|
|
||||||
p5 = Vector(-1, 0, 3)
|
|
||||||
p6 = Vector(-2, 0, 2)
|
|
||||||
p7 = Vector(-4, 0, 0)
|
|
||||||
|
|
||||||
self.assertLines(i.edges, i.tail, [e0.valueAt(e0.FirstParameter), p0, p1, p2, p3, p4, p5, p6, p7, e6.valueAt(e6.LastParameter)])
|
|
||||||
self.assertIsNotNone(i.tail)
|
|
||||||
|
|
||||||
def test06(self):
|
|
||||||
"""Verify intersection for different z levels."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
# for all lines below 3 we get the trapezoid
|
|
||||||
for i in range(0, 3):
|
|
||||||
p0 = Vector(5, 0, i)
|
|
||||||
p1 = Vector(4-i, 0, i)
|
|
||||||
p2 = Vector(1, 0, 3)
|
|
||||||
p3 = Vector(-1, 0, 3)
|
|
||||||
p4 = Vector(-4+i, 0, i)
|
|
||||||
p5 = Vector(-5, 0, i)
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, p5))
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertLines(s.edges, s.tail, [p0, p1, p2, p3, p4, p5])
|
|
||||||
|
|
||||||
# for all edges at height or above the original line is used
|
|
||||||
for i in range(3, 5):
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, i), Vector(-5, 0, i)))
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertLine(s.tail, edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))
|
|
||||||
|
|
||||||
def test10(self):
|
|
||||||
"""Verify intersection with an arc."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 0)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.8, -3.919184, 0)
|
|
||||||
pj = Vector(0.05, -0.998749, 3)
|
|
||||||
pk = Vector(0.05, +0.998749, 3)
|
|
||||||
pl = Vector(0.8, +3.919184, 0)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 4)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.486010, -8.342417, 0), pi)
|
|
||||||
self.assertCurve(s.edges[1], pi, Vector(0.314296, -2.487396, 1.470795), pj)
|
|
||||||
self.assertCurve(s.edges[2], pj, Vector(0, 0, 3), pk)
|
|
||||||
self.assertCurve(s.edges[3], pk, Vector(.3142960, +2.487396, 1.470795), pl)
|
|
||||||
self.assertCurve(s.tail, pl, Vector(4.486010, +8.342417, 0), p2)
|
|
||||||
|
|
||||||
def test20(self):
|
|
||||||
"""Verify intersection with a helix."""
|
|
||||||
tag = Tag( 0, 0, 8, 3, 45, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 2)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10, 'K': 1}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.513574, -3.163498, 0.795085)
|
|
||||||
pj = Vector(0.050001, -0.998749, 3)
|
|
||||||
pk = Vector(0.050001, +0.998749, 3)
|
|
||||||
pl = Vector(0.397586, +2.791711, 1.180119)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 4)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.153420, -8.112798, 0.397543), pi)
|
|
||||||
self.assertCurve(s.edges[1], pi, Vector(0.221698, -2.093992, 1.897543), pj)
|
|
||||||
self.assertCurve(s.edges[2], pj, Vector(0, 0, 3), pk)
|
|
||||||
self.assertCurve(s.edges[3], pk, Vector(0.182776, 1.903182, 2.090060), pl)
|
|
||||||
self.assertCurve(s.tail, pl, Vector(3.996548, +7.997409, 1.590060), p2)
|
|
||||||
|
|
||||||
|
|
||||||
class TestTag04TriangularTag(PathTestBase): # ========================
|
|
||||||
"""Unit tests for tags that take on a triangular shape."""
|
|
||||||
|
|
||||||
def test00(self):
|
|
||||||
"""Verify intersection of triangular tag with line ending at tag start."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(4, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 1)
|
|
||||||
self.assertLine(i.edges[0], edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter))
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test01(self):
|
|
||||||
"""Verify intersection of triangular tag with line ending between P0 and P1."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(Vector(5, 0, 0), Vector(3, 0, 0)))
|
|
||||||
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(3, 0, 1)
|
|
||||||
self.assertLines(i.edges, i.tail, [edge.valueAt(edge.FirstParameter), p1, p2])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# verify we stay in P1 if we add another segment
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), Vector(1, 0, 0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P0)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
p3 = Vector(1, 0, 3)
|
|
||||||
self.assertLine(i.edges[2], p2, p3)
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
def test02(self):
|
|
||||||
"""Verify proper down plunge on exit of triangular tag."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
|
|
||||||
p0 = Vector(5, 0, 0)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(0, 0, 4)
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, FreeCAD.Vector(0,0,0)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertEqual(len(i.edges), 2)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2])
|
|
||||||
|
|
||||||
# adding another segment doesn't make a difference
|
|
||||||
edge = Part.Edge(Part.LineSegment(edge.valueAt(edge.LastParameter), FreeCAD.Vector(-3,0,0)))
|
|
||||||
i = i.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertEqual(len(i.edges), 3)
|
|
||||||
p3 = Vector(-3, 0, 1)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3])
|
|
||||||
|
|
||||||
# same result if all is one line
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, edge.valueAt(edge.LastParameter)))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3])
|
|
||||||
|
|
||||||
def test03(self):
|
|
||||||
"""Verify triangular tag shap on intersection."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
|
|
||||||
p0 = Vector(5, 0, 0)
|
|
||||||
p1 = Vector(4, 0, 0)
|
|
||||||
p2 = Vector(0, 0, 4)
|
|
||||||
p3 = Vector(-4, 0, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, p3))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3])
|
|
||||||
self.assertIsNone(i.tail)
|
|
||||||
|
|
||||||
# this should also work if there is some excess, aka tail
|
|
||||||
p4 = Vector(-5, 0, 0)
|
|
||||||
edge = Part.Edge(Part.LineSegment(p0, p4))
|
|
||||||
i = tag.intersect(edge)
|
|
||||||
self.assertTrue(i.isComplete())
|
|
||||||
self.assertLines(i.edges, i.tail, [p0, p1, p2, p3, p4])
|
|
||||||
self.assertIsNotNone(i.tail)
|
|
||||||
|
|
||||||
def test10(self):
|
|
||||||
"""Verify intersection with an arc."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 0)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.8, -3.919184, 0)
|
|
||||||
pj = Vector(0.0, 0.0, 4)
|
|
||||||
pk = Vector(0.8, +3.919184, 0)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 3)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.486010, -8.342417, 0), pi)
|
|
||||||
self.assertCurve(s.edges[1], pi, Vector(0.202041, -2., 1.958759), pj)
|
|
||||||
self.assertCurve(s.edges[2], pj, Vector(0.202041, +2., 1.958759), pk)
|
|
||||||
self.assertCurve(s.tail, pk, Vector(4.486010, +8.342417, 0), p2)
|
|
||||||
|
|
||||||
def test20(self):
|
|
||||||
"""Verify intersection with a helix."""
|
|
||||||
tag = Tag( 0, 0, 8, 7, 45, True, 0)
|
|
||||||
p1 = Vector(10, -10, 0)
|
|
||||||
p2 = Vector(10, +10, 2)
|
|
||||||
edge = PathGeom.edgeForCmd(Path.Command('G2', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'J': 10, 'K': 1}), p1)
|
|
||||||
|
|
||||||
pi = Vector(0.513574, -3.163498, 0.795085)
|
|
||||||
pj = Vector(0, 0, 4)
|
|
||||||
pk = Vector(0.397586, +2.791711, 1.180119)
|
|
||||||
|
|
||||||
s = tag.intersect(edge)
|
|
||||||
self.assertTrue(s.isComplete())
|
|
||||||
self.assertEqual(len(s.edges), 3)
|
|
||||||
self.assertCurve(s.edges[0], p1, Vector(4.153420, -8.112798, 0.397543), pi)
|
|
||||||
self.assertCurve(s.edges[1], pi, Vector(0.129229, -1.602457, 2.397542), pj)
|
|
||||||
self.assertCurve(s.edges[2], pj, Vector(0.099896, 1.409940, 2.590059), pk)
|
|
||||||
self.assertCurve(s.tail, pk, Vector(3.996548, +7.997409, 1.590060), p2)
|
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,4 @@ from PathTests.TestPathPost import PathPostTestCases
|
||||||
from PathTests.TestPathGeom import TestPathGeom
|
from PathTests.TestPathGeom import TestPathGeom
|
||||||
from PathTests.TestPathDepthParams import depthTestCases
|
from PathTests.TestPathDepthParams import depthTestCases
|
||||||
|
|
||||||
from PathTests.TestPathDressupHoldingTags import TestTag01BasicTag
|
from PathTests.TestPathDressupHoldingTags import TestHoldingTags
|
||||||
from PathTests.TestPathDressupHoldingTags import TestTag02SquareTag
|
|
||||||
from PathTests.TestPathDressupHoldingTags import TestTag03TrapezoidTag
|
|
||||||
from PathTests.TestPathDressupHoldingTags import TestTag04TriangularTag
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user