From e1af026933af5f4a9d49e2aa7b75d69c657af93c Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Fri, 22 Jun 2018 17:58:47 -0700 Subject: [PATCH] Added basic chamfer test case for offsetting a wire. --- src/Mod/Path/CMakeLists.txt | 8 +- src/Mod/Path/PathScripts/PathChamfer.py | 117 +++++++++++++------- src/Mod/Path/PathScripts/PathEngraveBase.py | 2 +- src/Mod/Path/PathScripts/PathGeom.py | 17 ++- src/Mod/Path/PathTests/TestPathChamfer.py | 113 +++++++++++++++++++ src/Mod/Path/PathTests/TestPathGeom.py | 7 ++ src/Mod/Path/PathTests/test_chamfer.fcstd | Bin 0 -> 46624 bytes src/Mod/Path/TestPathApp.py | 1 + 8 files changed, 223 insertions(+), 42 deletions(-) create mode 100644 src/Mod/Path/PathTests/TestPathChamfer.py create mode 100644 src/Mod/Path/PathTests/test_chamfer.fcstd diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 134d79ff45..f231f3fbc5 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -116,10 +116,8 @@ SET(PathScripts_post_SRCS SET(PathTests_SRCS PathTests/__init__.py - PathTests/boxtest.fcstd PathTests/PathTestUtils.py - PathTests/test_centroid_00.ngc - PathTests/test_linuxcnc_00.ngc + PathTests/TestPathChamfer.py PathTests/TestPathCore.py PathTests/TestPathDepthParams.py PathTests/TestPathDressupDogbone.py @@ -133,6 +131,10 @@ SET(PathTests_SRCS PathTests/TestPathToolController.py PathTests/TestPathTooltable.py PathTests/TestPathUtil.py + PathTests/boxtest.fcstd + PathTests/test_centroid_00.ngc + PathTests/test_chamfer.fcstd + PathTests/test_linuxcnc_00.ngc ) SET(PathImages_Ops diff --git a/src/Mod/Path/PathScripts/PathChamfer.py b/src/Mod/Path/PathScripts/PathChamfer.py index 59c5964cc5..4a83691585 100644 --- a/src/Mod/Path/PathScripts/PathChamfer.py +++ b/src/Mod/Path/PathScripts/PathChamfer.py @@ -26,11 +26,11 @@ import FreeCAD import Part import Path import PathScripts.PathEngraveBase as PathEngraveBase +import PathScripts.PathGeom as PathGeom import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import math -from PathScripts.PathGeom import PathGeom from PySide import QtCore if False: @@ -43,7 +43,32 @@ else: def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) -def removeInsideEdges(edges, shape, offset): +def orientWire(w, forward=True): + face = Part.Face(w) + cw = 0 < face.Surface.Axis.z + if forward != cw: + PathLog.track('orientWire - needs flipping') + return PathGeom.flipWire(w) + PathLog.track('orientWire - ok') + return w + +def isCircleAt(edge, center): + if Circel == type(edge.Curve) or ArcOfCircle == type(edge.Curve): + return PathGeom.pointsCoincide(edge.Curve.Center, center) + return False + +def offsetWire(wire, base, offset, forward): + PathLog.track('offsetWire') + + w = wire.makeOffset2D(offset) + if wire.isClosed(): + if not base.isInside(w.Edges[0].Vertexes[0].Point, offset/2, True): + PathLog.track('closed - outside') + return orientWire(w, forward) + PathLog.track('closed - inside') + w = wire.makeOffset2D(-offset) + return orientWire(w, forward) + # An edge is considered to be inside of shape if the mid point is inside # Of the remaining edges we take the longest wire to be the engraving side # Looking for a circle with the start vertex as center marks and end @@ -52,48 +77,66 @@ def removeInsideEdges(edges, shape, offset): # this is to also include edges which might partially be inside shape # if they need to be discarded, split, that should happen in a post process # Depending on the Axis of the circle, and which side remains we know if the wire needs to be flipped + + # find edges that are not inside the shape def isInside(edge): if shape.Shape.isInside(edge.Vertexes[0].Point, offset/2, True) and shape.Shape.isInside(edge.Vertexes[-1].Point, offset/2, True): return True return False - remaining = [e for e in edges if not isInside(e)] - # of the ones remaining, the first and the last are the end offsets - allFirst = [e.firstVertex().Point for e in remaining] - allLast = [e.lastVertex().Point for e in remaining] - first = [f for f in allFirst if not f in allLast][0] - last = [l for l in allLast if not l in allFirst][0] - #return [e for e in remaining if not PathGeom.pointsCoincide(e.firstVertex().Point, first) and not PathGeom.pointsCoincide(e.lastVertex().Point, last)] - return remaining + outside = [e for e in edges if not isInside(e)] + # discard all edges that are not part of the longest wire + longestWire = None + for w in [Part.Wire(el) for el in Part.sortEdges(outside)]: + if not longestWire or longestWire.Length < w.Length: + longestWire = w -def orientWireForClimbMilling(w): - face = Part.Face(w) - cw = 'Forward' == obj.ToolController.SpindleDir - wcw = 0 < face.Surface.Axis.z - if cw != wcw: - PathLog.track('flip wire') - # This works because Path creation will flip the edges accordingly - return Part.Wire([e for e in reversed(w.Edges)]) - PathLog.track('no flip', cw, wcw) - return w + # find the start and end point + start = wire.Vertexes[0].Point + end = wire.Vertexes[-1].Point -def offsetWire(obj, wire, base, offset): - PathLog.track(obj.Label) + collectLeft = False + collectRight = False + leftSideEdges = [] + rightSideEdges = [] - w = wire.makeOffset2D(offset) - if wire.isClosed(): - if not base.Shape.isInside(w.Edges[0].Vertexes[0].Point, offset/2, True): - return orientWireForClimbMilling(w) - w = wire.makeOffset2D(-offset) - return orientWireForClimbMilling(w) + for e in (w.Edges + w.Edges): + if isCircleAt(e, start): + if PathGeom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): + if not collectLeft and leftSideEdges: + break + collectLeft = True + collectRight = False + else: + if not collectRight and rightSideEdges: + break + collectLeft = False + collectRight = True + elif isCircleAt(e, end): + if PathGeom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): + if not collectRight and rightSideEdges: + break + collectLeft = False + collectRight = True + else: + if not collectLeft and leftSideEdges: + break + collectLeft = True + collectRight = False + elif collectLeft: + leftSideEdges.append(e) + elif collectRight: + rightSideEdges.append(e) - edges = removeInsideEdges(w.Edges, base, offset) - if not edges: - w = wire.makeOffset2D(-offset) - edges = removeInsideEdges(w.Edges, base, offset) - points = [] - for e in edges: - points - # determine the start point + edges = leftSideEdges + for e in longestWire.Edges: + for e0 in rightSideEdges: + if PathGeom.edgesMatch(e, e0): + if forward: + edges = [PathGeom.flipEdge(edge) for edge in rightSideEdges] + return Part.Wire(edges) + + if not forward: + edges = [PathGeom.flipEdge(edge) for edge in rightSideEdges] return Part.Wire(edges) class ObjectChamfer(PathEngraveBase.ObjectOp): @@ -138,7 +181,7 @@ class ObjectChamfer(PathEngraveBase.ObjectOp): basewires.append(Part.Wire(edgelist)) for w in self.adjustWirePlacement(obj, base, basewires): - wires.append(offsetWire(obj, w, base, offset)) + wires.append(offsetWire(obj, w, base.Shape, offset)) self.wires = wires self.buildpathocc(obj, wires, [depth], True) diff --git a/src/Mod/Path/PathScripts/PathEngraveBase.py b/src/Mod/Path/PathScripts/PathEngraveBase.py index ef11b9ec6d..1678891f69 100644 --- a/src/Mod/Path/PathScripts/PathEngraveBase.py +++ b/src/Mod/Path/PathScripts/PathEngraveBase.py @@ -26,12 +26,12 @@ import DraftGeomUtils import FreeCAD import Part import Path +import PathScripts.PathGeom as PathGeom import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import PathScripts.PathUtils as PathUtils import copy -from PathScripts.PathGeom import PathGeom from PySide import QtCore __doc__ = "Base class for all ops in the engrave family." diff --git a/src/Mod/Path/PathScripts/PathGeom.py b/src/Mod/Path/PathScripts/PathGeom.py index f0ce52fab2..1645931cd0 100644 --- a/src/Mod/Path/PathScripts/PathGeom.py +++ b/src/Mod/Path/PathScripts/PathGeom.py @@ -465,7 +465,17 @@ def flipEdge(edge): elif Part.Line == type(edge.Curve) or Part.LineSegment == type(edge.Curve): return Part.Edge(Part.LineSegment(edge.Vertexes[-1].Point, edge.Vertexes[0].Point)) elif Part.Circle == type(edge.Curve): - return Part.makeCircle(edge.Curve.Radius, edge.Curve.Center, -edge.Curve.Axis, -math.degrees(edge.LastParameter), -math.degrees(edge.FirstParameter)) + r = edge.Curve.Radius + c = edge.Curve.Center + d = edge.Curve.Axis + a = math.degrees(edge.Curve.AngleXU) + f = math.degrees(edge.FirstParameter) + l = math.degrees(edge.LastParameter) + if 0 > d.z: + a = a + 180 + PathLog.track(r, c, d, a, f, l) + arc = Part.makeCircle(r, c, -d, -l-a, -f-a) + return arc elif Part.BSplineCurve == type(edge.Curve): spline = edge.Curve @@ -491,3 +501,8 @@ def flipEdge(edge): return Part.Edge(flipped) +def flipWire(wire): + '''Flip the entire wire and all its edges so it is being processed the other way around.''' + edges = [flipEdge(e) for e in wire.Edges] + edges.reverse() + return Part.Wire(edges) diff --git a/src/Mod/Path/PathTests/TestPathChamfer.py b/src/Mod/Path/PathTests/TestPathChamfer.py new file mode 100644 index 0000000000..2e12d4339a --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathChamfer.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2018 sliptonic * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +import FreeCAD +import Part +import Path +import PathScripts.PathChamfer as PathChamfer +import PathScripts.PathGeom as PathGeom +import PathScripts.PathLog as PathLog +import PathTests.PathTestUtils as PathTestUtils + +from FreeCAD import Vector + +PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +#PathLog.trackModule(PathLog.thisModule()) + +def getWire(obj): + return obj.Tool.Tip.Profile[0].Shape.Wires[0] + +def getPositiveShape(obj): + return obj.Tool.Shape + +def getNegativeShape(obj): + return obj.Shape + +class TestPathChamfer(PathTestUtils.PathTestBase): + + def setUp(self): + self.doc = FreeCAD.open(FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_chamfer.fcstd') + self.circle = self.doc.getObjectsByLabel('circle-cut')[0] + self.square = self.doc.getObjectsByLabel('square-cut')[0] + self.triangle = self.doc.getObjectsByLabel('triangle-cut')[0] + self.shape = self.doc.getObjectsByLabel('shape-cut')[0] + + def tearDown(self): + FreeCAD.closeDocument("test_chamfer") + + def test01(self): + '''Check offsetting a cylinder.''' + obj = self.circle + + wire = PathChamfer.offsetWire(getWire(obj), getPositiveShape(obj), 3, True) + self.assertEqual(1, len(wire.Edges)) + edge = wire.Edges[0] + self.assertCoincide(Vector(), edge.Curve.Center) + self.assertCoincide(Vector(0, 0, -1), edge.Curve.Axis) + self.assertRoughly(33, edge.Curve.Radius) + + # the other way around everything's the same except the axis is negative + wire = PathChamfer.offsetWire(getWire(obj), getPositiveShape(obj), 3, False) + self.assertEqual(1, len(wire.Edges)) + edge = wire.Edges[0] + self.assertCoincide(Vector(), edge.Curve.Center) + self.assertCoincide(Vector(0, 0, +1), edge.Curve.Axis) + self.assertRoughly(33, edge.Curve.Radius) + + + def test02(self): + '''Check offsetting a box.''' + obj = self.square + + wire = PathChamfer.offsetWire(getWire(obj), getPositiveShape(obj), 3, True) + self.assertEqual(8, len(wire.Edges)) + self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) + self.assertEqual(4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) + for e in wire.Edges: + if Part.Line == type(e.Curve): + if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + self.assertEqual(40, e.Length) + if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + self.assertEqual(60, e.Length) + if Part.Circle == type(e.Curve): + self.assertRoughly(3, e.Curve.Radius) + # As it turns out the arcs are oriented the wrong way + self.assertCoincide(Vector(0, 0, +1), e.Curve.Axis) + + + wire = PathChamfer.offsetWire(getWire(obj), getPositiveShape(obj), 3, False) + self.assertEqual(8, len(wire.Edges)) + self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) + self.assertEqual(4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) + for e in wire.Edges: + if Part.Line == type(e.Curve): + if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + self.assertEqual(40, e.Length) + if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + self.assertEqual(60, e.Length) + if Part.Circle == type(e.Curve): + self.assertRoughly(3, e.Curve.Radius) + # As it turns out the arcs are oriented the wrong way + self.assertCoincide(Vector(0, 0, -1), e.Curve.Axis) + diff --git a/src/Mod/Path/PathTests/TestPathGeom.py b/src/Mod/Path/PathTests/TestPathGeom.py index 9a2dd4e86f..d4d961c70c 100644 --- a/src/Mod/Path/PathTests/TestPathGeom.py +++ b/src/Mod/Path/PathTests/TestPathGeom.py @@ -427,6 +427,12 @@ class TestPathGeom(PathTestBase): edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1), 300, 340) self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + def test74(self): + '''Flip a rotated arc''' + # oh yes ... + edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 45, 90) + edge.rotate(edge.Curve.Center, Vector(0, 0, 1), -90) + self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) def test75(self): '''Flip a b-spline''' @@ -440,3 +446,4 @@ class TestPathGeom(PathTestBase): + diff --git a/src/Mod/Path/PathTests/test_chamfer.fcstd b/src/Mod/Path/PathTests/test_chamfer.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..2d09689fa85cd248a381b3c7e8ff7a12f54e5302 GIT binary patch literal 46624 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 E-)+`B82|tP literal 0 HcmV?d00001 diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index ecf3a25d6e..6026e4a934 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -37,4 +37,5 @@ from PathTests.TestPathTool import TestPathTool from PathTests.TestPathTooltable import TestPathTooltable from PathTests.TestPathToolController import TestPathToolController from PathTests.TestPathSetupSheet import TestPathSetupSheet +from PathTests.TestPathChamfer import TestPathChamfer