Updated CadQuery library with mirrorX fix for issue #51
This commit is contained in:
parent
e7309e37ed
commit
d299a74b86
|
@ -1269,6 +1269,7 @@ class Workplane(CQ):
|
||||||
|
|
||||||
#attempt again to consolidate all of the wires
|
#attempt again to consolidate all of the wires
|
||||||
c = consolidated.consolidateWires()
|
c = consolidated.consolidateWires()
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def mirrorY(self):
|
def mirrorY(self):
|
||||||
|
@ -1288,7 +1289,6 @@ class Workplane(CQ):
|
||||||
|
|
||||||
Future Enhancements:
|
Future Enhancements:
|
||||||
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
||||||
|
|
||||||
"""
|
"""
|
||||||
tm = Matrix()
|
tm = Matrix()
|
||||||
tm.rotateY(math.pi)
|
tm.rotateY(math.pi)
|
||||||
|
@ -1307,7 +1307,6 @@ class Workplane(CQ):
|
||||||
|
|
||||||
Future Enhancements:
|
Future Enhancements:
|
||||||
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
|
||||||
|
|
||||||
"""
|
"""
|
||||||
tm = Matrix()
|
tm = Matrix()
|
||||||
tm.rotateX(math.pi)
|
tm.rotateX(math.pi)
|
||||||
|
@ -1349,11 +1348,9 @@ class Workplane(CQ):
|
||||||
If possible, a new object with the results are returned.
|
If possible, a new object with the results are returned.
|
||||||
if not possible, the wires remain separated
|
if not possible, the wires remain separated
|
||||||
|
|
||||||
FreeCAD has a bug in Part.Wire([]) which does not create wires/edges properly somtimes
|
FreeCAD has a bug in Part.Wire([]) which does not create wires/edges properly sometimes
|
||||||
Additionally, it has a bug where a profile compose of two wires ( rathre than one )
|
Additionally, it has a bug where a profile compose of two wires ( rather than one )
|
||||||
also does not work properly
|
also does not work properly. Together these are a real problem.
|
||||||
|
|
||||||
together these are a real problem.
|
|
||||||
"""
|
"""
|
||||||
wires = self.wires().vals()
|
wires = self.wires().vals()
|
||||||
if len(wires) < 2:
|
if len(wires) < 2:
|
||||||
|
@ -2272,11 +2269,48 @@ class Workplane(CQ):
|
||||||
return self.union(boxes)
|
return self.union(boxes)
|
||||||
|
|
||||||
def sphere(self, radius, direct=(0, 0, 1), angle1=-90, angle2=90, angle3=360, centered=(True, True, True), combine=True):
|
def sphere(self, radius, direct=(0, 0, 1), angle1=-90, angle2=90, angle3=360, centered=(True, True, True), combine=True):
|
||||||
|
"""
|
||||||
|
Returns a 3D sphere with the specified radius for each point on the stack
|
||||||
|
|
||||||
|
:param radius: The radius of the sphere
|
||||||
|
:type radius: float > 0
|
||||||
|
:param direct: The direction axis for the creation of the sphere
|
||||||
|
:type direct: A three-tuple
|
||||||
|
:param angle1: The first angle to sweep the sphere arc through
|
||||||
|
:type angle1: float > 0
|
||||||
|
:param angle2: The second angle to sweep the sphere arc through
|
||||||
|
:type angle2: float > 0
|
||||||
|
:param angle3: The third angle to sweep the sphere arc through
|
||||||
|
:type angle3: float > 0
|
||||||
|
:param centered: A three-tuple of booleans that determines whether the sphere is centered on each axis origin
|
||||||
|
:param combine: Whether the results should be combined with other solids on the stack (and each other)
|
||||||
|
:type combine: true to combine shapes, false otherwise
|
||||||
|
:return: A sphere object for each point on the stack
|
||||||
|
|
||||||
|
Centered is a tuple that describes whether the sphere should be centered on the x,y, and z axes. If true,
|
||||||
|
the sphere is centered on the respective axis relative to the workplane origin, if false, the workplane center
|
||||||
|
will represent the lower bound of the resulting sphere
|
||||||
|
|
||||||
|
One sphere is created for each item on the current stack. If no items are on the stack, one box using
|
||||||
|
the current workplane center is created.
|
||||||
|
|
||||||
|
If combine is true, the result will be a single object on the stack:
|
||||||
|
If a solid was found in the chain, the result is that solid with all spheres produced fused onto it
|
||||||
|
otherwise, the result is the combination of all the produced boxes
|
||||||
|
|
||||||
|
If combine is false, the result will be a list of the spheres produced
|
||||||
|
"""
|
||||||
|
|
||||||
# Convert the direction tuple to a vector, if needed
|
# Convert the direction tuple to a vector, if needed
|
||||||
if isinstance(direct, tuple):
|
if isinstance(direct, tuple):
|
||||||
direct = Vector(direct)
|
direct = Vector(direct)
|
||||||
|
|
||||||
def _makesphere(pnt):
|
def _makesphere(pnt):
|
||||||
|
"""
|
||||||
|
Inner function that is used to create a sphere for each point/object on the workplane
|
||||||
|
:param pnt: The center point for the sphere
|
||||||
|
:return: A CQ Solid object representing a sphere
|
||||||
|
"""
|
||||||
(xp, yp, zp) = pnt.toTuple()
|
(xp, yp, zp) = pnt.toTuple()
|
||||||
|
|
||||||
if centered[0]:
|
if centered[0]:
|
||||||
|
@ -2288,6 +2322,7 @@ class Workplane(CQ):
|
||||||
|
|
||||||
return Solid.makeSphere(radius, Vector(xp, yp, zp), direct, angle1, angle2, angle3)
|
return Solid.makeSphere(radius, Vector(xp, yp, zp), direct, angle1, angle2, angle3)
|
||||||
|
|
||||||
|
# We want a sphere for each point on the workplane
|
||||||
spheres = self.eachpoint(_makesphere, True)
|
spheres = self.eachpoint(_makesphere, True)
|
||||||
|
|
||||||
# If we don't need to combine everything, just return the created spheres
|
# If we don't need to combine everything, just return the created spheres
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
License along with this library; If not, see <http://www.gnu.org/licenses/>
|
License along with this library; If not, see <http://www.gnu.org/licenses/>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import math,sys
|
import math
|
||||||
|
import cadquery
|
||||||
import FreeCAD
|
import FreeCAD
|
||||||
#Turns out we don't need the Part module here.
|
import Part as FreeCADPart
|
||||||
|
|
||||||
def sortWiresByBuildOrder(wireList,plane,result=[]):
|
def sortWiresByBuildOrder(wireList,plane,result=[]):
|
||||||
"""
|
"""
|
||||||
|
@ -405,7 +406,7 @@ class Plane:
|
||||||
"""
|
"""
|
||||||
if isinstance(obj, Vector):
|
if isinstance(obj, Vector):
|
||||||
return Vector(self.fG.multiply(obj.wrapped))
|
return Vector(self.fG.multiply(obj.wrapped))
|
||||||
elif isinstance(obj,Shape):
|
elif isinstance(obj, cadquery.Shape):
|
||||||
return obj.transformShape(self.rG)
|
return obj.transformShape(self.rG)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Dont know how to convert type %s to local coordinates" % str(type(obj)))
|
raise ValueError("Dont know how to convert type %s to local coordinates" % str(type(obj)))
|
||||||
|
@ -480,24 +481,42 @@ class Plane:
|
||||||
#There might be a better way, but to do this rotation takes 3 steps
|
#There might be a better way, but to do this rotation takes 3 steps
|
||||||
#transform geometry to local coordinates
|
#transform geometry to local coordinates
|
||||||
#then rotate about x
|
#then rotate about x
|
||||||
#then transform back to global coordiante
|
#then transform back to global coordinates
|
||||||
|
|
||||||
resultWires = []
|
resultWires = []
|
||||||
for w in listOfShapes:
|
for w in listOfShapes:
|
||||||
mirrored = w.transformGeometry(rotationMatrix.wrapped)
|
mirrored = w.transformGeometry(rotationMatrix.wrapped)
|
||||||
|
|
||||||
|
# If the first vertex of the second wire is not coincident with the first or last vertices of the first wire
|
||||||
|
# we have to fix the wire so that it will mirror correctly
|
||||||
|
if (mirrored.wrapped.Vertexes[0].X == w.wrapped.Vertexes[0].X and
|
||||||
|
mirrored.wrapped.Vertexes[0].Y == w.wrapped.Vertexes[0].Y and
|
||||||
|
mirrored.wrapped.Vertexes[0].Z == w.wrapped.Vertexes[0].Z) or \
|
||||||
|
(mirrored.wrapped.Vertexes[0].X == w.wrapped.Vertexes[-1].X and
|
||||||
|
mirrored.wrapped.Vertexes[0].Y == w.wrapped.Vertexes[-1].Y and
|
||||||
|
mirrored.wrapped.Vertexes[0].Z == w.wrapped.Vertexes[-1].Z):
|
||||||
|
|
||||||
resultWires.append(mirrored)
|
resultWires.append(mirrored)
|
||||||
|
else:
|
||||||
|
# Make sure that our mirrored edges meet up and are ordered properly
|
||||||
|
aEdges = w.wrapped.Edges
|
||||||
|
aEdges.extend(mirrored.wrapped.Edges)
|
||||||
|
comp = FreeCADPart.Compound(aEdges)
|
||||||
|
mirroredWire = comp.connectEdgesToWires(False).Wires[0]
|
||||||
|
|
||||||
|
resultWires.append(cadquery.Shape.cast(mirroredWire))
|
||||||
|
|
||||||
return resultWires
|
return resultWires
|
||||||
|
|
||||||
|
|
||||||
def _calcTransforms(self):
|
def _calcTransforms(self):
|
||||||
"""
|
"""
|
||||||
Computes transformation martrices to convert betwene local and global coordinates
|
Computes transformation martrices to convert between local and global coordinates
|
||||||
"""
|
"""
|
||||||
#r is the forward transformation matrix from world to local coordinates
|
#r is the forward transformation matrix from world to local coordinates
|
||||||
#ok i will be really honest-- i cannot understand exactly why this works
|
#ok i will be really honest-- i cannot understand exactly why this works
|
||||||
#something bout the order of the transaltion and the rotation.
|
#something bout the order of the translation and the rotation.
|
||||||
# the double-inverting is strange, and i dont understand it.
|
# the double-inverting is strange, and I don't understand it.
|
||||||
r = FreeCAD.Base.Matrix()
|
r = FreeCAD.Base.Matrix()
|
||||||
|
|
||||||
#forward transform must rotate and adjust for origin
|
#forward transform must rotate and adjust for origin
|
||||||
|
|
Loading…
Reference in New Issue
Block a user