the test cases pass now at least
This commit is contained in:
parent
3f7d38cdeb
commit
26cd0a443d
1417
cadquery/CQ.py
1417
cadquery/CQ.py
File diff suppressed because it is too large
Load Diff
8
cadquery/README.txt
Normal file
8
cadquery/README.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
***
|
||||
Core CadQuery implementation.
|
||||
|
||||
No files should depend on or import FreeCAD , pythonOCC, or other CAD Kernel libraries!!!
|
||||
Dependencies should be on the classes provided by implementation packages, which in turn
|
||||
can depend on CAD libraries.
|
||||
|
||||
***
|
|
@ -19,20 +19,20 @@
|
|||
|
||||
|
||||
#these items point to the freecad implementation
|
||||
from .freecad_impl.geom import Plane,BoundBox,Vector
|
||||
from .freecad_impl.shapes import Shape,Vertex,Edge,Wire,Solid,Shell,Compound
|
||||
from .freecad_impl.exporters import SvgExporter, AmfExporter, JsonExporter
|
||||
from .freecad_impl.geom import Plane,BoundBox,Vector,Matrix,sortWiresByBuildOrder
|
||||
from .freecad_impl.shapes import Shape,Vertex,Edge,Face,Wire,Solid,Shell,Compound
|
||||
from .freecad_impl import exporters
|
||||
|
||||
#these items are the common implementation
|
||||
from .CQ import CQ
|
||||
from .workplane import Workplane
|
||||
from . import plugins
|
||||
|
||||
#the order of these matter
|
||||
from . import selectors
|
||||
from .CQ import CQ,CQContext,Workplane
|
||||
|
||||
|
||||
__all__ = [
|
||||
'CQ','Workplane','plugins','selectors','Plane','BoundBox',
|
||||
'Shape','Vertex','Edge','Wire','Solid','Shell','Compound',
|
||||
'SvgExporter','AmfExporter','JsonExporter',
|
||||
'CQ','Workplane','plugins','selectors','Plane','BoundBox','Matrix','Vector','sortWiresByBuildOrder',
|
||||
'Shape','Vertex','Edge','Wire','Solid','Shell','Compound','exporters',
|
||||
'plugins'
|
||||
]
|
||||
|
||||
|
|
3
cadquery/freecad_impl/README.txt
Normal file
3
cadquery/freecad_impl/README.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
It is ok for files in this directory to import FreeCAD, FreeCAD.Base, and FreeCAD.Part.
|
||||
|
||||
Other modules should _not_ depend on FreeCAD
|
|
@ -17,6 +17,9 @@
|
|||
License along with this library; If not, see <http://www.gnu.org/licenses/>
|
||||
"""
|
||||
|
||||
import FreeCAD
|
||||
from FreeCAD import Drawing
|
||||
|
||||
try:
|
||||
import xml.etree.cElementTree as ET
|
||||
except ImportError:
|
||||
|
@ -54,15 +57,8 @@ def guessUnitOfMeasure(shape):
|
|||
|
||||
return UNITS.MM
|
||||
|
||||
class Exporter(object):
|
||||
|
||||
def export(self):
|
||||
"""
|
||||
return a string representing the model exported in the specified format
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
class AmfExporter(Exporter):
|
||||
class AmfExporter(object):
|
||||
def __init__(self,tessellation):
|
||||
|
||||
self.units = "mm"
|
||||
|
@ -105,7 +101,7 @@ class AmfExporter(Exporter):
|
|||
three.js JSON object notation
|
||||
https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3.0
|
||||
"""
|
||||
class JsonExporter(Exporter):
|
||||
class JsonExporter(object):
|
||||
def __init__(self):
|
||||
|
||||
self.vertices = [];
|
||||
|
@ -135,10 +131,6 @@ class JsonExporter(Exporter):
|
|||
'nFaces' : self.nFaces
|
||||
};
|
||||
|
||||
class SvgExporter(Exporter):
|
||||
|
||||
def export(self):
|
||||
pass
|
||||
|
||||
def getPaths(freeCadSVG):
|
||||
"""
|
||||
|
@ -240,11 +232,15 @@ def getSVG(shape,opts=None):
|
|||
#)
|
||||
return svg
|
||||
|
||||
|
||||
def exportSVG(shape, fileName):
|
||||
"""
|
||||
accept a cadquery shape, and export it to the provided file
|
||||
TODO: should use file-like objects, not a fileName, and/or be able to return a string instead
|
||||
export a view of a part to svg
|
||||
"""
|
||||
svg = getSVG(shape)
|
||||
|
||||
svg = getSVG(shape.val().wrapped)
|
||||
f = open(fileName,'w')
|
||||
f.write(svg)
|
||||
f.close()
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
"""
|
||||
Copyright (C) 2011-2013 Parametric Products Intellectual Holdings, LLC
|
||||
Copyright (C) 2011-2013 Parametric Products Intellectual Holdings, LLC
|
||||
|
||||
This file is part of CadQuery.
|
||||
|
||||
CadQuery is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This file is part of CadQuery.
|
||||
|
||||
CadQuery is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
CadQuery is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
CadQuery is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; If not, see <http://www.gnu.org/licenses/>
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; If not, see <http://www.gnu.org/licenses/>
|
||||
"""
|
||||
|
||||
import math,sys
|
||||
|
@ -48,33 +48,6 @@ def sortWiresByBuildOrder(wireList,plane,result=[]):
|
|||
|
||||
return result
|
||||
|
||||
def sortWiresByBuildOrderOld(wireList,plane,result=[]):
|
||||
"""
|
||||
Tries to determine how wires should be combined into faces.
|
||||
Assume:
|
||||
The wires make up one or more faces, which could have 'holes'
|
||||
Outer wires are listed ahead of inner wires
|
||||
there are no wires inside wires inside wires ( IE, islands -- we can deal with that later on )
|
||||
none of the wires are construction wires
|
||||
Compute:
|
||||
one or more sets of wires, with the outer wire listed first, and inner ones
|
||||
Returns, list of lists.
|
||||
"""
|
||||
outerWire = wireList.pop(0)
|
||||
|
||||
remainingWires = list(wireList)
|
||||
childWires = []
|
||||
for w in wireList:
|
||||
if plane.isWireInside(outerWire,w):
|
||||
childWires.append(remainingWires.pop(0))
|
||||
else:
|
||||
#doesnt match, assume this wire is a new outer
|
||||
result.append([outerWire] + childWires)
|
||||
return sortWiresByBuildOrder(remainingWires,plane,result)
|
||||
|
||||
result.append([outerWire] + childWires)
|
||||
return result
|
||||
|
||||
class Vector(object):
|
||||
"""
|
||||
Create a 3-dimensional vector
|
||||
|
@ -212,6 +185,25 @@ class Vector(object):
|
|||
def __eq__(self,other):
|
||||
return self.wrapped.__eq__(other)
|
||||
|
||||
class Matrix:
|
||||
"""
|
||||
A 3d , 4x4 transformation matrix.
|
||||
|
||||
Used to move geometry in space.
|
||||
"""
|
||||
def __init__(self,matrix=None):
|
||||
if matrix == None:
|
||||
self.wrapped = FreeCAD.Base.Matrix()
|
||||
else:
|
||||
self.wrapped = matrix
|
||||
|
||||
def rotateX(self,angle):
|
||||
self.wrapped.rotateX(angle)
|
||||
|
||||
def rotateY(self,angle):
|
||||
self.wrapped.rotateY(angle)
|
||||
|
||||
|
||||
class Plane:
|
||||
"""
|
||||
A 2d coordinate system in space, with the x-y axes on the a plane, and a particular point as the origin.
|
||||
|
@ -329,6 +321,7 @@ class Plane:
|
|||
|
||||
self.setOrigin3d(origin)
|
||||
|
||||
|
||||
def setOrigin3d(self,originVector):
|
||||
"""
|
||||
Move the origin of the plane, leaving its orientation and xDirection unchanged.
|
||||
|
@ -417,6 +410,7 @@ class Plane:
|
|||
else:
|
||||
raise ValueError("Dont know how to convert type %s to local coordinates" % str(type(obj)))
|
||||
|
||||
|
||||
def toWorldCoords(self, tuplePoint):
|
||||
"""
|
||||
Convert a point in local coordinates to global coordinates.
|
||||
|
@ -433,6 +427,7 @@ class Plane:
|
|||
v = Vector(tuplePoint[0],tuplePoint[1],tuplePoint[2])
|
||||
return Vector(self.rG.multiply(v.wrapped))
|
||||
|
||||
|
||||
def rotated(self,rotate=Vector(0,0,0)):
|
||||
"""
|
||||
returns a copy of this plane, rotated about the specified axes, as measured from horizontal
|
||||
|
@ -453,7 +448,7 @@ class Plane:
|
|||
rotate = rotate.multiply(math.pi / 180.0 )
|
||||
|
||||
#compute rotation matrix
|
||||
m = Base.Matrix()
|
||||
m = FreeCAD.Base.Matrix()
|
||||
m.rotateX(rotate.x)
|
||||
m.rotateY(rotate.y)
|
||||
m.rotateZ(rotate.z)
|
||||
|
@ -473,7 +468,7 @@ class Plane:
|
|||
#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.
|
||||
r = Base.Matrix()
|
||||
r = FreeCAD.Base.Matrix()
|
||||
|
||||
#forward transform must rotate and adjust for origin
|
||||
(r.A11, r.A12, r.A13 ) = (self.xDir.x, self.xDir.y, self.xDir.z )
|
||||
|
@ -484,7 +479,14 @@ class Plane:
|
|||
(invR.A14,invR.A24,invR.A34) = (self.origin.x,self.origin.y,self.origin.z)
|
||||
|
||||
( self.rG,self.fG ) = ( invR,invR.inverse() )
|
||||
|
||||
|
||||
def computeTransform(self,tMatrix):
|
||||
"""
|
||||
Computes the 2-d projection of the supplied matrix
|
||||
"""
|
||||
|
||||
rm = self.fG.multiply(tMatrix.wrapped).multiply(self.rG)
|
||||
return Matrix(rm)
|
||||
|
||||
class BoundBox(object):
|
||||
"A BoundingBox for an object or set of objects. Wraps the FreeCAD one"
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
object each one returns, so these are better grouped by the type of object they return.
|
||||
(who would know that Part.makeCircle() returns an Edge, but Part.makePolygon() returns a Wire ?
|
||||
"""
|
||||
from cadquery import Vector
|
||||
from cadquery import Vector,BoundBox
|
||||
import FreeCAD
|
||||
import FreeCAD.Part
|
||||
|
||||
|
@ -65,7 +65,7 @@ class Shape(object):
|
|||
def cast(cls,obj,forConstruction = False):
|
||||
"Returns the right type of wrapper, given a FreeCAD object"
|
||||
s = obj.ShapeType
|
||||
if type(obj) == Base.Vector:
|
||||
if type(obj) == FreeCAD.Base.Vector:
|
||||
return Vector(obj)
|
||||
tr = None
|
||||
|
||||
|
@ -99,7 +99,9 @@ class Shape(object):
|
|||
|
||||
tr.forConstruction = forConstruction
|
||||
return tr
|
||||
|
||||
#TODO: all these should move into the exporters folder.
|
||||
#we dont need a bunch of exporting code stored in here!
|
||||
#
|
||||
def exportStl(self,fileName):
|
||||
self.wrapped.exportStl(fileName)
|
||||
|
||||
|
@ -254,6 +256,7 @@ class Shape(object):
|
|||
|
||||
def transformShape(self,tMatrix):
|
||||
"""
|
||||
tMatrix is a matrix object.
|
||||
returns a copy of the ojbect, transformed by the provided matrix,
|
||||
with all objects keeping their type
|
||||
"""
|
||||
|
@ -265,6 +268,8 @@ class Shape(object):
|
|||
|
||||
def transformGeometry(self,tMatrix):
|
||||
"""
|
||||
tMatrix is a matrix object.
|
||||
|
||||
returns a copy of the object, but with geometry transformed insetad of just
|
||||
rotated.
|
||||
|
||||
|
@ -311,9 +316,9 @@ class Edge(Shape):
|
|||
#self.endPoint = None
|
||||
|
||||
self.edgetypes= {
|
||||
Part.Line : 'LINE',
|
||||
Part.ArcOfCircle : 'ARC',
|
||||
Part.Circle : 'CIRCLE'
|
||||
FreeCAD.Part.Line : 'LINE',
|
||||
FreeCAD.Part.ArcOfCircle : 'ARC',
|
||||
FreeCAD.Part.Circle : 'CIRCLE'
|
||||
}
|
||||
|
||||
def geomType(self):
|
||||
|
@ -363,7 +368,7 @@ class Edge(Shape):
|
|||
|
||||
@classmethod
|
||||
def makeCircle(cls,radius,pnt=(0,0,0),dir=(0,0,1),angle1=360.0,angle2=360):
|
||||
return Edge(Part.makeCircle(radius,toVector(pnt),toVector(dir),angle1,angle2))
|
||||
return Edge(FreeCAD.Part.makeCircle(radius,toVector(pnt),toVector(dir),angle1,angle2))
|
||||
|
||||
@classmethod
|
||||
def makeSpline(cls,listOfVector):
|
||||
|
@ -375,7 +380,7 @@ class Edge(Shape):
|
|||
"""
|
||||
vecs = [v.wrapped for v in listOfVector]
|
||||
|
||||
spline = Part.BSplineCurve()
|
||||
spline = FreeCAD.Part.BSplineCurve()
|
||||
spline.interpolate(vecs,False)
|
||||
return Edge(spline.toShape())
|
||||
|
||||
|
@ -389,7 +394,7 @@ class Edge(Shape):
|
|||
:param v3: end vector
|
||||
:return: an edge object through the three points
|
||||
"""
|
||||
arc = Part.Arc(v1.wrapped,v2.wrapped,v3.wrapped)
|
||||
arc = FreeCAD.Part.Arc(v1.wrapped,v2.wrapped,v3.wrapped)
|
||||
e = Edge(arc.toShape())
|
||||
return e #arcane and undocumented, this creates an Edge object
|
||||
|
||||
|
@ -401,7 +406,7 @@ class Edge(Shape):
|
|||
:param v2: Vector that represents the second point
|
||||
:return: A linear edge between the two provided points
|
||||
"""
|
||||
return Edge(Part.makeLine(v1.toTuple(),v2.toTuple() ))
|
||||
return Edge(FreeCAD.Part.makeLine(v1.toTuple(),v2.toTuple() ))
|
||||
|
||||
|
||||
class Wire(Shape):
|
||||
|
@ -420,7 +425,7 @@ class Wire(Shape):
|
|||
:param listOfWires:
|
||||
:return:
|
||||
"""
|
||||
return Shape.cast(Part.Wire([w.wrapped for w in listOfWires]))
|
||||
return Shape.cast(FreeCAD.Part.Wire([w.wrapped for w in listOfWires]))
|
||||
|
||||
@classmethod
|
||||
def assembleEdges(cls,listOfEdges):
|
||||
|
@ -432,7 +437,7 @@ class Wire(Shape):
|
|||
"""
|
||||
fCEdges = [a.wrapped for a in listOfEdges]
|
||||
|
||||
wa = Wire( Part.Wire(fCEdges) )
|
||||
wa = Wire( FreeCAD.Part.Wire(fCEdges) )
|
||||
return wa
|
||||
|
||||
@classmethod
|
||||
|
@ -444,13 +449,13 @@ class Wire(Shape):
|
|||
:param normal: vector representing the direction of the plane the circle should lie in
|
||||
:return:
|
||||
"""
|
||||
w = Wire(Part.Wire([Part.makeCircle(radius,center.wrapped,normal.wrapped)]))
|
||||
w = Wire(FreeCAD.Part.Wire([FreeCAD.Part.makeCircle(radius,center.wrapped,normal.wrapped)]))
|
||||
return w
|
||||
|
||||
@classmethod
|
||||
def makePolygon(cls,listOfVertices,forConstruction=False):
|
||||
#convert list of tuples into Vectors.
|
||||
w = Wire(Part.makePolygon([i.wrapped for i in listOfVertices]))
|
||||
w = Wire(FreeCAD.Part.makePolygon([i.wrapped for i in listOfVertices]))
|
||||
w.forConstruction = forConstruction
|
||||
return w
|
||||
|
||||
|
@ -461,7 +466,7 @@ class Wire(Shape):
|
|||
By default a cylindrical surface is used to create the helix. If
|
||||
the fourth parameter is set (the apex given in degree) a conical surface is used instead'
|
||||
"""
|
||||
return Wire(Part.makeHelix(pitch,height,radius,angle))
|
||||
return Wire(FreeCAD.Part.makeHelix(pitch,height,radius,angle))
|
||||
|
||||
|
||||
class Face(Shape):
|
||||
|
@ -473,9 +478,9 @@ class Face(Shape):
|
|||
|
||||
self.facetypes = {
|
||||
#TODO: bezier,bspline etc
|
||||
Part.Plane : 'PLANE',
|
||||
Part.Sphere : 'SPHERE',
|
||||
Part.Cone : 'CONE'
|
||||
FreeCAD.Part.Plane : 'PLANE',
|
||||
FreeCAD.Part.Sphere : 'SPHERE',
|
||||
FreeCAD.Part.Cone : 'CONE'
|
||||
}
|
||||
|
||||
def geomType(self):
|
||||
|
@ -501,7 +506,7 @@ class Face(Shape):
|
|||
|
||||
@classmethod
|
||||
def makePlane(cls,length,width,basePnt=None,dir=None):
|
||||
return Face(Part.makePlan(length,width,toVector(basePnt),toVector(dir)))
|
||||
return Face(FreeCAD.Part.makePlan(length,width,toVector(basePnt),toVector(dir)))
|
||||
|
||||
@classmethod
|
||||
def makeRuledSurface(cls,edgeOrWire1,edgeOrWire2,dist=None):
|
||||
|
@ -510,7 +515,7 @@ class Face(Shape):
|
|||
Create a ruled surface out of two edges or wires. If wires are used then
|
||||
these must have the same
|
||||
"""
|
||||
return Shape.cast(Part.makeRuledSurface(edgeOrWire1.obj,edgeOrWire2.obj,dist))
|
||||
return Shape.cast(FreeCAD.Part.makeRuledSurface(edgeOrWire1.obj,edgeOrWire2.obj,dist))
|
||||
|
||||
def cut(self,faceToCut):
|
||||
"Remove a face from another one"
|
||||
|
@ -536,7 +541,7 @@ class Shell(Shape):
|
|||
|
||||
@classmethod
|
||||
def makeShell(cls,listOfFaces):
|
||||
return Shell(Part.makeShell([i.obj for i in listOfFaces]))
|
||||
return Shell(FreeCAD.Part.makeShell([i.obj for i in listOfFaces]))
|
||||
|
||||
|
||||
class Solid(Shape):
|
||||
|
@ -563,7 +568,7 @@ class Solid(Shape):
|
|||
makeBox(length,width,height,[pnt,dir]) -- Make a box located\nin pnt with the d
|
||||
imensions (length,width,height)\nBy default pnt=Vector(0,0,0) and dir=Vector(0,0,1)'
|
||||
"""
|
||||
return Shape.cast(Part.makeBox(length,width,height,pnt.wrapped,dir.wrapped))
|
||||
return Shape.cast(FreeCAD.Part.makeBox(length,width,height,pnt.wrapped,dir.wrapped))
|
||||
|
||||
@classmethod
|
||||
def makeCone(cls,radius1,radius2,height,pnt=Vector(0,0,0),dir=Vector(0,0,1),angleDegrees=360):
|
||||
|
@ -572,7 +577,7 @@ class Solid(Shape):
|
|||
Make a cone with given radii and height\nBy default pnt=Vector(0,0,0),
|
||||
dir=Vector(0,0,1) and angle=360'
|
||||
"""
|
||||
return Shape.cast(Part.makeCone(radius1,radius2,height,pnt.wrapped,dir.wrapped,angleDegrees))
|
||||
return Shape.cast(FreeCAD.Part.makeCone(radius1,radius2,height,pnt.wrapped,dir.wrapped,angleDegrees))
|
||||
|
||||
@classmethod
|
||||
def makeCylinder(cls,radius,height,pnt=Vector(0,0,0),dir=Vector(0,0,1),angleDegrees=360):
|
||||
|
@ -581,7 +586,7 @@ class Solid(Shape):
|
|||
Make a cylinder with a given radius and height
|
||||
By default pnt=Vector(0,0,0),dir=Vector(0,0,1) and angle=360'
|
||||
"""
|
||||
return Shape.cast(Part.makeCylinder(radius,height,pnt.wrapped,dir.wrapped,angleDegrees))
|
||||
return Shape.cast(FreeCAD.Part.makeCylinder(radius,height,pnt.wrapped,dir.wrapped,angleDegrees))
|
||||
|
||||
@classmethod
|
||||
def makeTorus(cls,radius1,radius2,pnt=None,dir=None,angleDegrees1=None,angleDegrees2=None):
|
||||
|
@ -591,7 +596,7 @@ class Solid(Shape):
|
|||
By default pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0
|
||||
,angle1=360 and angle=360'
|
||||
"""
|
||||
return Shape.cast(Part.makeTorus(radius1,radius2,pnt,dir,angleDegrees1,angleDegrees2))
|
||||
return Shape.cast(FreeCAD.Part.makeTorus(radius1,radius2,pnt,dir,angleDegrees1,angleDegrees2))
|
||||
|
||||
@classmethod
|
||||
def sweep(cls,profileWire,pathWire):
|
||||
|
@ -610,11 +615,11 @@ class Solid(Shape):
|
|||
"""
|
||||
makes a loft from a list of wires
|
||||
The wires will be converted into faces when possible-- it is presumed that nobody ever actually
|
||||
wants to make an infinitely thin shell for a real part.
|
||||
wants to make an infinitely thin shell for a real FreeCAD.Part.
|
||||
"""
|
||||
#the True flag requests building a solid instead of a shell.
|
||||
|
||||
return Shape.cast(Part.makeLoft([i.wrapped for i in listOfWire],True))
|
||||
return Shape.cast(FreeCAD.Part.makeLoft([i.wrapped for i in listOfWire],True))
|
||||
|
||||
@classmethod
|
||||
def makeWedge(cls,xmin,ymin,zmin,z2min,x2min,xmax,ymax,zmax,z2max,x2max,pnt=None,dir=None):
|
||||
|
@ -624,7 +629,7 @@ class Solid(Shape):
|
|||
Make a wedge located in pnt\nBy default pnt=Vector(0,0,0) and dir=Vec
|
||||
tor(0,0,1)'
|
||||
"""
|
||||
return Shape.cast(Part.makeWedge(xmin,ymin,zmin,z2min,x2min,xmax,ymax,zmax,z2max,x2max,pnt,dir))
|
||||
return Shape.cast(FreeCAD.Part.makeWedge(xmin,ymin,zmin,z2min,x2min,xmax,ymax,zmax,z2max,x2max,pnt,dir))
|
||||
|
||||
@classmethod
|
||||
def makeSphere(cls,radius,pnt=None,angleDegrees1=None,angleDegrees2=None,angleDegrees3=None):
|
||||
|
@ -633,7 +638,7 @@ class Solid(Shape):
|
|||
Make a sphere with a giv
|
||||
en radius\nBy default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0, angle2=90 and angle3=360'
|
||||
"""
|
||||
return Solid(Part.makeSphere(radius,pnt,angleDegrees1,angleDegrees2,angleDegrees3))
|
||||
return Solid(FreeCAD.Part.makeSphere(radius,pnt,angleDegrees1,angleDegrees2,angleDegrees3))
|
||||
|
||||
@classmethod
|
||||
def extrudeLinearWithRotation(cls,outerWire,innerWires,vecCenter, vecNormal,angleDegrees):
|
||||
|
@ -674,12 +679,12 @@ class Solid(Shape):
|
|||
#make a ruled surface for each set of wires
|
||||
sides = []
|
||||
for w1,w2 in zip(startWires,endWires):
|
||||
rs = Part.makeRuledSurface(w1,w2)
|
||||
rs = FreeCAD.Part.makeRuledSurface(w1,w2)
|
||||
sides.append(rs)
|
||||
|
||||
#make faces for the top and bottom
|
||||
startFace = Part.Face(startWires)
|
||||
endFace = Part.Face(endWires)
|
||||
startFace = FreeCAD.Part.Face(startWires)
|
||||
endFace = FreeCAD.Part.Face(endWires)
|
||||
|
||||
#collect all the faces from the sides
|
||||
faceList = [ startFace]
|
||||
|
@ -687,8 +692,8 @@ class Solid(Shape):
|
|||
faceList.extend(s.Faces)
|
||||
faceList.append(endFace)
|
||||
|
||||
shell = Part.makeShell(faceList)
|
||||
solid = Part.makeSolid(shell)
|
||||
shell = FreeCAD.Part.makeShell(faceList)
|
||||
solid = FreeCAD.Part.makeSolid(shell)
|
||||
return Shape.cast(solid)
|
||||
|
||||
@classmethod
|
||||
|
@ -725,7 +730,7 @@ class Solid(Shape):
|
|||
for w in innerWires:
|
||||
freeCADWires.append(w.wrapped)
|
||||
|
||||
f = Part.Face(freeCADWires)
|
||||
f = FreeCAD.Part.Face(freeCADWires)
|
||||
result = f.extrude(vecNormal.wrapped)
|
||||
|
||||
return Shape.cast(result)
|
||||
|
@ -789,7 +794,7 @@ class Compound(Shape):
|
|||
Create a compound out of a list of shapes
|
||||
"""
|
||||
solids = [s.wrapped for s in listOfShapes]
|
||||
c = Part.Compound(solids)
|
||||
c = FreeCAD.Part.Compound(solids)
|
||||
return Shape.cast( c)
|
||||
|
||||
def fuse(self,toJoin):
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import re
|
||||
import math
|
||||
from cadquery import Vector,Edge,Vertex,Face,Solid,Shell,Compound
|
||||
|
||||
class Selector(object):
|
||||
"""
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
"""
|
||||
|
||||
import math
|
||||
from . import CQ
|
||||
from cadquery import Vector
|
||||
|
||||
from cadquery import Vector,CQ,CQContext,Plane,Wire
|
||||
|
||||
class Workplane(CQ):
|
||||
"""
|
||||
|
|
16
runtests.py
Normal file
16
runtests.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
import sys
|
||||
from tests import *
|
||||
import cadquery
|
||||
import unittest
|
||||
|
||||
#if you are on python 2.7, you can use -m uniitest discover.
|
||||
#but this is required for python 2.6.6 on windows. FreeCAD0.12 will not load
|
||||
#on py 2.7.x on win
|
||||
suite = unittest.TestSuite()
|
||||
|
||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCadObjects.TestCadObjects))
|
||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestWorkplanes.TestWorkplanes))
|
||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCQSelectors.TestCQSelectors))
|
||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCadQuery.TestCadQuery))
|
||||
|
||||
unittest.TextTestRunner().run(suite)
|
1
tests/README.txt
Normal file
1
tests/README.txt
Normal file
|
@ -0,0 +1 @@
|
|||
It is OK for tests to import implementations like FreeCAD directly.
|
|
@ -13,8 +13,9 @@ import unittest,sys
|
|||
import os.path
|
||||
|
||||
#my modules
|
||||
from TestBase import *
|
||||
from tests import BaseTest,makeUnitCube,makeUnitSquareWire
|
||||
from cadquery import *
|
||||
from cadquery import selectors
|
||||
|
||||
class TestCQSelectors(BaseTest):
|
||||
|
||||
|
@ -122,8 +123,8 @@ class TestCQSelectors(BaseTest):
|
|||
#faces parallel to Z axis
|
||||
self.assertEqual(2, c.faces("|Z").size())
|
||||
#TODO: provide short names for ParallelDirSelector
|
||||
self.assertEqual(2, c.faces(ParallelDirSelector(Vector((0,0,1)))).size()) #same thing as above
|
||||
self.assertEqual(2, c.faces(ParallelDirSelector(Vector((0,0,-1)))).size()) #same thing as above
|
||||
self.assertEqual(2, c.faces(selectors.ParallelDirSelector(Vector((0,0,1)))).size()) #same thing as above
|
||||
self.assertEqual(2, c.faces(selectors.ParallelDirSelector(Vector((0,0,-1)))).size()) #same thing as above
|
||||
|
||||
#just for fun, vertices on faces parallel to z
|
||||
self.assertEqual(8, c.faces("|Z").vertices().size())
|
||||
|
@ -164,17 +165,17 @@ class TestCQSelectors(BaseTest):
|
|||
#nearest vertex to origin is (0,0,0)
|
||||
t = Vector(0.1,0.1,0.1)
|
||||
|
||||
v = c.vertices(NearestToPointSelector(t)).vals()[0]
|
||||
v = c.vertices(selectors.NearestToPointSelector(t)).vals()[0]
|
||||
self.assertTupleAlmostEquals((0.0,0.0,0.0),(v.X,v.Y,v.Z),3)
|
||||
|
||||
t = Vector(0.1,0.1,0.2)
|
||||
#nearest edge is the vertical side edge, 0,0,0 -> 0,0,1
|
||||
e = c.edges(NearestToPointSelector(t)).vals()[0]
|
||||
v = c.edges(NearestToPointSelector(t)).vertices().vals()
|
||||
e = c.edges(selectors.NearestToPointSelector(t)).vals()[0]
|
||||
v = c.edges(selectors.NearestToPointSelector(t)).vertices().vals()
|
||||
self.assertEqual(2,len(v))
|
||||
|
||||
#nearest solid is myself
|
||||
s = c.solids(NearestToPointSelector(t)).vals()
|
||||
s = c.solids(selectors.NearestToPointSelector(t)).vals()
|
||||
self.assertEqual(1,len(s))
|
||||
|
||||
def testFaceCount(self):
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#system modules
|
||||
import sys
|
||||
|
||||
#my modules
|
||||
|
||||
import from cadquery import *
|
||||
|
||||
|
||||
import unittest
|
||||
from tests import BaseTest
|
||||
import FreeCAD
|
||||
from cadquery import *
|
||||
|
||||
class TestCadObjects(BaseTest):
|
||||
|
||||
def testVectorConstructors(self):
|
||||
|
@ -56,4 +56,7 @@ class TestCadObjects(BaseTest):
|
|||
|
||||
def testVertices(self):
|
||||
e = Shape.cast(FreeCAD.Part.makeLine((0,0,0),(1,1,0)))
|
||||
self.assertEquals(2,len(e.Vertices()))
|
||||
self.assertEquals(2,len(e.Vertices()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -7,6 +7,8 @@ import math,sys,os.path,time
|
|||
|
||||
#my modules
|
||||
from cadquery import *
|
||||
from cadquery import exporters
|
||||
from tests import BaseTest,writeStringToFile,makeUnitCube,readFileAsString,makeUnitSquareWire,makeCube
|
||||
|
||||
#where unit test output will be saved
|
||||
OUTDIR = "c:/temp"
|
||||
|
@ -739,16 +741,6 @@ class TestCadQuery(BaseTest):
|
|||
self.saveModel(s3)
|
||||
|
||||
|
||||
def testTwistedGear3(self):
|
||||
pts = plugins.make_gear(14.5,10,2.5) #make involutes
|
||||
s = Workplane("XY").polyline(pts).twistExtrude(4.0,8.0)
|
||||
#s2 = s.faces(">Z").workplane().transformed(rotate=Vector(0,0,8)).polyline(pts).twistExtrude(4.0,-8.0,combine=False)
|
||||
#s3 = s.union(s2)
|
||||
#s.val().exportStl("c:\\temp\\pleasework3.stl")
|
||||
#s3.val().exportStl("c:\\temp\\pleasework5.stl")
|
||||
self.saveModel(s)
|
||||
|
||||
|
||||
def testEnclosure(self):
|
||||
"""
|
||||
Builds an electronics enclosure
|
||||
|
|
|
@ -3,7 +3,7 @@ __author__ = 'dcowden'
|
|||
from cadquery import *
|
||||
|
||||
import unittest,sys
|
||||
import MakeTestObjects
|
||||
from tests import MakeTestObjects
|
||||
import SVGexporter
|
||||
|
||||
class TestCadQuery(unittest.TestCase):
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
#my modules
|
||||
from cadquery import *
|
||||
from tests import BaseTest,toTuple
|
||||
|
||||
class TestPlane(BaseTest):
|
||||
|
||||
class TestWorkplanes(BaseTest):
|
||||
|
||||
def testYZPlaneOrigins(self):
|
||||
#xy plane-- with origin at x=0.25
|
||||
|
|
|
@ -32,7 +32,7 @@ def makeCube(size):
|
|||
def toTuple(v):
|
||||
"convert a vector or a vertex to a 3-tuple: x,y,z"
|
||||
pnt = v
|
||||
if type(v) == Base.Vector:
|
||||
if type(v) == FreeCAD.Base.Vector:
|
||||
return (v.Point.x,v.Point.y,v.Point.z)
|
||||
elif type(v) == Vector:
|
||||
return v.toTuple()
|
||||
|
@ -45,3 +45,5 @@ class BaseTest(unittest.TestCase):
|
|||
def assertTupleAlmostEquals(self,expected,actual,places):
|
||||
for i,j in zip(actual,expected):
|
||||
self.assertAlmostEquals(i,j,places)
|
||||
|
||||
__all__ = [ 'TestCadObjects','TestCadQuery','TestCQSelectors','TestWorkplanes']
|
||||
|
|
Loading…
Reference in New Issue
Block a user