Make sure the offset wire is oriented predictably.

This commit is contained in:
Markus Lampert
2018-07-06 20:56:23 -07:00
parent 41ca2b3b6c
commit 1a952af89c
2 changed files with 30 additions and 21 deletions

View File

@@ -31,17 +31,28 @@ import math
from PySide import QtCore
__title__ = "PathOpTools - Tools for Path operations."
__author__ = "sliptonic (Brad Collette)"
__url__ = "http://www.freecadweb.org"
__doc__ = "Collection of functions used by various Path operations. The functions are specific to Path and the algorithms employed by Path's operations."
if False:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
PrintWireDebug = False
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
def debugEdge(label, e):
'''debugEdge(label, e) ... prints a python statement to create e
Currently lines and arcs are supported.'''
if not PrintWireDebug:
return
if Part.Line == type(e.Curve):
p0 = e.valueAt(e.FirstParameter)
p1 = e.valueAt(e.LastParameter)
@@ -61,6 +72,9 @@ def debugEdge(label, e):
print("%s %s (%.2f, %.2f, %.2f) -> (%.2f, %.2f, %.2f)" % (label, type(e.Curve).__name__, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z))
def debugWire(label, w):
'''debugWire(label, w) ... prints python statements for all edges of w to be added to the object tree in a group.'''
if not PrintWireDebug:
return
print("#%s wire >>>>>>>>>>>>>>>>>>>>>>>>" % label)
print("grp = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroup', '%s')" % label)
for i,e in enumerate(w.Edges):
@@ -71,6 +85,8 @@ def debugWire(label, w):
print("#%s wire <<<<<<<<<<<<<<<<<<<<<<<<" % label)
def _orientEdges(inEdges):
'''_orientEdges(inEdges) ... internal worker function to orient edges so the last vertex of one edge connects to the first vertex of the next edge.
Assumes the edges are in an order so they can be connected.'''
PathLog.track()
# orient all edges of the wire so each edge's last value connects to the next edge's first value
e0 = inEdges[0]
@@ -91,6 +107,8 @@ def _orientEdges(inEdges):
return edges
def _isWireClockwise(w):
'''_isWireClockwise(w) ... return True if wire is oriented clockwise.
Assumes the edges of w are already properly oriented - for generic access use isWireClockwise(w).'''
# handle wires consisting of a single circle or 2 edges where one is an arc.
# in both cases, because the edges are expected to be oriented correctly, the orientation can be
# determined by looking at (one of) the circle curves.
@@ -175,7 +193,7 @@ def offsetWire(wire, base, offset, forward):
# if we get to this point the assumption is that makeOffset2D can deal with the edge
pass
owire = wire.makeOffset2D(offset)
owire = orientWire(wire.makeOffset2D(offset), True)
debugWire('makeOffset2D_%d' % len(wire.Edges), owire)
if wire.isClosed():
@@ -209,8 +227,6 @@ def offsetWire(wire, base, offset, forward):
# determine the start and end point
start = edges[0].firstVertex().Point
end = edges[-1].lastVertex().Point
print("Part.show(Part.Vertex(%.2f, %.2f, %.2f), 'wire_start')" % (start.x, start.y, start.z))
print("Part.show(Part.Vertex(%.2f, %.2f, %.2f), 'wire_end')" % (end.x, end.y, end.z))
debugWire('wire', wire)
debugWire('wedges', Part.Wire(edges))
@@ -292,18 +308,18 @@ def offsetWire(wire, base, offset, forward):
for e0 in rightSideEdges:
if PathGeom.edgesMatch(e, e0):
edges = rightSideEdges
print("#use right side edges")
PathLog.debug("#use right side edges")
if not forward:
print("#reverse")
PathLog.debug("#reverse")
edges.reverse()
return orientWire(Part.Wire(edges), None)
# at this point we have the correct edges and they are in the order for forward
# traversal (climb milling). If that's not what we want just reverse the order,
# orientWire takes care of orienting the edges appropriately.
print("#use left side edges")
PathLog.debug("#use left side edges")
if not forward:
print("#reverse")
PathLog.debug("#reverse")
edges.reverse()
return orientWire(Part.Wire(edges), None)

View File

@@ -580,14 +580,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase):
lEdges = [e for e in w.Edges if not PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y)]
self.assertEqual(2, len(lEdges))
print("\n# ====================================")
for i,e in enumerate(lEdges):
PathOpTools.debugEdge("test42_orig_e%d = " % i, e)
wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, True)
for i,e in enumerate(wire.Edges):
PathOpTools.debugEdge("test42_offs_e%d = " % i, e)
print("# ====================================")
x = length/2 + 2 * math.cos(math.pi/6)
y = -10 + 2 * math.sin(math.pi/6)
@@ -602,16 +595,16 @@ class TestPathOpTools(PathTestUtils.PathTestBase):
self.assertCoincide(Vector(0, 0, -1), rEdges[0].Curve.Axis)
#offset the other way
#wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False)
wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False)
#self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point)
#self.assertCoincide(Vector(-x, y, 0), wire.Edges[-1].Vertexes[1].Point)
self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point)
self.assertCoincide(Vector(-x, y, 0), wire.Edges[-1].Vertexes[1].Point)
#rEdges = [e for e in wire.Edges if Part.Circle == type(e.Curve)]
rEdges = [e for e in wire.Edges if Part.Circle == type(e.Curve)]
#self.assertEqual(1, len(rEdges))
#self.assertCoincide(Vector(0, 20, 0), rEdges[0].Curve.Center)
#self.assertCoincide(Vector(0, 0, +1), rEdges[0].Curve.Axis)
self.assertEqual(1, len(rEdges))
self.assertCoincide(Vector(0, 20, 0), rEdges[0].Curve.Center)
self.assertCoincide(Vector(0, 0, +1), rEdges[0].Curve.Axis)
def test43(self):
'''Check offsetting multiple backwards outside edges.'''