Path calculation through intersections - enhanced robustness.
This commit is contained in:
parent
e7968a95f6
commit
2159923c4b
|
@ -335,9 +335,13 @@ class ObjectDressup:
|
|||
|
||||
def adaptiveBoneLength(self, obj, inChord, outChord, boneAngle):
|
||||
cornerDistance, cornerAngle = self.cornerDistanceAndAngle(obj, inChord, outChord)
|
||||
if cornerAngle == boneAngle:
|
||||
# there is something weird happening if the boneAngle came from a horizontal/vertical t-bone
|
||||
# for some reason pi/2 is not equal to pi/2
|
||||
if math.fabs(cornerAngle - boneAngle) < 0.00001:
|
||||
# moving directly towards the corner
|
||||
debugPrint("adaptive - on target: %.2f - %.2f" % (cornerDistance, self.toolRadius))
|
||||
return cornerDistance - self.toolRadius
|
||||
debugPrint("adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (cornerAngle/math.pi, boneAngle/math.pi, cornerAngle - boneAngle))
|
||||
|
||||
# The bones root and end point form a triangle with the intersection of the tool path
|
||||
# with the toolRadius circle around the bone end point.
|
||||
|
@ -348,6 +352,7 @@ class ObjectDressup:
|
|||
beta = math.fabs(addAngle(boneAngle, -cornerAngle))
|
||||
D = (cornerDistance / self.toolRadius) * math.sin(beta)
|
||||
if D > 1: # no intersection
|
||||
debugPrint("adaptive - no intersection - no bone")
|
||||
return 0
|
||||
gamma = math.asin(D)
|
||||
alpha = math.pi - beta - gamma
|
||||
|
@ -359,17 +364,37 @@ class ObjectDressup:
|
|||
boneDistance2 = self.toolRadius * math.sin(alpha2) / math.sin(beta2)
|
||||
boneDistance = min(boneDistance, boneDistance2)
|
||||
|
||||
debugPrint("corner=%.2f * %.2f -> bone=%.2f * %.2f" % (cornerDistance, cornerAngle, boneDistance, boneAngle))
|
||||
debugPrint("adaptive corner=%.2f * %.2f -> bone=%.2f * %.2f" % (cornerDistance, cornerAngle, boneDistance, boneAngle))
|
||||
return boneDistance
|
||||
|
||||
def smoothChordCommands(self, obj, inChord, outChord, edge, bone, corner, smooth, color):
|
||||
def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color):
|
||||
ppt = None
|
||||
pptDistance = 0
|
||||
for pt in DraftGeomUtils.findIntersection(edge, pivotEdge):
|
||||
#debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2)
|
||||
distance = (pt - refPt).Length
|
||||
if not ppt or pptDistance < distance:
|
||||
ppt = pt
|
||||
pptDistance = distance
|
||||
if not ppt:
|
||||
tangent = DraftGeomUtils.findDistance(pivot, edge)
|
||||
if tangent:
|
||||
ppt = pivot + tangent
|
||||
else:
|
||||
ppt = inChord.Start
|
||||
#debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2)
|
||||
return ppt
|
||||
|
||||
def smoothChordCommands(self, obj, inChord, outChord, edge, bone, corner, smooth, color = None):
|
||||
if smooth == 0:
|
||||
debugPrint(" No smoothing requested")
|
||||
return [ inChord.g1Command(), outChord.g1Command() ]
|
||||
|
||||
d = 'in'
|
||||
refPoint = inChord.Start
|
||||
if smooth == Smooth.Out:
|
||||
d = 'out'
|
||||
refPoint = outChord.End
|
||||
|
||||
if DraftGeomUtils.areColinear(inChord.asEdge(), outChord.asEdge()):
|
||||
debugPrint(" straight edge %s" % d)
|
||||
|
@ -381,7 +406,7 @@ class ObjectDressup:
|
|||
for e in bone.Edges:
|
||||
for pt in DraftGeomUtils.findIntersection(edge, e, True):
|
||||
if pt != corner:
|
||||
distance = (pt - inChord.End).Length
|
||||
distance = (pt - refPoint).Length
|
||||
if not pivot or pivotDistance > distance:
|
||||
pivot = pt
|
||||
pivotDistance = distance
|
||||
|
@ -390,14 +415,10 @@ class ObjectDressup:
|
|||
|
||||
if pivot:
|
||||
debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color)
|
||||
inTangent = DraftGeomUtils.findDistance(pivot, inChord.asEdge(), True)
|
||||
if not inTangent:
|
||||
inTangent = inChord.Start - pivot
|
||||
outTangent = DraftGeomUtils.findDistance(pivot, outChord.asEdge(), True)
|
||||
if not outTangent:
|
||||
outTangent = outChord.End - pivot
|
||||
t1 = pivot + inTangent
|
||||
t2 = pivot + outTangent
|
||||
|
||||
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)
|
||||
|
||||
commands = []
|
||||
if t1 != inChord.Start:
|
||||
|
@ -450,7 +471,7 @@ class ObjectDressup:
|
|||
oChord = Chord(outChord.Start + offset, outChord.End + offset)
|
||||
iLine = iChord.asLine()
|
||||
oLine = oChord.asLine()
|
||||
cornerEdge = Part.Shape([iLine, oLine])
|
||||
cornerShape = Part.Shape([iLine, oLine])
|
||||
|
||||
# construct a shape representing the cut made by the bone
|
||||
vt0 = FreeCAD.Vector( 0, self.toolRadius, 0)
|
||||
|
@ -469,7 +490,7 @@ class ObjectDressup:
|
|||
boneWire = Part.Shape([boneTop,boneArc,boneBot])
|
||||
boneWire.rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), boneAngle * 180 / math.pi)
|
||||
boneWire.translate(inChord.End)
|
||||
self.boneShapes = [cornerEdge, boneWire]
|
||||
self.boneShapes = [cornerShape, boneWire]
|
||||
|
||||
bones.extend(self.smoothChordCommands(obj, inChord, boneInChord, Part.Edge(iLine), boneWire, corner, smooth & Smooth.In, (1., 0., 0.)))
|
||||
bones.extend(self.smoothChordCommands(obj, boneOutChord, outChord, Part.Edge(oLine), boneWire, corner, smooth & Smooth.Out, (0., 1., 0.)))
|
||||
|
@ -555,7 +576,7 @@ class ObjectDressup:
|
|||
self.bones.append((boneId, loc, enabled, inaccessible))
|
||||
|
||||
self.boneId = boneId
|
||||
if debugDogbone and boneId == 0:
|
||||
if debugDogbone and boneId != 4:
|
||||
bones = self.boneCommands(obj, False, inChord, outChord, smooth)
|
||||
else:
|
||||
bones = self.boneCommands(obj, enabled, inChord, outChord, smooth)
|
||||
|
@ -585,10 +606,10 @@ class ObjectDressup:
|
|||
self.bones = []
|
||||
self.locationBlacklist = set()
|
||||
|
||||
for thisCmd in obj.Base.Path.Commands:
|
||||
if thisCmd.Name in movecommands:
|
||||
thisChord = lastChord.moveToParameters(thisCmd.Parameters)
|
||||
thisIsACandidate = self.canAttachDogbone(thisCmd, thisChord)
|
||||
for thisCommand in obj.Base.Path.Commands:
|
||||
if thisCommand.Name in movecommands:
|
||||
thisChord = lastChord.moveToParameters(thisCommand.Parameters)
|
||||
thisIsACandidate = self.canAttachDogbone(thisCommand, thisChord)
|
||||
|
||||
if thisIsACandidate and lastCommand and self.shouldInsertDogbone(obj, lastChord, thisChord):
|
||||
boneId, lastCommand = self.insertBone(boneId, obj, lastChord, thisChord, commands, Smooth.InAndOut)
|
||||
|
@ -597,14 +618,16 @@ class ObjectDressup:
|
|||
if self.shouldInsertDogbone(obj, lastChord, chord):
|
||||
boneId, lastCommand = self.insertBone(boneId, obj, lastChord, chord, commands, Smooth.In)
|
||||
lastCommand = None
|
||||
commands.append(thisCmd)
|
||||
commands.append(thisCommand)
|
||||
elif thisIsACandidate:
|
||||
lastCommand = thisCmd
|
||||
if lastCommand:
|
||||
commands.append(lastCommand)
|
||||
lastCommand = thisCommand
|
||||
else:
|
||||
if lastCommand:
|
||||
commands.append(lastCommand)
|
||||
lastCommand = None
|
||||
commands.append(thisCmd)
|
||||
commands.append(thisCommand)
|
||||
|
||||
if lastChord.isAPlungeMove() and thisIsACandidate:
|
||||
oddsAndEnds.append(thisChord)
|
||||
|
@ -614,7 +637,7 @@ class ObjectDressup:
|
|||
if lastCommand:
|
||||
commands.append(lastCommand)
|
||||
lastCommand = None
|
||||
commands.append(thisCmd)
|
||||
commands.append(thisCommand)
|
||||
#for cmd in commands:
|
||||
# debugPrint("cmd = '%s'" % cmd)
|
||||
path = Path.Path(commands)
|
||||
|
@ -723,6 +746,19 @@ class TaskPanel:
|
|||
self.form.customLabel.setEnabled(customSelected)
|
||||
self.updateBoneList()
|
||||
|
||||
if debugDogbone:
|
||||
for obj in FreeCAD.ActiveDocument.Objects:
|
||||
if obj.Name.startswith('Shape'):
|
||||
FreeCAD.ActiveDocument.removeObject(obj.Name)
|
||||
if hasattr(self.obj.Proxy, "shapes"):
|
||||
print("showing shapes attribute")
|
||||
for shapes in self.obj.Proxy.shapes.itervalues():
|
||||
for shape in shapes:
|
||||
Part.show(shape)
|
||||
else:
|
||||
print("no shapes attribute found")
|
||||
|
||||
|
||||
def updateModel(self):
|
||||
self.getFields()
|
||||
self.updateUI()
|
||||
|
@ -746,14 +782,6 @@ class TaskPanel:
|
|||
self.form.custom.setValue(self.obj.Custom)
|
||||
self.updateUI()
|
||||
|
||||
if hasattr(self.obj.Proxy, "shapes"):
|
||||
print("showing shapes attribute")
|
||||
for shapes in self.obj.Proxy.shapes.itervalues():
|
||||
for shape in shapes:
|
||||
Part.show(shape)
|
||||
else:
|
||||
print("no shapes attribute found")
|
||||
|
||||
|
||||
def open(self):
|
||||
self.s = SelObserver()
|
||||
|
|
Loading…
Reference in New Issue
Block a user