Merge pull request #1229 from sliptonic/master

Renaming Path Commands to comply with standard.  Typos and PEP8 cleanup.
This commit is contained in:
Yorik van Havre
2018-01-17 22:13:27 -02:00
committed by GitHub
13 changed files with 308 additions and 259 deletions

View File

@@ -30,7 +30,6 @@ SET(PathScripts_SRCS
PathScripts/PathDressupDragknife.py
PathScripts/PathDressupHoldingTags.py
PathScripts/PathDressupRampEntry.py
PathScripts/PathDressupTag.py
PathScripts/PathDressupTagGui.py
PathScripts/PathDressupTagPreferences.py
PathScripts/PathDrilling.py

View File

@@ -86,7 +86,7 @@ class PathWorkbench (Workbench):
twodopcmdlist = ["Path_Contour", "Path_Profile_Faces", "Path_Profile_Edges", "Path_Pocket_Shape", "Path_Drilling", "Path_Engrave", "Path_MillFace", "Path_Helix"]
threedopcmdlist = ["Path_Pocket_3D"]
modcmdlist = ["Path_OperationCopy", "Path_Array", "Path_SimpleCopy" ]
dressupcmdlist = ["PathDressup_Dogbone", "PathDressup_DragKnife", "PathDressup_Tag", "PathDressup_RampEntry"]
dressupcmdlist = ["Path_DressupDogbone", "Path_DressupDragKnife", "Path_DressupTag", "Path_DressupRampEntry"]
extracmdlist = []
#modcmdmore = ["Path_Hop",]
#remotecmdlist = ["Path_Remote"]

View File

@@ -42,36 +42,40 @@ LOG_MODULE = PathLog.thisModule()
if False:
PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE)
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
movecommands = ['G0', 'G00', 'G1', 'G01', 'G2', 'G02', 'G3', 'G03']
movestraight = ['G1', 'G01']
movecw = ['G2', 'G02']
moveccw = ['G3', 'G03']
movecw = ['G2', 'G02']
moveccw = ['G3', 'G03']
movearc = movecw + moveccw
def debugMarker(vector, label, color = None, radius = 0.5):
def debugMarker(vector, label, color=None, radius=0.5):
if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG:
obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label)
obj.Label = label
obj.Radius = radius
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
if color:
obj.ViewObject.ShapeColor = color
def debugCircle(vector, r, label, color = None):
def debugCircle(vector, r, label, color=None):
if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG:
obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label)
obj.Label = label
obj.Radius = r
obj.Height = 1
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
obj.ViewObject.Transparency = 90
if color:
obj.ViewObject.ShapeColor = color
def addAngle(a1, a2):
a = a1 + a2
while a <= -math.pi:
@@ -80,6 +84,7 @@ def addAngle(a1, a2):
a -= 2*math.pi
return a
def anglesAreParallel(a1, a2):
an1 = addAngle(a1, 0)
an2 = addAngle(a2, 0)
@@ -89,18 +94,21 @@ def anglesAreParallel(a1, a2):
return True
return False
def getAngle(v):
a = v.getAngle(FreeCAD.Vector(1,0,0))
a = v.getAngle(FreeCAD.Vector(1, 0, 0))
if v.y < 0:
return -a
return a
def pointFromCommand(cmd, pt, X='X', Y='Y', Z='Z'):
x = cmd.Parameters.get(X, pt.x)
y = cmd.Parameters.get(Y, pt.y)
z = cmd.Parameters.get(Z, pt.z)
return FreeCAD.Vector(x, y, z)
def edgesForCommands(cmds, startPt):
edges = []
lastPt = startPt
@@ -110,7 +118,7 @@ def edgesForCommands(cmds, startPt):
if cmd.Name in movestraight:
edges.append(Part.Edge(Part.LineSegment(lastPt, pt)))
elif cmd.Name in movearc:
center = lastPt + pointFromCommand(cmd, FreeCAD.Vector(0,0,0), 'I', 'J', 'K')
center = lastPt + pointFromCommand(cmd, FreeCAD.Vector(0, 0, 0), 'I', 'J', 'K')
A = lastPt - center
B = pt - center
d = -B.x * A.y + B.y * A.x
@@ -131,6 +139,7 @@ def edgesForCommands(cmds, startPt):
lastPt = pt
return edges
class Style:
Dogbone = 'Dogbone'
Tbone_H = 'T-bone horizontal'
@@ -139,6 +148,7 @@ class Style:
Tbone_S = 'T-bone short edge'
All = [Dogbone, Tbone_H, Tbone_V, Tbone_L, Tbone_S]
class Side:
Left = 'Left'
Right = 'Right'
@@ -152,18 +162,21 @@ class Side:
return cls.Left
return None
class Incision:
Fixed = 'fixed'
Adaptive = 'adaptive'
Custom = 'custom'
All = [Adaptive, Fixed, Custom]
class Smooth:
Neither = 0
In = 1
Out = 2
InAndOut = In | Out
# Chord
# A class to represent the start and end point of a path command. If the underlying
# Command is a rotate command the receiver does represent a chord in the geometric
@@ -174,7 +187,7 @@ class Smooth:
# Instances of Chord are generally considered immutable and all movement member
# functions return new instances.
class Chord (object):
def __init__(self, start = None, end = None):
def __init__(self, start=None, end=None):
if not start:
start = FreeCAD.Vector()
if not end:
@@ -247,7 +260,7 @@ class Chord (object):
return self.getAngleOfVector(refChordOrVector)
def getAngleXY(self):
return self.getAngle(FreeCAD.Vector(1,0,0))
return self.getAngle(FreeCAD.Vector(1, 0, 0))
def g1Command(self):
return Path.Command("G1", {"X": self.End.x, "Y": self.End.y, "Z": self.End.z})
@@ -273,6 +286,7 @@ class Chord (object):
def connectsTo(self, chord):
return PathGeom.pointsCoincide(self.End, chord.Start)
class Bone:
def __init__(self, boneId, obj, lastCommand, inChord, outChord, smooth):
self.obj = obj
@@ -296,7 +310,7 @@ class Bone:
def distance(self, toolRadius):
if not hasattr(self, 'cDist'):
self.angle() # make sure the angles are initialized
self.angle() # make sure the angles are initialized
self.cDist = toolRadius / math.cos(self.tAngle/2)
return self.cDist
@@ -327,13 +341,13 @@ class Bone:
# beta = fabs(boneAngle - angle)
beta = math.fabs(addAngle(boneAngle, -angle))
D = (distance / toolRadius) * math.sin(beta)
if D > 1: # no intersection
if D > 1: # no intersection
PathLog.debug("adaptive - no intersection - no bone")
return 0
gamma = math.asin(D)
alpha = math.pi - beta - gamma
length = toolRadius * math.sin(alpha) / math.sin(beta)
if D < 1 and toolRadius < distance: # there exists a second solution
if D < 1 and toolRadius < distance: # there exists a second solution
beta2 = beta
gamma2 = math.pi - gamma
alpha2 = math.pi - beta2 - gamma2
@@ -343,25 +357,26 @@ class Bone:
PathLog.debug("adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, angle, length, boneAngle))
return length
class ObjectDressup:
def __init__(self, obj, base):
# Tool Properties
obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The tool controller that will be used to calculate the path"))
obj.addProperty("App::PropertyLink", "Base","Base", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "The base path to modify"))
obj.addProperty("App::PropertyEnumeration", "Side", "Dressup", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "The side of path to insert bones"))
obj.addProperty("App::PropertyLink", "Base", "Base", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "The base path to modify"))
obj.addProperty("App::PropertyEnumeration", "Side", "Dressup", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "The side of path to insert bones"))
obj.Side = [Side.Left, Side.Right]
obj.Side = Side.Right
obj.addProperty("App::PropertyEnumeration", "Style", "Dressup", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "The style of bones"))
obj.addProperty("App::PropertyEnumeration", "Style", "Dressup", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "The style of bones"))
obj.Style = Style.All
obj.Style = Style.Dogbone
obj.addProperty("App::PropertyIntegerList", "BoneBlacklist", "Dressup", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "Bones that aren't dressed up"))
obj.addProperty("App::PropertyIntegerList", "BoneBlacklist", "Dressup", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "Bones that aren't dressed up"))
obj.BoneBlacklist = []
obj.setEditorMode('BoneBlacklist', 2) # hide this one
obj.addProperty("App::PropertyEnumeration", "Incision", "Dressup", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "The algorithm to determine the bone length"))
obj.addProperty("App::PropertyEnumeration", "Incision", "Dressup", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "The algorithm to determine the bone length"))
obj.Incision = Incision.All
obj.Incision = Incision.Adaptive
obj.addProperty("App::PropertyFloat", "Custom", "Dressup", QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "Dressup length if Incision == custom"))
obj.addProperty("App::PropertyFloat", "Custom", "Dressup", QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "Dressup length if Incision == custom"))
obj.Custom = 0.0
obj.Proxy = self
obj.Base = base
@@ -389,7 +404,7 @@ class ObjectDressup:
ppt = None
pptDistance = 0
for pt in DraftGeomUtils.findIntersection(edge, pivotEdge, dts=False):
#debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2)
# debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2)
distance = (pt - refPt).Length
PathLog.debug(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance))
if not ppt or pptDistance < distance:
@@ -403,7 +418,7 @@ class ObjectDressup:
else:
PathLog.debug("Taking chord start as intersect %s" % edge.Vertexes[0].Point)
ppt = edge.Vertexes[0].Point
#debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2)
# debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2)
PathLog.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y))
return ppt
@@ -411,10 +426,10 @@ class ObjectDressup:
param = edge.Curve.parameter(point)
return edge.FirstParameter <= param <= edge.LastParameter
def smoothChordCommands(self, bone, inChord, outChord, edge, wire, corner, smooth, color = None):
def smoothChordCommands(self, bone, inChord, outChord, edge, wire, corner, smooth, color=None):
if smooth == 0:
PathLog.info(" No smoothing requested")
return [ bone.lastCommand, outChord.g1Command() ]
return [bone.lastCommand, outChord.g1Command()]
d = 'in'
refPoint = inChord.Start
@@ -424,7 +439,7 @@ class ObjectDressup:
if DraftGeomUtils.areColinear(inChord.asEdge(), outChord.asEdge()):
PathLog.info(" straight edge %s" % d)
return [ outChord.g1Command() ]
return [outChord.g1Command()]
pivot = None
pivotDistance = 0
@@ -438,7 +453,7 @@ class ObjectDressup:
PathLog.debug(" (%.2f, %.2f)^%.2f" % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius))
for pt in DraftGeomUtils.findIntersection(edge, e, True, findAll=True):
if not PathGeom.pointsCoincide(pt, corner) and self.pointIsOnEdge(pt, e):
#debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05)
# debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05)
PathLog.debug(" -> candidate")
distance = (pt - refPoint).Length
if not pivot or pivotDistance > distance:
@@ -448,9 +463,9 @@ class ObjectDressup:
PathLog.debug(" -> corner intersect")
if pivot:
#debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color)
# debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color)
pivotEdge = Part.Edge(Part.Circle(pivot, FreeCAD.Vector(0,0,1), self.toolRadius))
pivotEdge = Part.Edge(Part.Circle(pivot, FreeCAD.Vector(0, 0, 1), self.toolRadius))
t1 = self.findPivotIntersection(pivot, pivotEdge, inChord.asEdge(), inChord.End, d, color)
t2 = self.findPivotIntersection(pivot, pivotEdge, outChord.asEdge(), inChord.End, d, color)
@@ -468,22 +483,22 @@ class ObjectDressup:
PathLog.debug(" add lead out")
commands.append(Chord(t2, outChord.End).g1Command())
#debugMarker(pivot, "pivot.%d-%s" % (self.boneId, d), color, 0.2)
#debugMarker(t1, "pivot.%d-%s.in" % (self.boneId, d), color, 0.1)
#debugMarker(t2, "pivot.%d-%s.out" % (self.boneId, d), color, 0.1)
# debugMarker(pivot, "pivot.%d-%s" % (self.boneId, d), color, 0.2)
# debugMarker(t1, "pivot.%d-%s.in" % (self.boneId, d), color, 0.1)
# debugMarker(t2, "pivot.%d-%s.out" % (self.boneId, d), color, 0.1)
return commands
PathLog.info(" no pivot found - straight command")
return [ inChord.g1Command(), outChord.g1Command() ]
return [inChord.g1Command(), outChord.g1Command()]
def inOutBoneCommands(self, bone, boneAngle, fixedLength):
corner = bone.corner(self.toolRadius)
bone.tip = bone.inChord.End # in case there is no bone
bone.tip = bone.inChord.End # in case there is no bone
PathLog.debug("corner = (%.2f, %.2f)" % (corner.x, corner.y))
#debugMarker(corner, 'corner', (1., 0., 1.), self.toolRadius)
# debugMarker(corner, 'corner', (1., 0., 1.), self.toolRadius)
length = fixedLength
if bone.obj.Incision == Incision.Custom:
@@ -493,18 +508,18 @@ class ObjectDressup:
if length == 0:
PathLog.info("no bone after all ..")
return [ bone.lastCommand, bone.outChord.g1Command() ]
return [bone.lastCommand, bone.outChord.g1Command()]
boneInChord = bone.inChord.move(length, boneAngle)
boneOutChord = boneInChord.moveTo(bone.outChord.Start)
#debugCircle(boneInChord.Start, self.toolRadius, 'boneStart')
#debugCircle(boneInChord.End, self.toolRadius, 'boneEnd')
# debugCircle(boneInChord.Start, self.toolRadius, 'boneStart')
# debugCircle(boneInChord.End, self.toolRadius, 'boneEnd')
bone.tip = boneInChord.End
if bone.smooth == 0:
return [ bone.lastCommand, boneInChord.g1Command(), boneOutChord.g1Command(), bone.outChord.g1Command()]
return [bone.lastCommand, boneInChord.g1Command(), boneOutChord.g1Command(), bone.outChord.g1Command()]
# reconstruct the corner and convert to an edge
offset = corner - bone.inChord.End
@@ -515,9 +530,9 @@ class ObjectDressup:
cornerShape = Part.Shape([iLine, oLine])
# construct a shape representing the cut made by the bone
vt0 = FreeCAD.Vector( 0, self.toolRadius, 0)
vt0 = FreeCAD.Vector(0, self.toolRadius, 0)
vt1 = FreeCAD.Vector(length, self.toolRadius, 0)
vb0 = FreeCAD.Vector( 0, -self.toolRadius, 0)
vb0 = FreeCAD.Vector(0, -self.toolRadius, 0)
vb1 = FreeCAD.Vector(length, -self.toolRadius, 0)
vm2 = FreeCAD.Vector(length + self.toolRadius, 0, 0)
@@ -528,19 +543,19 @@ class ObjectDressup:
# what we actually want is an Arc - but findIntersect only returns the coincident if one exists
# which really sucks because that's the one we're probably not interested in ....
boneArc = Part.Arc(vt1, vm2, vb1)
#boneArc = Part.Circle(FreeCAD.Vector(length, 0, 0), FreeCAD.Vector(0,0,1), self.toolRadius)
# boneArc = Part.Circle(FreeCAD.Vector(length, 0, 0), FreeCAD.Vector(0,0,1), self.toolRadius)
boneWire = Part.Shape([boneTop, boneArc, boneBot, boneLid])
boneWire.rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), boneAngle * 180 / math.pi)
boneWire.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), boneAngle * 180 / math.pi)
boneWire.translate(bone.inChord.End)
self.boneShapes = [cornerShape, boneWire]
bone.inCommands = self.smoothChordCommands(bone, bone.inChord, boneInChord, Part.Edge(iLine), boneWire, corner, bone.smooth & Smooth.In, (1., 0., 0.))
bone.inCommands = self.smoothChordCommands(bone, bone.inChord, boneInChord, Part.Edge(iLine), boneWire, corner, bone.smooth & Smooth.In, (1., 0., 0.))
bone.outCommands = self.smoothChordCommands(bone, boneOutChord, bone.outChord, Part.Edge(oLine), boneWire, corner, bone.smooth & Smooth.Out, (0., 1., 0.))
return bone.inCommands + bone.outCommands
def dogbone(self, bone):
boneAngle = bone.angle()
length = self.toolRadius * 0.41422 # 0.41422 = 2/sqrt(2) - 1 + (a tiny bit)
length = self.toolRadius * 0.41422 # 0.41422 = 2/sqrt(2) - 1 + (a tiny bit)
return self.inOutBoneCommands(bone, boneAngle, length)
def tboneHorizontal(self, bone):
@@ -611,7 +626,7 @@ class ObjectDressup:
if bone.obj.Style == Style.Tbone_S:
return self.tboneShortEdge(bone)
else:
return [ bone.lastCommand, bone.outChord.g1Command() ]
return [bone.lastCommand, bone.outChord.g1Command()]
def insertBone(self, bone):
PathLog.debug(">----------------------------------- %d --------------------------------------" % bone.boneId)
@@ -635,19 +650,19 @@ class ObjectDressup:
commands.append(bone2.lastCommand)
bones = bone2.commands
if True and hasattr(bone1, "outCommands") and hasattr(bone2, "inCommands"):
inEdges = edgesForCommands(bone1.outCommands, bone1.tip)
inEdges = edgesForCommands(bone1.outCommands, bone1.tip)
outEdges = edgesForCommands(bone2.inCommands, bone2.inChord.Start)
for i in range(len(inEdges)):
e1 = inEdges[i]
for j in range(len(outEdges) -1, -1, -1):
for j in range(len(outEdges)-1, -1, -1):
e2 = outEdges[j]
cutoff = DraftGeomUtils.findIntersection(e1, e2)
for pt in cutoff:
#debugCircle(e1.Curve.Center, e1.Curve.Radius, "bone.%d-1" % (self.boneId), (1.,0.,0.))
#debugCircle(e2.Curve.Center, e2.Curve.Radius, "bone.%d-2" % (self.boneId), (0.,1.,0.))
# debugCircle(e1.Curve.Center, e1.Curve.Radius, "bone.%d-1" % (self.boneId), (1.,0.,0.))
# debugCircle(e2.Curve.Center, e2.Curve.Radius, "bone.%d-2" % (self.boneId), (0.,1.,0.))
if PathGeom.pointsCoincide(pt, e1.valueAt(e1.LastParameter)) or PathGeom.pointsCoincide(pt, e2.valueAt(e2.FirstParameter)):
continue
#debugMarker(pt, "it", (0.0, 1.0, 1.0))
# debugMarker(pt, "it", (0.0, 1.0, 1.0))
# 1. remove all redundant commands
commands = commands[:-(len(inEdges) - i)]
# 2., correct where c1 ends
@@ -694,10 +709,10 @@ class ObjectDressup:
boneId = 1
self.bones = []
self.locationBlacklist = set()
boneIserted = False
# boneIserted = False
for (i, thisCommand) in enumerate(obj.Base.Path.Commands):
#if i > 14:
# if i > 14:
# if lastCommand:
# commands.append(lastCommand)
# lastCommand = None
@@ -715,7 +730,7 @@ class ObjectDressup:
boneId += 1
if lastBone:
PathLog.info(" removing potential path crossing")
#debugMarker(thisChord.Start, "it", (1.0, 0.0, 1.0))
# debugMarker(thisChord.Start, "it", (1.0, 0.0, 1.0))
commands, bones = self.removePathCrossing(commands, lastBone, bone)
commands.extend(bones[:-1])
lastCommand = bones[-1]
@@ -731,7 +746,7 @@ class ObjectDressup:
boneId += 1
if lastBone:
PathLog.info(" removing potential path crossing")
#debugMarker(chord.Start, "it", (0.0, 1.0, 1.0))
# debugMarker(chord.Start, "it", (0.0, 1.0, 1.0))
commands, bones = self.removePathCrossing(commands, lastBone, bone)
commands.extend(bones[:-1])
lastCommand = bones[-1]
@@ -767,7 +782,7 @@ class ObjectDressup:
lastCommand = None
commands.append(thisCommand)
lastBone = None
#for cmd in commands:
# for cmd in commands:
# PathLog.debug("cmd = '%s'" % cmd)
path = Path.Path(commands)
obj.Path = path
@@ -792,7 +807,7 @@ class ObjectDressup:
if tc is None or tc.ToolNumber == 0:
self.toolRadius = 5
else:
tool = tc.Proxy.getTool(tc) #PathUtils.getTool(obj, tc.ToolNumber)
tool = tc.Proxy.getTool(tc) # PathUtils.getTool(obj, tc.ToolNumber)
if not tool or tool.Diameter == 0:
self.toolRadius = 5
else:
@@ -814,6 +829,7 @@ class ObjectDressup:
state[loc] = (enabled, inaccessible, [id])
return state
class TaskPanel:
DataIds = QtCore.Qt.ItemDataRole.UserRole
DataKey = QtCore.Qt.ItemDataRole.UserRole + 1
@@ -821,7 +837,7 @@ class TaskPanel:
def __init__(self, obj):
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":/panels/DogboneEdit.ui")
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_Dogbone", "Edit Dogbone Dress-up"))
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDogbone", "Edit Dogbone Dress-up"))
def reject(self):
FreeCAD.ActiveDocument.abortTransaction()
@@ -840,7 +856,7 @@ class TaskPanel:
def getFields(self):
self.obj.Style = str(self.form.styleCombo.currentText())
self.obj.Side = str(self.form.sideCombo.currentText())
self.obj.Side = str(self.form.sideCombo.currentText())
self.obj.Incision = str(self.form.incisionCombo.currentText())
self.obj.Custom = self.form.custom.value()
blacklist = []
@@ -890,7 +906,6 @@ class TaskPanel:
else:
PathLog.info("no shapes attribute found")
def updateModel(self):
self.getFields()
self.updateUI()
@@ -914,13 +929,11 @@ class TaskPanel:
self.form.custom.setValue(self.obj.Custom)
self.updateUI()
def open(self):
self.s = SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
def setupUi(self):
self.setFields()
# now that the form is filled, setup the signal handlers
@@ -930,6 +943,7 @@ class TaskPanel:
self.form.custom.valueChanged.connect(self.updateModel)
self.form.bones.itemChanged.connect(self.updateModel)
class SelObserver:
def __init__(self):
import PathScripts.PathSelection as PST
@@ -943,6 +957,7 @@ class SelObserver:
FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
FreeCADGui.updateGui()
class ViewProviderDressup:
def __init__(self, vobj):
@@ -958,7 +973,7 @@ class ViewProviderDressup:
if g.Name == self.obj.Base.Name:
group.remove(g)
i.Group = group
#FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
# FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
return
def claimChildren(self):
@@ -985,7 +1000,8 @@ class ViewProviderDressup:
arg1.Object.Base = None
return True
def Create(base, name = 'DogboneDressup'):
def Create(base, name='DogboneDressup'):
'''
Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones.
'''
@@ -1002,12 +1018,13 @@ def Create(base, name = 'DogboneDressup'):
dbo.setup(obj, True)
return obj
class CommandDressupDogbone:
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "Dogbone Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathDressup_Dogbone", "Creates a Dogbone Dress-up object from a selected path")}
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "Dogbone Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_DressupDogbone", "Creates a Dogbone Dress-up object from a selected path")}
def IsActive(self):
if FreeCAD.ActiveDocument is not None:
@@ -1021,18 +1038,18 @@ class CommandDressupDogbone:
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("PathDressup_Dogbone", "Please select one path object\n"))
FreeCAD.Console.PrintError(translate("Path_DressupDogbone", "Please select one path object\n"))
return
baseObject = selection[0]
if not baseObject.isDerivedFrom("Path::Feature"):
FreeCAD.Console.PrintError(translate("PathDressup_Dogbone", "The selected object is not a path\n"))
FreeCAD.Console.PrintError(translate("Path_DressupDogbone", "The selected object is not a path\n"))
return
if not hasattr(baseObject, "Side") and not hasattr(baseObject, 'Direction'):
FreeCAD.Console.PrintError(translate("PathDressup_Dogbone", "Please select a Profile/Contour or Dogbone Dressup object"))
FreeCAD.Console.PrintError(translate("Path_DressupDogbone", "Please select a Profile/Contour or Dogbone Dressup object"))
return
# everything ok!
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_Dogbone", "Create Dogbone Dress-up"))
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDogbone", "Create Dogbone Dress-up"))
FreeCADGui.addModule('PathScripts.PathDressupDogbone')
FreeCADGui.doCommand("PathScripts.PathDressupDogbone.Create(FreeCAD.ActiveDocument.%s)" % baseObject.Name)
FreeCAD.ActiveDocument.commitTransaction()
@@ -1040,6 +1057,6 @@ class CommandDressupDogbone:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('PathDressup_Dogbone', CommandDressupDogbone())
FreeCADGui.addCommand('Path_DressupDogbone', CommandDressupDogbone())
FreeCAD.Console.PrintLog("Loading DressupDogbone... done\n")

View File

@@ -26,14 +26,14 @@ from __future__ import print_function
import FreeCAD
import FreeCADGui
import Path
#import PathGui
from PySide import QtCore, QtGui
from PySide import QtCore
import math
import DraftVecUtils as D
import PathScripts.PathUtils as PathUtils
"""Dragknife Dressup object and FreeCAD command"""
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -48,10 +48,10 @@ currLocation = {}
class ObjectDressup:
def __init__(self, obj):
obj.addProperty("App::PropertyLink", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","The base path to modify"))
obj.addProperty("App::PropertyAngle", "filterangle", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Angles less than filter angle will not receive corner actions"))
obj.addProperty("App::PropertyFloat", "offset", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Distance the point trails behind the spindle"))
obj.addProperty("App::PropertyFloat", "pivotheight", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Height to raise during corner action"))
obj.addProperty("App::PropertyLink", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The base path to modify"))
obj.addProperty("App::PropertyAngle", "filterangle", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Angles less than filter angle will not receive corner actions"))
obj.addProperty("App::PropertyFloat", "offset", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Distance the point trails behind the spindle"))
obj.addProperty("App::PropertyFloat", "pivotheight", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Height to raise during corner action"))
obj.Proxy = self
@@ -69,7 +69,7 @@ class ObjectDressup:
if queue[1].Name in arccommands:
arcLoc = FreeCAD.Vector(queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation['Z'])
radvector = arcLoc.sub(queue[1].Placement.Base) #.sub(arcLoc) # vector of chord from center to point
radvector = arcLoc.sub(queue[1].Placement.Base) # .sub(arcLoc) # vector of chord from center to point
# vector of line perp to chord.
v1 = radvector.cross(FreeCAD.Vector(0, 0, 1))
else:
@@ -77,7 +77,7 @@ class ObjectDressup:
# get the vector of the current move
if queue[0].Name in arccommands:
arcLoc = FreeCAD.Vector( (queue[1].x + queue[0].I), (queue[1].y + queue[0].J), currLocation['Z'])
arcLoc = FreeCAD.Vector((queue[1].x + queue[0].I), (queue[1].y + queue[0].J), currLocation['Z'])
radvector = queue[1].Placement.Base.sub(arcLoc) # calculate arcangle
v2 = radvector.cross(FreeCAD.Vector(0, 0, 1))
else:
@@ -95,17 +95,17 @@ class ObjectDressup:
global arccommands
if currCommand.Name in arccommands:
arcLoc = FreeCAD.Vector( (prevCommand.x + currCommand.I), (prevCommand.y + currCommand.J), currentZ)
arcLoc = FreeCAD.Vector((prevCommand.x + currCommand.I), (prevCommand.y + currCommand.J), currentZ)
if endpos is True:
radvector = arcLoc.sub(currCommand.Placement.Base) #Calculate vector at start of arc
radvector = arcLoc.sub(currCommand.Placement.Base) # Calculate vector at start of arc
else:
radvector = arcLoc.sub(prevCommand.Placement.Base) #Calculate vector at end of arc
radvector = arcLoc.sub(prevCommand.Placement.Base) # Calculate vector at end of arc
v1 = radvector.cross(FreeCAD.Vector(0, 0, 1))
if currCommand.Name in ["G2", "G02"]:
v1 = D.rotate2D(v1, math.radians(180))
else:
v1 = currCommand.Placement.Base.sub(prevCommand.Placement.Base) #Straight segments are easy
v1 = currCommand.Placement.Base.sub(prevCommand.Placement.Base) # Straight segments are easy
myAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1))
return myAngle
@@ -214,7 +214,7 @@ class ObjectDressup:
# add G2/G3 move
arcmove = Path.Command(
arcdir, {"X": endpointvector.x, "Y": endpointvector.y, "I": offsetvector.x, "J": offsetvector.y})
arcdir, {"X": endpointvector.x, "Y": endpointvector.y, "I": offsetvector.x, "J": offsetvector.y})
results.append(arcmove)
currLocation.update(arcmove.Parameters)
@@ -378,7 +378,7 @@ class ObjectDressup:
if abs(incident_angle) >= obj.filterangle:
if self.shortcut(queue) == "CW":
#if incident_angle >= 0:
# if incident_angle >= 0:
twistCW = True
else:
twistCW = False
@@ -438,7 +438,7 @@ class ViewProviderDressup:
group.remove(g)
i.Group = group
print(i.Group)
#FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
# FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
def unsetEdit(self, vobj, mode=0):
return False
@@ -466,8 +466,8 @@ class CommandDressupDragknife:
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathDressup_DragKnife", "DragKnife Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathDressup_DragKnife", "Modifies a path to add dragknife corner actions")}
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_DressupDragKnife", "DragKnife Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_DressupDragKnife", "Modifies a path to add dragknife corner actions")}
def IsActive(self):
if FreeCAD.ActiveDocument is not None:
@@ -482,19 +482,19 @@ class CommandDressupDragknife:
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(
translate("PathDressup_DragKnife", "Please select one path object\n"))
translate("Path_DressupDragKnife", "Please select one path object\n"))
return
if not selection[0].isDerivedFrom("Path::Feature"):
FreeCAD.Console.PrintError(
translate("PathDressup_DragKnife", "The selected object is not a path\n"))
translate("Path_DressupDragKnife", "The selected object is not a path\n"))
return
if selection[0].isDerivedFrom("Path::FeatureCompoundPython"):
FreeCAD.Console.PrintError(
translate("PathDressup_DragKnife", "Please select a Path object"))
translate("Path_DressupDragKnife", "Please select a Path object"))
return
# everything ok!
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_DragKnife", "Create Dress-up"))
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDragKnife", "Create Dress-up"))
FreeCADGui.addModule("PathScripts.PathDressupDragknife")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","DragknifeDressup")')
@@ -513,6 +513,6 @@ class CommandDressupDragknife:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('PathDressup_DragKnife', CommandDressupDragknife())
FreeCADGui.addCommand('Path_DressupDragKnife', CommandDressupDragknife())
FreeCAD.Console.PrintLog("Loading PathDressup_DragKnife... done\n")
FreeCAD.Console.PrintLog("Loading Path_DressupDragKnife... done\n")

View File

@@ -24,18 +24,14 @@
import FreeCAD
import Part
import Path
import PathScripts
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils
import copy
import math
from PathScripts import PathUtils
from PathScripts.PathGeom import PathGeom
from PathScripts.PathDressupTagPreferences import HoldingTagPreferences
from PathScripts.PathPreferences import PathPreferences
from PathScripts.PathUtils import waiting_effects
from PySide import QtCore
@@ -47,11 +43,13 @@ if False:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
def debugEdge(edge, prefix, force = False):
def debugEdge(edge, prefix, force=False):
if force or PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
pf = edge.valueAt(edge.FirstParameter)
pl = edge.valueAt(edge.LastParameter)
@@ -61,34 +59,37 @@ def debugEdge(edge, prefix, force = False):
pm = edge.valueAt((edge.FirstParameter+edge.LastParameter)/2)
print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pm.x, pm.y, pm.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):
if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label)
obj.Label = label
obj.Radius = radius
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
if color:
obj.ViewObject.ShapeColor = color
def debugCylinder(vector, r, height, label, color = None):
def debugCylinder(vector, r, height, label, color=None):
if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label)
obj.Label = label
obj.Radius = r
obj.Height = height
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
obj.ViewObject.Transparency = 90
if color:
obj.ViewObject.ShapeColor = color
def debugCone(vector, r1, r2, height, label, color = None):
def debugCone(vector, r1, r2, height, label, color=None):
if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
obj = FreeCAD.ActiveDocument.addObject("Part::Cone", label)
obj.Label = label
obj.Radius1 = r1
obj.Radius2 = r2
obj.Height = height
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
obj.ViewObject.Transparency = 90
if color:
obj.ViewObject.ShapeColor = color
@@ -156,10 +157,10 @@ class Tag:
# degenerated case - no tag
PathLog.debug("Part.makeSphere(%f / 10000)" % (r1))
self.solid = Part.makeSphere(r1 / 10000)
if not R == 0: # testing is easier if the solid is not rotated
if not R == 0: # testing is easier if the solid is not rotated
angle = -PathGeom.getAngle(self.originAt(0)) * 180 / math.pi
PathLog.debug("solid.rotate(%f)" % angle)
self.solid.rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), angle)
self.solid.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle)
orig = self.originAt(z - 0.01 * self.actualHeight)
PathLog.debug("solid.translate(%s)" % orig)
self.solid.translate(orig)
@@ -188,19 +189,18 @@ class Tag:
return True
if PathGeom.isRoughly(edge.FirstParameter, param) or PathGeom.isRoughly(edge.LastParameter, param):
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))))
p1 = edge.Vertexes[0]
f1 = edge.Curve.parameter(FreeCAD.Vector(p1.X, p1.Y, p1.Z))
p2 = edge.Vertexes[1]
f2 = edge.Curve.parameter(FreeCAD.Vector(p2.X, p2.Y, p2.Z))
# 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]
# f1 = edge.Curve.parameter(FreeCAD.Vector(p1.X, p1.Y, p1.Z))
# p2 = edge.Vertexes[1]
# f2 = edge.Curve.parameter(FreeCAD.Vector(p2.X, p2.Y, p2.Z))
return False
def nextIntersectionClosestTo(self, edge, solid, refPt):
ef = edge.valueAt(edge.FirstParameter)
em = edge.valueAt((edge.FirstParameter+edge.LastParameter)/2)
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))
# ef = edge.valueAt(edge.FirstParameter)
# em = edge.valueAt((edge.FirstParameter+edge.LastParameter)/2)
# 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))
vertexes = edge.common(solid).Vertexes
if vertexes:
@@ -358,7 +358,7 @@ class MapWireToTag:
p0 = self.entry
lastP = p0
while edges:
#print("(%.2f, %.2f, %.2f) %d %d" % (p0.x, p0.y, p0.z))
# print("(%.2f, %.2f, %.2f) %d %d" % (p0.x, p0.y, p0.z))
for e in edges:
p1 = e.valueAt(e.FirstParameter)
p2 = e.valueAt(e.LastParameter)
@@ -428,7 +428,7 @@ class MapWireToTag:
shape = self.shell().common(self.tag.solid)
commands = []
rapid = None
for e,flip in self.orderAndFlipEdges(self.cleanupEdges(shape.Edges)):
for e, flip in self.orderAndFlipEdges(self.cleanupEdges(shape.Edges)):
debugEdge(e, '++++++++ %s' % ('<' if flip else '>'), False)
p1 = e.valueAt(e.FirstParameter)
p2 = e.valueAt(e.LastParameter)
@@ -478,6 +478,7 @@ class MapWireToTag:
def mappingComplete(self):
return self.complete
class _RapidEdges:
def __init__(self, rapid):
self.rapid = rapid
@@ -493,6 +494,7 @@ class _RapidEdges:
return True
return False
class PathData:
def __init__(self, obj):
PathLog.track(obj.Base.Name)
@@ -520,7 +522,7 @@ class PathData:
def findZLimits(self, edges):
# not considering arcs and spheres in Z direction, find the highes and lowest Z values
minZ = 99999999999
minZ = 99999999999
maxZ = -99999999999
for e in edges:
if self.rapid.isRapid(e):
@@ -538,7 +540,7 @@ class PathData:
def generateTags(self, obj, count, width=None, height=None, angle=None, radius=None, spacing=None):
PathLog.track(count, width, height, angle, spacing)
#for e in self.baseWire.Edges:
# for e in self.baseWire.Edges:
# debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2)
if spacing:
@@ -551,7 +553,6 @@ class PathData:
A = angle if angle else self.defaultTagAngle()
R = radius if radius else self.defaultTagRadius()
# start assigning tags on the longest segment
(shortestEdge, longestEdge) = self.shortestAndLongestPathEdge()
startIndex = 0
@@ -577,7 +578,7 @@ class PathData:
PathLog.debug(" -> lastTagLength=%.2f)" % lastTagLength)
PathLog.debug(" -> currentLength=%.2f)" % currentLength)
edgeDict = { startIndex: startCount }
edgeDict = {startIndex: startCount}
for i in range(startIndex + 1, len(self.baseWire.Edges)):
edge = self.baseWire.Edges[i]
@@ -591,8 +592,8 @@ class PathData:
for (i, count) in PathUtil.keyValueIter(edgeDict):
edge = self.baseWire.Edges[i]
PathLog.debug(" %d: %d" % (i, count))
#debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2)
#debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2)
# debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2)
# debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2)
if 0 != count:
distance = (edge.LastParameter - edge.FirstParameter) / count
for j in range(0, count):
@@ -663,18 +664,19 @@ class PathData:
def pointAtBottom(self, p):
return FreeCAD.Vector(p.x, p.y, self.minZ)
class ObjectTagDressup:
def __init__(self, obj, base):
obj.addProperty("App::PropertyLink", "Base","Base", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "The base path to modify"))
obj.addProperty("App::PropertyLength", "Width", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Width of tags."))
obj.addProperty("App::PropertyLength", "Height", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Height of tags."))
obj.addProperty("App::PropertyAngle", "Angle", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Angle of tag plunge and ascent."))
obj.addProperty("App::PropertyLength", "Radius", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Radius of the fillet for the tag."))
obj.addProperty("App::PropertyVectorList", "Positions", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Locations of inserted holding tags"))
obj.addProperty("App::PropertyIntegerList", "Disabled", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "IDs of disabled holding tags"))
obj.addProperty("App::PropertyInteger", "SegmentationFactor", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Factor determining the # of segments used to approximate rounded tags."))
obj.addProperty("App::PropertyLink", "Base", "Base", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "The base path to modify"))
obj.addProperty("App::PropertyLength", "Width", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Width of tags."))
obj.addProperty("App::PropertyLength", "Height", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Height of tags."))
obj.addProperty("App::PropertyAngle", "Angle", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Angle of tag plunge and ascent."))
obj.addProperty("App::PropertyLength", "Radius", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Radius of the fillet for the tag."))
obj.addProperty("App::PropertyVectorList", "Positions", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Locations of inserted holding tags"))
obj.addProperty("App::PropertyIntegerList", "Disabled", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "IDs of disabled holding tags"))
obj.addProperty("App::PropertyInteger", "SegmentationFactor", "Tag", QtCore.QT_TRANSLATE_NOOP("Path_DressupTag", "Factor determining the # of segments used to approximate rounded tags."))
obj.Proxy = self
obj.Base = base
@@ -684,6 +686,7 @@ class ObjectTagDressup:
def __getstate__(self):
return None
def __setstate__(self, state):
return None
@@ -697,7 +700,7 @@ class ObjectTagDressup:
if hasattr(self, "pathData"):
self.tags = self.pathData.generateTags(obj, count, obj.Width.Value, obj.Height.Value, obj.Angle, obj.Radius.Value, None)
obj.Positions = [tag.originAt(self.pathData.minZ) for tag in self.tags]
obj.Disabled = []
obj.Disabled = []
return False
else:
self.setup(obj, count)
@@ -725,9 +728,9 @@ class ObjectTagDressup:
commands = []
lastEdge = 0
lastTag = 0
sameTag = None
# sameTag = None
t = 0
inters = None
# inters = None
edge = None
segm = 50
@@ -746,7 +749,7 @@ class ObjectTagDressup:
edge = pathData.edges[lastEdge]
debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges)))
lastEdge += 1
sameTag = None
# sameTag = None
if mapper:
mapper.add(edge)
@@ -766,7 +769,6 @@ class ObjectTagDressup:
self.mappers.append(mapper)
edge = mapper.tail
if not mapper and t >= len(tags):
# gone through all tags, consume edge and move on
if edge:
@@ -783,7 +785,7 @@ class ObjectTagDressup:
edge = None
t = 0
lastCmd = Path.Command('G0', {'X': 0.0, 'Y': 0.0, 'Z': 0.0});
lastCmd = Path.Command('G0', {'X': 0.0, 'Y': 0.0, 'Z': 0.0})
outCommands = []
horizFeed = obj.Base.ToolController.HorizFeed.Value
@@ -814,7 +816,7 @@ class ObjectTagDressup:
lastCmd = cmd
outCommands.append(Path.Command(cmd.Name, params))
return Path.Path(outCommands)
def problems(self):
@@ -851,20 +853,20 @@ class ObjectTagDressup:
PathLog.debug("previousTag = %d [%s]" % (i, prev))
else:
disabled.append(i)
tag.id = i # assigne final id
tag.id = i # assigne final id
tags.append(tag)
positions.append(tag.originAt(self.pathData.minZ))
return (tags, positions, disabled)
def execute(self, obj):
#import cProfile
#pr = cProfile.Profile()
#pr.enable()
# import cProfile
# pr = cProfile.Profile()
# pr.enable()
self.doExecute(obj)
#pr.disable()
#pr.print_stats()
# pr.disable()
# pr.print_stats()
def doExecute(self,obj):
def doExecute(self, obj):
if not obj.Base:
return
if not obj.Base.isDerivedFrom("Path::Feature"):
@@ -917,10 +919,10 @@ class ObjectTagDressup:
tagID += 1
if tag.enabled:
PathLog.debug("x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ))
#debugMarker(FreeCAD.Vector(tag.x, tag.y, self.pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5)
#if tag.angle != 90:
# debugMarker(FreeCAD.Vector(tag.x, tag.y, self.pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5)
# if tag.angle != 90:
# debugCone(tag.originAt(self.pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID)
#else:
# else:
# debugCylinder(tag.originAt(self.pathData.minZ), tag.fullWidth()/2, tag.actualHeight, "tag-%02d" % tagID)
obj.Path = self.createPath(obj, self.pathData, self.tags)
@@ -931,15 +933,15 @@ class ObjectTagDressup:
try:
pathData = PathData(obj)
except ValueError:
PathLog.error(translate("PathDressup_HoldingTags", "Cannot insert holding tags for this path - please select a Profile path\n"))
PathLog.error(translate("Path_DressupTag", "Cannot insert holding tags for this path - please select a Profile path\n"))
return None
self.toolRadius = obj.Base.ToolController.Tool.Diameter / 2
self.pathData = pathData
if generate:
obj.Height = self.pathData.defaultTagHeight()
obj.Width = self.pathData.defaultTagWidth()
obj.Angle = self.pathData.defaultTagAngle()
obj.Width = self.pathData.defaultTagWidth()
obj.Angle = self.pathData.defaultTagAngle()
obj.Radius = self.pathData.defaultTagRadius()
count = HoldingTagPreferences.defaultCount()
self.generateTags(obj, count)
@@ -952,7 +954,7 @@ class ObjectTagDressup:
positions = []
disabled = []
for i, (x, y, enabled) in enumerate(triples):
#print("%d: (%.2f, %.2f) %d" % (i, x, y, enabled))
# print("%d: (%.2f, %.2f) %d" % (i, x, y, enabled))
positions.append(FreeCAD.Vector(x, y, 0))
if not enabled:
disabled.append(i)
@@ -970,16 +972,16 @@ class ObjectTagDressup:
return self.pathData.pointAtBottom(point)
def Create(baseObject, name = 'DressupTag'):
def Create(baseObject, name='DressupTag'):
'''
Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
Create(basePath, name='DressupTag') ... create tag dressup object for the given base path.
'''
if not baseObject.isDerivedFrom('Path::Feature'):
PathLog.error(translate('PathDressup_Tag', 'The selected object is not a path\n'))
PathLog.error(translate('Path_DressupTag', 'The selected object is not a path\n'))
return None
if baseObject.isDerivedFrom('Path::FeatureCompoundPython'):
PathLog.error(translate('PathDressup_Tag', 'Please select a Profile object'))
PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
return None
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
@@ -989,4 +991,4 @@ def Create(baseObject, name = 'DressupTag'):
dbo.setup(obj, True)
return obj
PathLog.notice("Loading PathDressupHoldingTags... done\n")
PathLog.notice("Loading Path_DressupTag... done\n")

View File

@@ -34,7 +34,7 @@ from PySide import QtCore
# Qt tanslation handling
def translate(text, context="PathDressup_RampEntry", disambig=None):
def translate(text, context="Path_DressupRampEntry", disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -46,8 +46,8 @@ class ObjectDressup:
def __init__(self, obj):
self.obj = obj
obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The tool controller that will be used to calculate the path"))
obj.addProperty("App::PropertyLink", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("PathDressup_RampEntry", "The base path to modify"))
obj.addProperty("App::PropertyAngle", "Angle", "Path", QtCore.QT_TRANSLATE_NOOP("PathDressup_RampEntry", "Angle of ramp."))
obj.addProperty("App::PropertyLink", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("Path_DressupRampEntry", "The base path to modify"))
obj.addProperty("App::PropertyAngle", "Angle", "Path", QtCore.QT_TRANSLATE_NOOP("Path_DressupRampEntry", "Angle of ramp."))
obj.addProperty("App::PropertyEnumeration", "Method", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Ramping Method"))
obj.addProperty("App::PropertyEnumeration", "RampFeedRate", "FeedRate", QtCore.QT_TRANSLATE_NOOP("App::Property", "Which feed rate to use for ramping"))
obj.addProperty("App::PropertySpeed", "CustomFeedRate", "FeedRate", QtCore.QT_TRANSLATE_NOOP("App::Property", "Custom feedrate"))
@@ -530,7 +530,6 @@ class ObjectDressup:
horizRapid = obj.ToolController.HorizRapid.Value
vertRapid = obj.ToolController.VertRapid.Value
for cmd in commands:
params = cmd.Parameters
zVal = params.get('Z', None)
@@ -610,8 +609,8 @@ class CommandPathDressupRampEntry:
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathDressup_RampEntry", "RampEntry Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathDressup_RampEntry", "Creates a Ramp Entry Dress-up object from a selected path")}
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_DressupRampEntry", "RampEntry Dress-up"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_DressupRampEntry", "Creates a Ramp Entry Dress-up object from a selected path")}
def IsActive(self):
if FreeCAD.ActiveDocument is not None:
@@ -653,6 +652,6 @@ class CommandPathDressupRampEntry:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('PathDressup_RampEntry', CommandPathDressupRampEntry())
FreeCADGui.addCommand('Path_DressupRampEntry', CommandPathDressupRampEntry())
PathLog.notice("Loading PathDressupRampEntry... done\n")
PathLog.notice("Loading Path_DressupRampEntry... done\n")

View File

@@ -24,10 +24,7 @@
import FreeCAD
import DraftGeomUtils
import Part
import Path
import PathScripts
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup
import PathScripts.PathUtils as PathUtils
import math
import sys
@@ -39,10 +36,12 @@ from PySide import QtCore
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule()
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class TagSolid:
def __init__(self, proxy, z, R):
self.proxy = proxy
@@ -94,7 +93,7 @@ class TagSolid:
PathLog.debug("makeFillet(%.4f)" % radius)
self.solid = self.solid.makeFillet(radius, [self.solid.Edges[0]])
#lastly determine the center of the model, we want to make sure the seam of
# lastly determine the center of the model, we want to make sure the seam of
# the tag solid points away (in the hopes it doesn't coincide with a path)
self.baseCenter = FreeCAD.Vector((proxy.ptMin.x+proxy.ptMax.x)/2, (proxy.ptMin.y+proxy.ptMax.y)/2, 0)
@@ -102,7 +101,7 @@ class TagSolid:
clone = self.solid.copy()
pos.z = 0
angle = -PathGeom.getAngle(pos - self.baseCenter) * 180 / math.pi
clone.rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), angle)
clone.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle)
pos.z = self.z - self.actualHeight * 0.01
clone.translate(pos)
return clone
@@ -112,14 +111,14 @@ class ObjectDressup:
def __init__(self, obj, base):
obj.addProperty('App::PropertyLink', 'Base','Base', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'The base path to modify'))
obj.addProperty('App::PropertyLength', 'Width', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Width of tags.'))
obj.addProperty('App::PropertyLength', 'Height', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Height of tags.'))
obj.addProperty('App::PropertyAngle', 'Angle', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Angle of tag plunge and ascent.'))
obj.addProperty('App::PropertyLength', 'Radius', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Radius of the fillet for the tag.'))
obj.addProperty('App::PropertyVectorList', 'Positions', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Locations of inserted holding tags'))
obj.addProperty('App::PropertyIntegerList', 'Disabled', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'IDs of disabled holding tags'))
obj.addProperty('App::PropertyInteger', 'SegmentationFactor', 'Tag', QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Factor determining the # of segments used to approximate rounded tags.'))
obj.addProperty('App::PropertyLink', 'Base', 'Base', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'The base path to modify'))
obj.addProperty('App::PropertyLength', 'Width', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Width of tags.'))
obj.addProperty('App::PropertyLength', 'Height', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Height of tags.'))
obj.addProperty('App::PropertyAngle', 'Angle', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Angle of tag plunge and ascent.'))
obj.addProperty('App::PropertyLength', 'Radius', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Radius of the fillet for the tag.'))
obj.addProperty('App::PropertyVectorList', 'Positions', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Locations of inserted holding tags'))
obj.addProperty('App::PropertyIntegerList', 'Disabled', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'IDs of disabled holding tags'))
obj.addProperty('App::PropertyInteger', 'SegmentationFactor', 'Tag', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Factor determining the # of segments used to approximate rounded tags.'))
obj.Proxy = self
obj.Base = base
@@ -129,31 +128,32 @@ class ObjectDressup:
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def assignDefaultValues(self):
self.obj.Width = HoldingTagPreferences.defaultWidth(self.toolRadius() * 2)
self.obj.Width = HoldingTagPreferences.defaultWidth(self.toolRadius() * 2)
self.obj.Height = HoldingTagPreferences.defaultHeight(self.toolRadius())
self.obj.Angle = HoldingTagPreferences.defaultAngle()
self.obj.Angle = HoldingTagPreferences.defaultAngle()
self.obj.Radius = HoldingTagPreferences.defaultRadius()
def execute(self, obj):
PathLog.track()
if not obj.Base:
PathLog.error(translate('PathDressup_Tag', 'No Base object found.'))
PathLog.error(translate('Path_DressupTag', 'No Base object found.'))
return
if not obj.Base.isDerivedFrom('Path::Feature'):
PathLog.error(translate('PathDressup_Tag', 'Base is not a Path::Feature object.'))
PathLog.error(translate('Path_DressupTag', 'Base is not a Path::Feature object.'))
return
if not obj.Base.Path:
PathLog.error(translate('PathDressup_Tag', 'Base doesn\'t have a Path to dress-up.'))
PathLog.error(translate('Path_DressupTag', 'Base doesn\'t have a Path to dress-up.'))
return
if not obj.Base.Path.Commands:
PathLog.error(translate('PathDressup_Tag', 'Base Path is empty.'))
PathLog.error(translate('Path_DressupTag', 'Base Path is empty.'))
return
self.obj = obj;
self.obj = obj
minZ = +sys.maxint
minX = minZ
@@ -191,8 +191,8 @@ class ObjectDressup:
maxTagZ = minZ + obj.Height.Value
lastX = 0
lastY = 0
# lastX = 0
# lastY = 0
lastZ = 0
commands = []
@@ -227,16 +227,17 @@ class ObjectDressup:
return True
return False
def Create(baseObject, name = 'DressupTag'):
def Create(baseObject, name='DressupTag'):
'''
Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
'''
if not baseObject.isDerivedFrom('Path::Feature'):
PathLog.error(translate('PathDressup_Tag', 'The selected object is not a path\n'))
PathLog.error(translate('Path_DressupTag', 'The selected object is not a path\n'))
return None
if baseObject.isDerivedFrom('Path::FeatureCompoundPython'):
PathLog.error(translate('PathDressup_Tag', 'Please select a Profile object'))
PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
return None
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
@@ -246,4 +247,4 @@ def Create(baseObject, name = 'DressupTag'):
dbo.assignDefaultValues()
return obj
PathLog.notice('Loading PathDressupTag... done\n')
PathLog.notice('Loading Path_DressupTag... done\n')

View File

@@ -21,12 +21,12 @@
# * USA *
# * *
# ***************************************************************************
import Draft
# import Draft
import FreeCAD
import FreeCADGui
import Path
import PathScripts
#import PathScripts.PathDressupTag as PathDressupTag
# import Path
# import PathScripts
# import PathScripts.PathDressupTag as PathDressupTag
import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathDressupHoldingTags as PathDressupTag
import PathScripts.PathLog as PathLog
@@ -38,26 +38,29 @@ from PySide import QtCore, QtGui
from pivy import coin
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule()
# PathLog.trackModule()
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
def addDebugDisplay():
return PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG
class PathDressupTagTaskPanel:
DataX = QtCore.Qt.ItemDataRole.UserRole
DataY = QtCore.Qt.ItemDataRole.UserRole + 1
DataZ = QtCore.Qt.ItemDataRole.UserRole + 2
DataX = QtCore.Qt.ItemDataRole.UserRole
DataY = QtCore.Qt.ItemDataRole.UserRole + 1
DataZ = QtCore.Qt.ItemDataRole.UserRole + 2
DataID = QtCore.Qt.ItemDataRole.UserRole + 3
def __init__(self, obj, viewProvider, jvoVisibility=None):
self.obj = obj
self.obj.Proxy.obj = obj
self.viewProvider = viewProvider
self.form = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTagsEdit.ui")
self.form = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTagsEdit.ui")
self.getPoint = PathGetPoint.TaskPanel(self.form.removeEditAddGroup, True)
self.jvo = PathUtils.findParentJob(obj).ViewObject
if jvoVisibility is None:
@@ -116,15 +119,15 @@ class PathDressupTagTaskPanel:
enabled = item.checkState() == QtCore.Qt.CheckState.Checked
x = item.data(self.DataX)
y = item.data(self.DataY)
#print("(%.2f, %.2f) i=%d/%s" % (x, y, i, index))
# print("(%.2f, %.2f) i=%d/%s" % (x, y, i, index))
if includeCurrent or i != index:
tags.append((x, y, enabled))
return tags
def getFields(self):
width = FreeCAD.Units.Quantity(self.form.ifWidth.text()).Value
width = FreeCAD.Units.Quantity(self.form.ifWidth.text()).Value
height = FreeCAD.Units.Quantity(self.form.ifHeight.text()).Value
angle = self.form.dsbAngle.value()
angle = self.form.dsbAngle.value()
radius = FreeCAD.Units.Quantity(self.form.ifRadius.text()).Value
tags = self.getTags(True)
@@ -154,7 +157,6 @@ class PathDressupTagTaskPanel:
self.obj.Disabled = disabled
self.isDirty = True
def updateTagsView(self):
PathLog.track()
self.form.lwTags.blockSignals(True)
@@ -185,7 +187,7 @@ class PathDressupTagTaskPanel:
if not self.obj.Proxy.generateTags(self.obj, count):
self.obj.Proxy.execute(self.obj)
self.Positions = self.obj.Positions
self.Disabled = self.obj.Disabled
self.Disabled = self.obj.Disabled
self.updateTagsView()
def updateModel(self):
@@ -214,7 +216,7 @@ class PathDressupTagTaskPanel:
def updateTagsViewWith(self, tags):
self.tags = tags
self.Positions = [FreeCAD.Vector(t[0], t[1], 0) for t in tags]
self.Disabled = [i for (i,t) in enumerate(self.tags) if not t[2]]
self.Disabled = [i for (i, t) in enumerate(self.tags) if not t[2]]
self.updateTagsView()
def deleteSelectedTag(self):
@@ -265,7 +267,7 @@ class PathDressupTagTaskPanel:
def setupUi(self):
self.Positions = self.obj.Positions
self.Disabled = self.obj.Disabled
self.Disabled = self.obj.Disabled
self.setFields()
self.whenCountChanged()
@@ -287,7 +289,6 @@ class PathDressupTagTaskPanel:
self.viewProvider.turnMarkerDisplayOn(True)
class HoldingTagMarker:
def __init__(self, point, colors):
self.point = point
@@ -320,6 +321,7 @@ class HoldingTagMarker:
self.material.diffuseColor = self.color[1] if not self.selected else self.color[2]
self.material.transparency = 0.6
class PathDressupTagViewProvider:
def __init__(self, vobj):
@@ -331,9 +333,9 @@ class PathDressupTagViewProvider:
self.debugDisplay()
def debugDisplay(self):
#if False and addDebugDisplay():
# if False and addDebugDisplay():
# if not hasattr(self.vobj, 'Debug'):
# self.vobj.addProperty('App::PropertyLink', 'Debug', 'Debug', QtCore.QT_TRANSLATE_NOOP('PathDressup_TagGui', 'Some elements for debugging'))
# self.vobj.addProperty('App::PropertyLink', 'Debug', 'Debug', QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Some elements for debugging'))
# dbg = self.vobj.Object.Document.addObject('App::DocumentObjectGroup', 'TagDebug')
# self.vobj.Debug = dbg
# return True
@@ -341,6 +343,7 @@ class PathDressupTagViewProvider:
def __getstate__(self):
return None
def __setstate__(self, state):
return None
@@ -351,9 +354,9 @@ class PathDressupTagViewProvider:
pref = PathPreferences.preferences()
# R G B A
npc = pref.GetUnsigned('DefaultPathMarkerColor', (( 85*256 + 255)*256 + 0)*256 + 255)
hpc = pref.GetUnsigned('DefaultHighlightPathColor', ((255*256 + 125)*256 + 0)*256 + 255)
dpc = pref.GetUnsigned('DefaultDisabledPathColor', ((205*256 + 205)*256 + 205)*256 + 154)
npc = pref.GetUnsigned('DefaultPathMarkerColor', ((85*256 + 255)*256 + 0) * 256 + 255)
hpc = pref.GetUnsigned('DefaultHighlightPathColor', ((255*256 + 125)*256 + 0)*256 + 255)
dpc = pref.GetUnsigned('DefaultDisabledPathColor', ((205*256 + 205)*256 + 205)*256 + 154)
self.colors = [colorForColorValue(npc), colorForColorValue(dpc), colorForColorValue(hpc)]
def attach(self, vobj):
@@ -372,7 +375,7 @@ class PathDressupTagViewProvider:
i.Group = [o for o in i.Group if o.Name != self.obj.Base.Name]
if self.obj.Base.ViewObject:
self.obj.Base.ViewObject.Visibility = False
#if self.debugDisplay() and self.vobj.Debug.ViewObject:
# if self.debugDisplay() and self.vobj.Debug.ViewObject:
# self.vobj.Debug.ViewObject.Visibility = False
def turnMarkerDisplayOn(self, display):
@@ -381,7 +384,7 @@ class PathDressupTagViewProvider:
def claimChildren(self):
PathLog.track()
#if self.debugDisplay():
# if self.debugDisplay():
# return [self.obj.Base, self.vobj.Debug]
return [self.obj.Base]
@@ -393,7 +396,7 @@ class PathDressupTagViewProvider:
job = PathUtils.findParentJob(self.obj)
job.Proxy.addOperation(arg1.Object.Base)
arg1.Object.Base = None
#if self.debugDisplay():
# if self.debugDisplay():
# self.vobj.Debug.removeObjectsFromDocument()
# self.vobj.Debug.Document.removeObject(self.vobj.Debug.Name)
# self.vobj.Debug = None
@@ -417,7 +420,7 @@ class PathDressupTagViewProvider:
def onModelChanged(self):
PathLog.track()
#if self.debugDisplay():
# if self.debugDisplay():
# self.vobj.Debug.removeObjectsFromDocument()
# for solid in self.obj.Proxy.solids:
# tag = self.obj.Document.addObject('Part::Feature', 'tag')
@@ -482,24 +485,26 @@ class PathDressupTagViewProvider:
self.panel.selectTagWithId(i)
FreeCADGui.updateGui()
def Create(baseObject, name='DressupTag'):
'''
Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
Use this command only iff the UI is up - for batch processing see PathDressupTag.Create
'''
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_Tag", "Create a Tag dressup"))
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupTag", "Create a Tag dressup"))
obj = PathDressupTag.Create(baseObject, name)
vp = PathDressupTagViewProvider(obj.ViewObject)
FreeCAD.ActiveDocument.commitTransaction()
obj.ViewObject.startEditing()
return obj
class CommandPathDressupTag:
def GetResources(self):
return {'Pixmap': 'Path-Dressup',
'MenuText': QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Tag Dress-up'),
'ToolTip': QtCore.QT_TRANSLATE_NOOP('PathDressup_Tag', 'Creates a Tag Dress-up object from a selected path')}
'MenuText': QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Tag Dress-up'),
'ToolTip': QtCore.QT_TRANSLATE_NOOP('Path_DressupTag', 'Creates a Tag Dress-up object from a selected path')}
def IsActive(self):
if FreeCAD.ActiveDocument is not None:
@@ -512,12 +517,12 @@ class CommandPathDressupTag:
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
PathLog.error(translate('PathDressup_Tag', 'Please select one path object\n'))
PathLog.error(translate('Path_DressupTag', 'Please select one path object\n'))
return
baseObject = selection[0]
# everything ok!
FreeCAD.ActiveDocument.openTransaction(translate('PathDressup_Tag', 'Create Tag Dress-up'))
FreeCAD.ActiveDocument.openTransaction(translate('Path_DressupTag', 'Create Tag Dress-up'))
FreeCADGui.addModule('PathScripts.PathDressupTagGui')
FreeCADGui.doCommand("PathScripts.PathDressupTagGui.Create(App.ActiveDocument.%s)" % baseObject.Name)
FreeCAD.ActiveDocument.commitTransaction()
@@ -525,6 +530,6 @@ class CommandPathDressupTag:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('PathDressup_Tag', CommandPathDressupTag())
FreeCADGui.addCommand('Path_DressupTag', CommandPathDressupTag())
PathLog.notice('Loading PathDressupTagGui... done\n')

View File

@@ -25,20 +25,21 @@
import FreeCAD
import FreeCADGui
import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup
from PathScripts.PathPreferences import PathPreferences
from PySide import QtCore
# Qt tanslation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class HoldingTagPreferences:
DefaultHoldingTagWidth = 'DefaultHoldingTagWidth'
DefaultHoldingTagHeight = 'DefaultHoldingTagHeight'
DefaultHoldingTagAngle = 'DefaultHoldingTagAngle'
DefaultHoldingTagRadius = 'DefaultHoldingTagRadius'
DefaultHoldingTagCount = 'DefaultHoldingTagCount'
DefaultHoldingTagWidth = 'DefaultHoldingTagWidth'
DefaultHoldingTagHeight = 'DefaultHoldingTagHeight'
DefaultHoldingTagAngle = 'DefaultHoldingTagAngle'
DefaultHoldingTagRadius = 'DefaultHoldingTagRadius'
DefaultHoldingTagCount = 'DefaultHoldingTagCount'
@classmethod
def defaultWidth(cls, ifNotSet):
@@ -55,27 +56,26 @@ class HoldingTagPreferences:
return value
@classmethod
def defaultAngle(cls, ifNotSet = 45.0):
def defaultAngle(cls, ifNotSet=45.0):
value = PathPreferences.preferences().GetFloat(cls.DefaultHoldingTagAngle, ifNotSet)
if value < 10.0:
return ifNotSet
return value
@classmethod
def defaultCount(cls, ifNotSet = 4):
def defaultCount(cls, ifNotSet=4):
value = PathPreferences.preferences().GetUnsigned(cls.DefaultHoldingTagCount, ifNotSet)
if value < 2:
return float(ifNotSet)
return float(value)
@classmethod
def defaultRadius(cls, ifNotSet = 0.0):
def defaultRadius(cls, ifNotSet=0.0):
return PathPreferences.preferences().GetFloat(cls.DefaultHoldingTagRadius, ifNotSet)
def __init__(self):
self.form = FreeCADGui.PySideUic.loadUi(":/preferences/PathDressupHoldingTags.ui")
self.label = translate("PathDressup_HoldingTag", 'Holding Tag')
self.label = translate("Path_DressupTag", 'Holding Tag')
def loadSettings(self):
self.form.ifWidth.setText(FreeCAD.Units.Quantity(self.defaultWidth(0), FreeCAD.Units.Length).UserString)

View File

@@ -33,8 +33,6 @@ import PathScripts.PathOp as PathOp
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils
import importlib
from PathScripts.PathGeom import PathGeom
from PySide import QtCore, QtGui
__title__ = "Path Operation UI base classes"
@@ -56,6 +54,7 @@ if False:
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -138,7 +137,7 @@ class ViewProvider(object):
def __setstate__(self, state):
'''__setstate__(state) ... callback on restoring a saved instance, pendant to __getstate__()
state is the dictionary returned by __getstate__().'''
self.OpName = state['OpName']
self.OpName = state['OpName']
self.OpIcon = state['OpIcon']
self.OpPageModule = state['OpPageModule']
self.OpPageClass = state['OpPageClass']
@@ -168,6 +167,7 @@ class ViewProvider(object):
PathUtil.clearExpressionEngine(vobj.Object)
return True
class TaskPanelPage(object):
'''Base class for all task panel pages.'''
@@ -186,11 +186,13 @@ class TaskPanelPage(object):
def onDirtyChanged(self, callback):
'''onDirtyChanged(callback) ... set callback when dirty state changes.'''
self.signalDirtyChanged = callback
def setDirty(self):
'''setDirty() ... mark receiver as dirty, causing the model to be recalculated if OK or Apply is pressed.'''
self.isdirty = True
if self.signalDirtyChanged:
self.signalDirtyChanged(self)
def setClean(self):
'''setClean() ... mark receiver as clean, indicating there is no need to recalculate the model even if the user presses OK or Apply.'''
self.isdirty = False
@@ -224,6 +226,7 @@ class TaskPanelPage(object):
def setTitle(self, title):
'''setTitle(title) ... sets a title for the page.'''
self.title = title
def getTitle(self, obj):
'''getTitle(obj) ... return title to be used for the receiver page.
The default implementation returns what was previously set with setTitle(title).
@@ -233,6 +236,7 @@ class TaskPanelPage(object):
def setIcon(self, icon):
'''setIcon(icon) ... sets the icon for the page.'''
self.icon = icon
def getIcon(self, icon):
'''getIcon(icon) ... return icon for page or None.
Can safely be overwritten by subclasses.'''
@@ -244,27 +248,33 @@ class TaskPanelPage(object):
Note that this function is invoked after all page controllers have been created.
Should be overwritten by subclasses.'''
pass
def modifyStandardButtons(self, buttonBox):
'''modifyStandardButtons(buttonBox) ... overwrite if the task panel standard buttons need to be modified.
Can safely be overwritten by subclasses.'''
pass
def getForm(self):
'''getForm() ... return UI form for this page.
Must be overwritten by subclasses.'''
pass
def getFields(self, obj):
'''getFields(obj) ... overwrite to transfer values from UI to obj's properties.
Can safely be overwritten by subclasses.'''
pass
def setFields(self, obj):
'''setFields(obj) ... overwrite to transfer obj's property values to UI.
Can safely be overwritten by subclasses.'''
pass
def getSignalsForUpdate(self, obj):
'''getSignalsForUpdate(obj) ... return signals which, when triggered, cause the receiver to update the model.
See also registerSignalHandlers(obj)
Can safely be overwritten by subclasses.'''
return []
def registerSignalHandlers(self, obj):
'''registerSignalHandlers(obj) ... overwrite to register custom signal handlers.
In case an update of a model is not the desired operation of a signal invocation
@@ -272,6 +282,7 @@ class TaskPanelPage(object):
manually.
Can safely be overwritten by subclasses.'''
pass
def updateData(self, obj, prop):
'''updateData(obj, prop) ... overwrite if the receiver needs to react to property changes that might not have been caused by the receiver itself.
Sometimes a model will recalculate properties based on a change of another property. In order to keep the UI up to date with such changes this
@@ -283,6 +294,7 @@ class TaskPanelPage(object):
In such a scenario the first property assignment will cause all changes in the UI of the other fields to be overwritten by setFields(obj).
You have been warned.'''
pass
def updateSelection(self, obj, sel):
'''updateSelection(obj, sel) ... overwrite to customize UI depending on current selection.
Can safely be overwritten by subclasses.'''
@@ -316,15 +328,18 @@ class TaskPanelPage(object):
if obj.ToolController != tc:
obj.ToolController = tc
class TaskPanelBaseGeometryPage(TaskPanelPage):
'''Page controller for the base geometry.'''
DataObject = QtCore.Qt.ItemDataRole.UserRole
DataObject = QtCore.Qt.ItemDataRole.UserRole
DataObjectSub = QtCore.Qt.ItemDataRole.UserRole + 1
def getForm(self):
return FreeCADGui.PySideUic.loadUi(":/panels/PageBaseGeometryEdit.ui")
def getTitle(self, obj):
return translate("PathOp", "Base Geometry")
def getFields(self, obj):
pass
@@ -348,14 +363,17 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
FreeCADGui.Selection.addSelection(obj, sub)
else:
FreeCADGui.Selection.addSelection(obj)
#FreeCADGui.updateGui()
# FreeCADGui.updateGui()
def supportsVertexes(self):
return self.features & PathOp.FeatureBaseVertexes
def supportsEdges(self):
return self.features & PathOp.FeatureBaseEdges
def supportsFaces(self):
return self.features & PathOp.FeatureBaseFaces
def supportsPanels(self):
return self.features & PathOp.FeatureBasePanels
@@ -395,7 +413,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
def addBase(self):
if self.addBaseGeometry(FreeCADGui.Selection.getSelectionEx()):
#self.obj.Proxy.execute(self.obj)
# self.obj.Proxy.execute(self.obj)
self.setFields(self.obj)
self.setDirty()
@@ -406,8 +424,8 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
self.form.baseList.takeItem(self.form.baseList.row(item))
self.setDirty()
self.updateBase()
#self.obj.Proxy.execute(self.obj)
#FreeCAD.ActiveDocument.recompute()
# self.obj.Proxy.execute(self.obj)
# FreeCAD.ActiveDocument.recompute()
def updateBase(self):
newlist = []
@@ -420,8 +438,8 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
PathLog.debug("Setting new base: %s -> %s" % (self.obj.Base, newlist))
self.obj.Base = newlist
#self.obj.Proxy.execute(self.obj)
#FreeCAD.ActiveDocument.recompute()
# self.obj.Proxy.execute(self.obj)
# FreeCAD.ActiveDocument.recompute()
def clearBase(self):
self.obj.Base = []
@@ -457,6 +475,7 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
def getTitle(self, obj):
return translate("PathOp", "Base Location")
def getFields(self, obj):
pass
@@ -483,7 +502,7 @@ class TaskPanelBaseLocationPage(TaskPanelPage):
selected = self.formLoc.baseList.selectedItems()
for item in selected:
row = self.formLoc.baseList.row(item)
if not row in deletedRows:
if row not in deletedRows:
deletedRows.append(row)
self.formLoc.baseList.removeRow(row)
self.updateLocations()
@@ -603,7 +622,6 @@ class TaskPanelDepthsPage(TaskPanelPage):
self.form.finishDepth.hide()
self.form.finishDepthLabel.hide()
def getTitle(self, obj):
return translate("PathOp", "Depths")
@@ -679,6 +697,7 @@ class TaskPanelDepthsPage(TaskPanelPage):
self.form.startDepthSet.setEnabled(False)
self.form.finalDepthSet.setEnabled(False)
class TaskPanel(object):
'''
Generic TaskPanel implementation handling the standard Path operation layout.
@@ -881,10 +900,13 @@ class TaskPanel(object):
# SelectionObserver interface
def addSelection(self, doc, obj, sub, pnt):
self.updateSelection()
def removeSelection(self, doc, obj, sub):
self.updateSelection()
def setSelection(self, doc):
self.updateSelection()
def clearSelection(self, doc):
self.updateSelection()
@@ -914,13 +936,14 @@ class CommandSetStartPoint:
def Activated(self):
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
def Create(res):
'''Create(res) ... generic implementation of a create function.
res is an instance of CommandResources. It is not expected that the user invokes
this function directly, but calls the Activated() function of the Command object
that is created in each operations Gui implementation.'''
FreeCAD.ActiveDocument.openTransaction("Create %s" % res.name)
obj = res.objFactory(res.name)
obj = res.objFactory(res.name)
if obj.Proxy:
vobj = ViewProvider(obj.ViewObject, res)
@@ -930,6 +953,7 @@ def Create(res):
FreeCAD.ActiveDocument.abortTransaction()
return None
class CommandPathOp:
'''Generic, data driven implementation of a Path operation creation command.
Instances of this class are stored in all Path operation Gui modules and can
@@ -956,6 +980,7 @@ class CommandPathOp:
def Activated(self):
return Create(self.res)
class CommandResources:
'''POD class to hold command specific resources.'''
def __init__(self, name, objFactory, opPageClass, pixmap, menuText, accelKey, toolTip):
@@ -967,13 +992,14 @@ class CommandResources:
self.accelKey = accelKey
self.toolTip = toolTip
def SetupOperation(name,
objFactory,
opPageClass,
pixmap,
menuText,
toolTip,
accelKey = None):
objFactory,
opPageClass,
pixmap,
menuText,
toolTip,
accelKey=None):
'''SetupOperation(name, objFactory, opPageClass, pixmap, menuText, toolTip, accelKey=None)
Creates an instance of CommandPathOp with the given parameters and registers the command with FreeCAD.
When activated it creates a model with proxy (by invoking objFactory), assigns a view provider to it
@@ -989,6 +1015,6 @@ def SetupOperation(name,
return command
FreeCADGui.addCommand('Set_StartPoint', CommandSetStartPoint())
FreeCADGui.addCommand('Path_SetStartPoint', CommandSetStartPoint())
FreeCAD.Console.PrintLog("Loading PathOpGui... done\n")

View File

@@ -90,7 +90,7 @@ PyObject* PathSimPy::GetResultMesh(PyObject * args)
Mesh::MeshPy *meshOuterpy = new Mesh::MeshPy(meshOuter);
Mesh::MeshObject *meshInner = new Mesh::MeshObject();
Mesh::MeshPy *meshInnerpy = new Mesh::MeshPy(meshInner);
stock->Tesselate(*meshOuter, *meshInner);
stock->Tessellate(*meshOuter, *meshInner);
PyObject *tuple = PyTuple_New(2);
PyTuple_SetItem(tuple, 0, meshOuterpy);
PyTuple_SetItem(tuple, 1, meshInnerpy);

View File

@@ -440,7 +440,7 @@ void cStock::AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4, std
facets.push_back(facet);
}
void cStock::Tesselate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner)
void cStock::Tessellate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner)
{
// reset attribs
for (int y = 0; y < m_y; y++)

View File

@@ -137,7 +137,7 @@ class cStock
public:
cStock(float px, float py, float pz, float lx, float ly, float lz, float res);
~cStock();
void Tesselate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner);
void Tessellate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner);
void CreatePocket(float x, float y, float rad, float height);
void ApplyLinearTool(Point3D & p1, Point3D & p2, cSimTool &tool);
void ApplyCircularTool(Point3D & p1, Point3D & p2, Point3D & cent, cSimTool &tool, bool isCCW);