Added adaptive length algorithm.
This commit is contained in:
parent
c70cd7b21e
commit
15c1d153c4
|
@ -62,7 +62,7 @@ class Length:
|
||||||
Fixed = 'fixed'
|
Fixed = 'fixed'
|
||||||
Adaptive = 'adaptive'
|
Adaptive = 'adaptive'
|
||||||
Custom = 'custom'
|
Custom = 'custom'
|
||||||
All = [Fixed, Custom]
|
All = [Adaptive, Fixed, Custom]
|
||||||
|
|
||||||
# Chord
|
# Chord
|
||||||
# A class to represent the start and end point of a path command. If the underlying
|
# A class to represent the start and end point of a path command. If the underlying
|
||||||
|
@ -83,7 +83,7 @@ class Chord (object):
|
||||||
self.End = end
|
self.End = end
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Chord([%g, %g, %g] -> [%g, %g, %g]) -> %s" % (self.Start.x, self.Start.y, self.Start.z, self.End.x, self.Start.y, self.Start.z, self.End - self.Start)
|
return "Chord([%g, %g, %g] -> [%g, %g, %g])" % (self.Start.x, self.Start.y, self.Start.z, self.End.x, self.End.y, self.End.z)
|
||||||
|
|
||||||
def moveTo(self, newEnd):
|
def moveTo(self, newEnd):
|
||||||
#print("Chord(%s -> %s)" % (self.End, newEnd))
|
#print("Chord(%s -> %s)" % (self.End, newEnd))
|
||||||
|
@ -139,6 +139,13 @@ class Chord (object):
|
||||||
def getAngleXY(self):
|
def getAngleXY(self):
|
||||||
return self.getAngle(FreeCAD.Vector(1,0,0))
|
return self.getAngle(FreeCAD.Vector(1,0,0))
|
||||||
|
|
||||||
|
def offsetBy(self, distance):
|
||||||
|
angle = self.getAngleXY() - math.pi/2
|
||||||
|
dx = distance * math.cos(angle)
|
||||||
|
dy = distance * math.sin(angle)
|
||||||
|
d = FreeCAD.Vector(dx, dy, 0)
|
||||||
|
return Chord(self.Start + d, self.End + d)
|
||||||
|
|
||||||
def g1Command(self):
|
def g1Command(self):
|
||||||
return Path.Command("G1", {"X": self.End.x, "Y": self.End.y})
|
return Path.Command("G1", {"X": self.End.x, "Y": self.End.y})
|
||||||
|
|
||||||
|
@ -152,6 +159,37 @@ class Chord (object):
|
||||||
def connectsTo(self, chord):
|
def connectsTo(self, chord):
|
||||||
return self.End == chord.Start
|
return self.End == chord.Start
|
||||||
|
|
||||||
|
def lineEquation(self):
|
||||||
|
if self.End.x != self.Start.x:
|
||||||
|
slope = (self.End.y - self.Start.y) / (self.End.x - self.Start.x)
|
||||||
|
offset = self.Start.y - self.Start.x * slope
|
||||||
|
return (offset, slope)
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
def intersection(self, chord, emergencyOffset = 0):
|
||||||
|
itsOffset, itsSlope = chord.lineEquation()
|
||||||
|
myOffset, mySlope = self.lineEquation()
|
||||||
|
x = 0
|
||||||
|
y = 0
|
||||||
|
if itsSlope is not None and mySlope is not None:
|
||||||
|
if itsSlope == mySlope:
|
||||||
|
# Now this is wierd, but it happens when the path folds onto itself
|
||||||
|
angle = self.getAngleXY()
|
||||||
|
x = self.End.x + emergencyOffset * math.cos(angle)
|
||||||
|
y = self.End.y + emergencyOffset * math.sin(angle)
|
||||||
|
else:
|
||||||
|
x = (myOffset - itsOffset) / (itsSlope - mySlope)
|
||||||
|
y = myOffset + mySlope * x
|
||||||
|
elif itsSlope is not None:
|
||||||
|
x = self.Start.x
|
||||||
|
y = itsOffset + x * itsSlope
|
||||||
|
elif mySlope is not None:
|
||||||
|
x = chord.Start.x
|
||||||
|
y = myOffset + x * mySlope
|
||||||
|
else:
|
||||||
|
print("Now this really sucks")
|
||||||
|
|
||||||
|
return (x, y)
|
||||||
|
|
||||||
class ObjectDressup:
|
class ObjectDressup:
|
||||||
|
|
||||||
|
@ -201,10 +239,25 @@ class ObjectDressup:
|
||||||
circle.update({"X": inChord.End.x, "Y": inChord.End.y})
|
circle.update({"X": inChord.End.x, "Y": inChord.End.y})
|
||||||
return [ Path.Command("G3", circle) ]
|
return [ Path.Command("G3", circle) ]
|
||||||
|
|
||||||
|
def adaptiveBoneLength(self, obj, inChord, outChord, angle):
|
||||||
|
iChord = inChord.offsetBy(self.toolRadius)
|
||||||
|
oChord = outChord.offsetBy(self.toolRadius)
|
||||||
|
x,y = iChord.intersection(oChord, self.toolRadius)
|
||||||
|
dest = inChord.moveTo(FreeCAD.Vector(x, y, inChord.End.z))
|
||||||
|
destAngle = dest.getAngleXY()
|
||||||
|
distance = dest.getLength() - self.toolRadius * math.fabs(math.cos(destAngle - angle))
|
||||||
|
#print("adapt")
|
||||||
|
#print(" in = %s -> %s" % (inChord, iChord))
|
||||||
|
#print(" out = %s -> %s" % (outChord, oChord))
|
||||||
|
#print(" = (%.2f, %.2f) -> %.2f (%.2f %.2f) -> %.2f" % (x, y, dest.getLength(), destAngle/math.pi, angle/math.pi, distance))
|
||||||
|
return distance
|
||||||
|
|
||||||
def inOutBoneCommands(self, obj, inChord, outChord, angle, fixedLength):
|
def inOutBoneCommands(self, obj, inChord, outChord, angle, fixedLength):
|
||||||
length = fixedLength
|
length = fixedLength
|
||||||
if obj.Length == Length.Custom:
|
if obj.Length == Length.Custom:
|
||||||
length = obj.Custom
|
length = obj.Custom
|
||||||
|
if obj.Length == Length.Adaptive:
|
||||||
|
length = self.adaptiveBoneLength(obj, inChord, outChord, angle)
|
||||||
x = length * math.cos(angle);
|
x = length * math.cos(angle);
|
||||||
y = length * math.sin(angle);
|
y = length * math.sin(angle);
|
||||||
boneChordIn = inChord.moveBy(x, y, 0)
|
boneChordIn = inChord.moveBy(x, y, 0)
|
||||||
|
@ -226,7 +279,7 @@ class ObjectDressup:
|
||||||
|
|
||||||
def dogbone(self, obj, inChord, outChord):
|
def dogbone(self, obj, inChord, outChord):
|
||||||
boneAngle = self.dogboneAngle(obj, inChord, outChord)
|
boneAngle = self.dogboneAngle(obj, inChord, outChord)
|
||||||
length = self.toolRadius * 0.2929 # 0.2929 = 1 - 1/sqrt(2) + (a tiny bit)
|
length = self.toolRadius * 0.41422 # 0.41422 = 2/sqrt(2) - 1 + (a tiny bit)
|
||||||
return self.inOutBoneCommands(obj, inChord, outChord, boneAngle, length)
|
return self.inOutBoneCommands(obj, inChord, outChord, boneAngle, length)
|
||||||
|
|
||||||
def tboneHorizontal(self, obj, inChord, outChord):
|
def tboneHorizontal(self, obj, inChord, outChord):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user