Added wire(s)ForPath functions with test.
This commit is contained in:
parent
fbc75d9797
commit
0807eaf597
|
@ -26,7 +26,6 @@ SET(PathScripts_SRCS
|
|||
PathScripts/PathCopy.py
|
||||
PathScripts/PathCustom.py
|
||||
PathScripts/PathDressup.py
|
||||
PathScripts/PathDressupHoldingTags.py
|
||||
PathScripts/PathDrilling.py
|
||||
PathScripts/PathEngrave.py
|
||||
PathScripts/PathFacePocket.py
|
||||
|
@ -73,7 +72,6 @@ SET(PathScripts_SRCS
|
|||
PathScripts/opensbp_pre.py
|
||||
PathScripts/rml_post.py
|
||||
PathScripts/slic3r_pre.py
|
||||
PathTests/TestPathDressupHoldingTags.py
|
||||
PathTests/TestPathGeom.py
|
||||
PathTests/TestPathPost.py
|
||||
PathTests/__init__.py
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
<file>panels/DogboneEdit.ui</file>
|
||||
<file>panels/DrillingEdit.ui</file>
|
||||
<file>panels/EngraveEdit.ui</file>
|
||||
<file>panels/HoldingTagsEdit.ui</file>
|
||||
<file>panels/JobEdit.ui</file>
|
||||
<file>panels/MillFaceEdit.ui</file>
|
||||
<file>panels/PocketEdit.ui</file>
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaskPanel</class>
|
||||
<widget class="QWidget" name="TaskPanel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>352</width>
|
||||
<height>387</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Holding Tags</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tbpTags">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>334</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Tags</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="twTags">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>80</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Angle</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDisable">
|
||||
<property name="text">
|
||||
<string>Disable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbAdd">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tbpGenerate">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>334</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Generate</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lWidth">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width of each tag.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="lHeight">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The height of the holding tag measured from the bottom of the path. By default this is set to the (estimated) height of the path.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="lAngle">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Angle </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbAngle">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Angle of tag walls.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Layout</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lCount">
|
||||
<property name="text">
|
||||
<string>Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="sbCount">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enter the number of tags you wish to have.</p><p><br/></p><p>Note that sometimes it's necessary to enter a larger than desired count number and disable the ones tags you don't want in order to get the holding tag layout you want.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Spacing </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbSpacing"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbAutoApply">
|
||||
<property name="text">
|
||||
<string>Auto Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -74,7 +74,6 @@ class PathWorkbench (Workbench):
|
|||
from PathScripts import PathProfileEdges
|
||||
from PathScripts import DogboneDressup
|
||||
from PathScripts import PathMillFace
|
||||
from PathScripts import PathDressupHoldingTags
|
||||
import PathCommands
|
||||
|
||||
# build commands list
|
||||
|
@ -84,7 +83,7 @@ class PathWorkbench (Workbench):
|
|||
twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace"]
|
||||
threedopcmdlist = ["Path_Surfacing"]
|
||||
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
|
||||
dressupcmdlist = ["Dogbone_Dressup", "DragKnife_Dressup", "PathDressup_HoldingTags"]
|
||||
dressupcmdlist = ["Dogbone_Dressup", "DragKnife_Dressup"]
|
||||
extracmdlist = ["Path_SelectLoop"]
|
||||
#modcmdmore = ["Path_Hop",]
|
||||
#remotecmdlist = ["Path_Remote"]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,11 +65,12 @@ class Side:
|
|||
class PathGeom:
|
||||
"""Class to transform Path Commands into Edges and Wire and back again.
|
||||
The interface might eventuallly become part of Path itself."""
|
||||
CmdMoveFast = ['G0', 'G00']
|
||||
CmdMoveStraight = ['G1', 'G01']
|
||||
CmdMoveCW = ['G2', 'G02']
|
||||
CmdMoveCCW = ['G3', 'G03']
|
||||
CmdMoveArc = CmdMoveCW + CmdMoveCCW
|
||||
CmdMove = CmdMoveStraight + CmdMoveArc
|
||||
CmdMoveCW = ['G2', 'G02']
|
||||
CmdMoveCCW = ['G3', 'G03']
|
||||
CmdMoveArc = CmdMoveCW + CmdMoveCCW
|
||||
CmdMove = CmdMoveStraight + CmdMoveArc
|
||||
|
||||
@classmethod
|
||||
def getAngle(cls, vertex):
|
||||
|
@ -108,11 +109,11 @@ class PathGeom:
|
|||
return Vector(pt.x, pt.y, 0)
|
||||
|
||||
@classmethod
|
||||
def edgeForCmd(cls, cmd, startPoint):
|
||||
def edgeForCmd(cls, cmd, startPoint, includeFastMoves = False):
|
||||
"""Returns a Curve representing the givne command, assuming a given startinPoint."""
|
||||
|
||||
endPoint = cls.commandEndPoint(cmd, startPoint)
|
||||
if cmd.Name in cls.CmdMoveStraight:
|
||||
if (cmd.Name in cls.CmdMoveStraight) or (includeFastMoves and cmd.Name in cls.CmdMoveFast):
|
||||
return Part.Edge(Part.Line(startPoint, endPoint))
|
||||
|
||||
if cmd.Name in cls.CmdMoveArc:
|
||||
|
@ -155,5 +156,35 @@ class PathGeom:
|
|||
e = helix.Edges[0]
|
||||
helix.translate(startPoint - e.valueAt(e.FirstParameter))
|
||||
return helix.Edges[0]
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def wireForPath(cls, path, startPoint = FreeCAD.Vector(0, 0, 0)):
|
||||
"""Returns a wire representing all move commands found in the given path."""
|
||||
edges = []
|
||||
if hasattr(path, "Commands"):
|
||||
for cmd in path.Commands:
|
||||
edge = cls.edgeForCmd(cmd, startPoint, True)
|
||||
if edge:
|
||||
edges.append(edge)
|
||||
startPoint = cls.commandEndPoint(cmd, startPoint)
|
||||
return Part.Wire(edges)
|
||||
|
||||
@classmethod
|
||||
def wiresForPath(cls, path, startPoint = FreeCAD.Vector(0, 0, 0)):
|
||||
"""Returns a collection of wires, each representing a continuous cutting Path in path."""
|
||||
wires = []
|
||||
if hasattr(path, "Commands"):
|
||||
edges = []
|
||||
for cmd in path.Commands:
|
||||
if cmd.Name in cls.CmdMove:
|
||||
edges.append(cls.edgeForCmd(cmd, startPoint, False))
|
||||
startPoint = cls.commandEndPoint(cmd, startPoint)
|
||||
elif cmd.Name in cls.CmdMoveFast:
|
||||
wires.append(Part.Wire(edges))
|
||||
edges = []
|
||||
startPoint = cls.commandEndPoint(cmd, startPoint)
|
||||
if edges:
|
||||
wires.append(Part.Wire(edges))
|
||||
return wires
|
||||
|
||||
|
|
|
@ -1,639 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 sliptonic <shopinthewoods@gmail.com> *
|
||||
# * *
|
||||
# * 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
|
||||
import math
|
||||
import unittest
|
||||
|
||||
from FreeCAD import Vector
|
||||
from PathScripts.PathDressupHoldingTags import *
|
||||
|
||||
def pointsCoincide(pt1, pt2):
|
||||
pt = pt1 - pt2
|
||||
if math.fabs(pt.x) > slack:
|
||||
return False
|
||||
if math.fabs(pt.y) > slack:
|
||||
return False
|
||||
if math.fabs(pt.z) > slack:
|
||||
return False
|
||||
return True
|
||||
|
||||
class TagTestCaseBase(unittest.TestCase):
|
||||
"""Base class for all tag test cases providing additional assert functions."""
|
||||
|
||||
def assertCylinderAt(self, solid, pt, r, h):
|
||||
"""Verify that solid is a cylinder at the specified location."""
|
||||
self.assertEqual(len(solid.Edges), 3)
|
||||
|
||||
lid = solid.Edges[0]
|
||||
hull = solid.Edges[1]
|
||||
base = solid.Edges[2]
|
||||
|
||||
self.assertCircle(lid, Vector(pt.x, pt.y, pt.z+h), r)
|
||||
self.assertLine(hull, Vector(pt.x+r, pt.y, pt.z), Vector(pt.x+r, pt.y, pt.z+h))
|
||||
self.assertCircle(base, Vector(pt.x, pt.y, pt.z), r)
|
||||
|
||||
def assertConeAt(self, solid, pt, r1, r2, h):
|
||||
"""Verify that solid is a cone at the specified location."""
|
||||
self.assertEqual(len(solid.Edges), 3)
|
||||
|
||||
lid = solid.Edges[0]
|
||||
hull = solid.Edges[1]
|
||||
base = solid.Edges[2]
|
||||
|
||||
self.assertCircle(lid, Vector(pt.x, pt.y, pt.z+h), r2)
|
||||
self.assertLine(hull, Vector(pt.x+r1, pt.y, pt.z), Vector(pt.x+r2, pt.y, pt.z+h))
|
||||
self.assertCircle(base, Vector(pt.x, pt.y, pt.z), r1)
|
||||
|
||||
def assertCircle(self, edge, pt, r):
|
||||
"""Verivy that edge is a circle at given location."""
|
||||
curve = edge.Curve
|
||||
self.assertIs(type(curve), Part.Circle)
|
||||
self.assertCoincide(curve.Center, Vector(pt.x, pt.y, pt.z))
|
||||
self.assertAbout(curve.Radius, r)
|
||||
|
||||
def assertLine(self, edge, pt1, pt2):
|
||||
"""Verify that edge is a line from pt1 to pt2."""
|
||||
curve = edge.Curve
|
||||
self.assertIs(type(curve), Part.Line)
|
||||
self.assertCoincide(curve.StartPoint, pt1)
|
||||
self.assertCoincide(curve.EndPoint, pt2)
|
||||
|
||||
def assertCoincide(self, pt1, pt2):
|
||||
"""Verify that 2 points coincide (with tolerance)."""
|
||||
self.assertAbout(pt1.x, pt2.x)
|
||||
self.assertAbout(pt1.y, pt2.y)
|
||||
self.assertAbout(pt1.z, pt2.z)
|
||||
|
||||
def assertAbout(self, v1, v2):
|
||||
"""Verify that 2 values are the same (accounting for float imprecision)."""
|
||||
if math.fabs(v1 - v2) > slack:
|
||||
self.fail("%f != %f" % (v1, v2))
|
||||
|
||||
def assertLines(self, edgs, tail, points):
|
||||
"""Check that there are 5 edges forming a trapezoid."""
|
||||
edges = list(edgs)
|
||||
if tail:
|
||||
edges.append(tail)
|
||||
self.assertEqual(len(edges), len(points) - 1)
|
||||
|
||||
for i in range(0, len(edges)):
|
||||
self.assertLine(edges[i], points[i], points[i+1])
|
||||
|
||||
class TestTag00BasicHolding(TagTestCaseBase):
|
||||
"""Some basid test cases."""
|
||||
|
||||
def test00(self,x=1, y=1):
|
||||
"""Test getAngle."""
|
||||
self.assertAbout(getAngle(FreeCAD.Vector( 1*x, 0*y, 0)), 0)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector( 1*x, 1*y, 0)), math.pi/4)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector( 0*x, 1*y, 0)), math.pi/2)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector(-1*x, 1*y, 0)), 3*math.pi/4)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector(-1*x, 0*y, 0)), math.pi)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector(-1*x,-1*y, 0)), -3*math.pi/4)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector( 0*x,-1*y, 0)), -math.pi/2)
|
||||
self.assertAbout(getAngle(FreeCAD.Vector( 1*x,-1*y, 0)), -math.pi/4)
|
||||
|
||||
def test01(self):
|
||||
"""Test class Side."""
|
||||
self.assertEqual(Side.of(FreeCAD.Vector( 1, 0, 0), FreeCAD.Vector( 1, 0, 0)), Side.On)
|
||||
self.assertEqual(Side.of(FreeCAD.Vector( 1, 0, 0), FreeCAD.Vector(-1, 0, 0)), Side.On)
|
||||
self.assertEqual(Side.of(FreeCAD.Vector( 1, 0, 0), FreeCAD.Vector( 0, 1, 0)), Side.Left)
|
||||
self.assertEqual(Side.of(FreeCAD.Vector( 1, 0, 0), FreeCAD.Vector( 0,-1, 0)), Side.Right)
|
||||
|
||||
|
||||
class TestTag01BasicTag(TagTestCaseBase): # =============
|
||||
"""Unit tests for the HoldingTags dressup."""
|
||||
|
||||
def test00(self):
|
||||
"""Check Tag origin, serialization and de-serialization."""
|
||||
tag = Tag(77, 13, 4, 5, 90, True)
|
||||
self.assertCoincide(tag.originAt(3), Vector(77, 13, 3))
|
||||
s = tag.toString()
|
||||
tagCopy = Tag.FromString(s)
|
||||
self.assertEqual(tag.x, tagCopy.x)
|
||||
self.assertEqual(tag.y, tagCopy.y)
|
||||
self.assertEqual(tag.height, tagCopy.height)
|
||||
self.assertEqual(tag.width, tagCopy.width)
|
||||
self.assertEqual(tag.enabled, tagCopy.enabled)
|
||||
|
||||
|
||||
def test01(self):
|
||||
"""Verify solid and core for a 90 degree tag are identical cylinders."""
|
||||
tag = Tag(100, 200, 4, 5, 90, True)
|
||||
tag.createSolidsAt(17)
|
||||
|
||||
self.assertIsNotNone(tag.solid)
|
||||
self.assertCylinderAt(tag.solid, Vector(100, 200, 17), 2, 5)
|
||||
|
||||
self.assertIsNotNone(tag.core)
|
||||
self.assertCylinderAt(tag.core, Vector(100, 200, 17), 2, 5)
|
||||
|
||||
def test02(self):
|
||||
"""Verify trapezoidal tag has a cone shape with a lid, and cylinder core."""
|
||||
tag = Tag(0, 0, 18, 5, 45, True)
|
||||
tag.createSolidsAt(0)
|
||||
|
||||
self.assertIsNotNone(tag.solid)
|
||||
self.assertConeAt(tag.solid, Vector(0,0,0), 9, 4, 5)
|
||||
|
||||
self.assertIsNotNone(tag.core)
|
||||
self.assertCylinderAt(tag.core, Vector(0,0,0), 4, 5)
|
||||
|
||||
def test03(self):
|
||||
"""Verify pointy cone shape of tag with pointy end if width, angle and height match up."""
|
||||
tag = Tag(0, 0, 10, 5, 45, True)
|
||||
tag.createSolidsAt(0)
|
||||
self.assertIsNotNone(tag.solid)
|
||||
self.assertConeAt(tag.solid, Vector(0,0,0), 5, 0, 5)
|
||||
|
||||
self.assertIsNone(tag.core)
|
||||
|
||||
def test04(self):
|
||||
"""Verify height adjustment if tag isn't wide eough for angle."""
|
||||
tag = Tag(0, 0, 5, 17, 60, True)
|
||||
tag.createSolidsAt(0)
|
||||
self.assertIsNotNone(tag.solid)
|
||||
self.assertConeAt(tag.solid, Vector(0,0,0), 2.5, 0, 2.5 * math.tan((60/180.0)*math.pi))
|
||||
|
||||
self.assertIsNone(tag.core)
|
||||
|
||||
class TestTag02SquareTag(TagTestCaseBase): # =============
|
||||
"""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.Line(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.Line(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.Curve.StartPoint, edge.Curve.EndPoint)
|
||||
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.Line(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.Curve.StartPoint, 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.Line(edge.Curve.EndPoint, 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.Line(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.Curve.StartPoint
|
||||
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.Line(Vector(5, 0, 0), Vector(0, 0, 0)))
|
||||
i = tag.intersect(edge)
|
||||
edge = Part.Edge(Part.Line(edge.Curve.EndPoint, 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.Line(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.Curve.StartPoint
|
||||
p1 = Vector( 4, 0, 0)
|
||||
p2 = Vector( 4, 0, 3)
|
||||
p3 = Vector(-4, 0, 3)
|
||||
p4 = Vector(-4, 0, 0)
|
||||
p5 = edge.Curve.EndPoint
|
||||
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.Line(Vector(5, 0, 0), Vector(+2, 0, 0)))
|
||||
e1 = Part.Edge(Part.Line(e0.Curve.EndPoint, Vector(+1, 0, 0)))
|
||||
e2 = Part.Edge(Part.Line(e1.Curve.EndPoint, Vector(+0.5, 0, 0)))
|
||||
e3 = Part.Edge(Part.Line(e2.Curve.EndPoint, Vector(-0.5, 0, 0)))
|
||||
e4 = Part.Edge(Part.Line(e3.Curve.EndPoint, Vector(-1, 0, 0)))
|
||||
e5 = Part.Edge(Part.Line(e4.Curve.EndPoint, Vector(-2, 0, 0)))
|
||||
e6 = Part.Edge(Part.Line(e5.Curve.EndPoint, 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.Curve.StartPoint, pt0, pt1, pt2, pt3, pt4, pt5, pt6, e6.Curve.StartPoint, e6.Curve.EndPoint])
|
||||
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.Line(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.Line(Vector(5, 0, i), Vector(-5, 0, i)))
|
||||
s = tag.intersect(edge)
|
||||
self.assertTrue(s.isComplete())
|
||||
self.assertLine(s.tail, edge.Curve.StartPoint, edge.Curve.EndPoint)
|
||||
|
||||
class TestTag03TrapezoidTag(TagTestCaseBase): # =============
|
||||
"""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.Line(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.Line(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.Curve.StartPoint, edge.Curve.EndPoint)
|
||||
self.assertIsNone(i.tail)
|
||||
|
||||
# now add another segment that doesn't reach the top of the cone
|
||||
edge = Part.Edge(Part.Line(edge.Curve.EndPoint, Vector(3, 0, 0)))
|
||||
i = i.intersect(edge)
|
||||
# still a P0 and edge fully consumed
|
||||
p1 = Vector(edge.Curve.StartPoint)
|
||||
p1.z = 0
|
||||
p2 = Vector(edge.Curve.EndPoint)
|
||||
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.Line(edge.Curve.EndPoint, Vector(2, 0, 0)))
|
||||
i = i.intersect(edge)
|
||||
# still a P0 and edge fully consumed
|
||||
p3 = Vector(edge.Curve.EndPoint)
|
||||
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.Line(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.Curve.StartPoint, 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.Line(edge.Curve.EndPoint, 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.Line(Vector(5, 0, 0), Vector(-1, 0, 0)))
|
||||
|
||||
i = tag.intersect(edge)
|
||||
self.assertEqual(i.state, Tag.Intersection.P2)
|
||||
p0 = Vector(edge.Curve.StartPoint)
|
||||
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.Line(Vector(5, 0, 0), Vector(1, 0, 0)))
|
||||
i = tag.intersect(edge)
|
||||
edge = Part.Edge(Part.Line(edge.Curve.EndPoint, 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.Line(Vector(5, 0, 0), Vector(0.5, 0, 0)))
|
||||
i = tag.intersect(edge)
|
||||
edge = Part.Edge(Part.Line(edge.Curve.EndPoint, 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.Line(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.Line(edge.Curve.EndPoint, 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.Line(edge.Curve.EndPoint, 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.Line(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.Line(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.Curve.EndPoint])
|
||||
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.Line(Vector(5, 0, 0), Vector(+4, 0, 0)))
|
||||
e1 = Part.Edge(Part.Line(e0.Curve.EndPoint, Vector(+2, 0, 0)))
|
||||
e2 = Part.Edge(Part.Line(e1.Curve.EndPoint, Vector(+0.5, 0, 0)))
|
||||
e3 = Part.Edge(Part.Line(e2.Curve.EndPoint, Vector(-0.5, 0, 0)))
|
||||
e4 = Part.Edge(Part.Line(e3.Curve.EndPoint, Vector(-1, 0, 0)))
|
||||
e5 = Part.Edge(Part.Line(e4.Curve.EndPoint, Vector(-2, 0, 0)))
|
||||
e6 = Part.Edge(Part.Line(e5.Curve.EndPoint, 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.Curve.StartPoint, p0, p1, p2, p3, p4, p5, p6, p7, e6.Curve.EndPoint])
|
||||
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.Line(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.Line(Vector(5, 0, i), Vector(-5, 0, i)))
|
||||
s = tag.intersect(edge)
|
||||
self.assertTrue(s.isComplete())
|
||||
self.assertLine(s.tail, edge.Curve.StartPoint, edge.Curve.EndPoint)
|
||||
|
||||
|
||||
class TestTag04TriangularTag(TagTestCaseBase): # ========================
|
||||
"""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.Line(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.Curve.StartPoint, edge.Curve.EndPoint)
|
||||
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.Line(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.Curve.StartPoint, p1, p2])
|
||||
self.assertIsNone(i.tail)
|
||||
|
||||
# verify we stay in P1 if we add another segment
|
||||
edge = Part.Edge(Part.Line(edge.Curve.EndPoint, 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.Line(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.Line(edge.Curve.EndPoint, 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.Line(p0, edge.Curve.EndPoint))
|
||||
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.Line(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.Line(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)
|
||||
|
|
@ -121,3 +121,27 @@ class TestPathGeom(PathTestBase):
|
|||
PathGeom.edgeForCmd(
|
||||
Path.Command('G3', {'X': p2.x, 'Y': p2.y, 'Z': p2.z, 'I': 1, 'J': 0, 'K': -1}), p1),
|
||||
p1, Vector(-1/math.sqrt(2), -1/math.sqrt(2), 1), p2)
|
||||
|
||||
def test50(self):
|
||||
"""Verify proper wire(s) aggregation from a Path."""
|
||||
commands = []
|
||||
commands.append(Path.Command('G1', {'X': 1}))
|
||||
commands.append(Path.Command('G1', {'Y': 1}))
|
||||
commands.append(Path.Command('G0', {'X': 0}))
|
||||
commands.append(Path.Command('G1', {'Y': 0}))
|
||||
|
||||
wire = PathGeom.wireForPath(Path.Path(commands))
|
||||
self.assertEqual(len(wire.Edges), 4)
|
||||
self.assertLine(wire.Edges[0], Vector(0,0,0), Vector(1,0,0))
|
||||
self.assertLine(wire.Edges[1], Vector(1,0,0), Vector(1,1,0))
|
||||
self.assertLine(wire.Edges[2], Vector(1,1,0), Vector(0,1,0))
|
||||
self.assertLine(wire.Edges[3], Vector(0,1,0), Vector(0,0,0))
|
||||
|
||||
wires = PathGeom.wiresForPath(Path.Path(commands))
|
||||
self.assertEqual(len(wires), 2)
|
||||
self.assertEqual(len(wires[0].Edges), 2)
|
||||
self.assertLine(wires[0].Edges[0], Vector(0,0,0), Vector(1,0,0))
|
||||
self.assertLine(wires[0].Edges[1], Vector(1,0,0), Vector(1,1,0))
|
||||
self.assertEqual(len(wires[1].Edges), 1)
|
||||
self.assertLine(wires[1].Edges[0], Vector(0,1,0), Vector(0,0,0))
|
||||
|
||||
|
|
|
@ -26,10 +26,4 @@ import TestApp
|
|||
|
||||
from PathTests.TestPathPost import PathPostTestCases
|
||||
|
||||
from PathTests.TestPathDressupHoldingTags import TestTag00BasicHolding
|
||||
from PathTests.TestPathDressupHoldingTags import TestTag01BasicTag
|
||||
from PathTests.TestPathDressupHoldingTags import TestTag02SquareTag
|
||||
from PathTests.TestPathDressupHoldingTags import TestTag03TrapezoidTag
|
||||
from PathTests.TestPathDressupHoldingTags import TestTag04TriangularTag
|
||||
|
||||
from PathTests.TestPathGeom import TestPathGeom
|
||||
|
|
Loading…
Reference in New Issue
Block a user