Updated CadQuery library with mirrorX fix for issue #51

This commit is contained in:
Jeremy Wright 2015-04-23 00:38:00 -04:00
parent e7309e37ed
commit d299a74b86
2 changed files with 72 additions and 18 deletions

View File

@ -1261,7 +1261,7 @@ class Workplane(CQ):
#attempt to consolidate wires together.
consolidated = n.consolidateWires()
rotatedWires = self.plane.rotateShapes(consolidated.wires().vals(),matrix)
rotatedWires = self.plane.rotateShapes(consolidated.wires().vals(), matrix)
for w in rotatedWires:
consolidated.objects.append(w)
@ -1269,6 +1269,7 @@ class Workplane(CQ):
#attempt again to consolidate all of the wires
c = consolidated.consolidateWires()
return c
def mirrorY(self):
@ -1288,7 +1289,6 @@ class Workplane(CQ):
Future Enhancements:
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
"""
tm = Matrix()
tm.rotateY(math.pi)
@ -1307,7 +1307,6 @@ class Workplane(CQ):
Future Enhancements:
mirrorX().mirrorY() should work but doesnt, due to some FreeCAD weirdness
"""
tm = Matrix()
tm.rotateX(math.pi)
@ -1349,11 +1348,9 @@ class Workplane(CQ):
If possible, a new object with the results are returned.
if not possible, the wires remain separated
FreeCAD has a bug in Part.Wire([]) which does not create wires/edges properly somtimes
Additionally, it has a bug where a profile compose of two wires ( rathre than one )
also does not work properly
together these are a real problem.
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 ( rather than one )
also does not work properly. Together these are a real problem.
"""
wires = self.wires().vals()
if len(wires) < 2:
@ -2272,11 +2269,48 @@ class Workplane(CQ):
return self.union(boxes)
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
if isinstance(direct, tuple):
direct = Vector(direct)
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()
if centered[0]:
@ -2288,6 +2322,7 @@ class Workplane(CQ):
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)
# If we don't need to combine everything, just return the created spheres

View File

@ -17,9 +17,10 @@
License along with this library; If not, see <http://www.gnu.org/licenses/>
"""
import math,sys
import math
import cadquery
import FreeCAD
#Turns out we don't need the Part module here.
import Part as FreeCADPart
def sortWiresByBuildOrder(wireList,plane,result=[]):
"""
@ -403,9 +404,9 @@ class Plane:
correctly.
"""
if isinstance(obj,Vector):
if isinstance(obj, Vector):
return Vector(self.fG.multiply(obj.wrapped))
elif isinstance(obj,Shape):
elif isinstance(obj, cadquery.Shape):
return obj.transformShape(self.rG)
else:
raise ValueError("Dont know how to convert type %s to local coordinates" % str(type(obj)))
@ -464,7 +465,7 @@ class Plane:
newP= Plane(self.origin,newXdir,newZdir)
return newP
def rotateShapes(self,listOfShapes,rotationMatrix):
def rotateShapes(self, listOfShapes, rotationMatrix):
"""
rotate the listOfShapes by the rotationMatrix supplied.
@param listOfShapes is a list of shape objects
@ -480,24 +481,42 @@ class Plane:
#There might be a better way, but to do this rotation takes 3 steps
#transform geometry to local coordinates
#then rotate about x
#then transform back to global coordiante
#then transform back to global coordinates
resultWires = []
for w in listOfShapes:
mirrored = w.transformGeometry(rotationMatrix.wrapped)
resultWires.append(mirrored)
# 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)
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
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
#ok i will be really honest-- i cannot understand exactly why this works
#something bout the order of the transaltion and the rotation.
# the double-inverting is strange, and i dont understand it.
#something bout the order of the translation and the rotation.
# the double-inverting is strange, and I don't understand it.
r = FreeCAD.Base.Matrix()
#forward transform must rotate and adjust for origin