| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | __title__ = "FreeCAD OpenSCAD Workbench - CSG exporter Version" |
| | __author__ = "Keith Sloan <keith@sloan-home.co.uk>" |
| | __url__ = ["http://www.sloan-home.co.uk/Export/Export.html"] |
| |
|
| | import FreeCAD |
| | from builtins import open as pyopen |
| |
|
| | if FreeCAD.GuiUp: |
| | gui = True |
| | else: |
| | gui = False |
| |
|
| | |
| | |
| | |
| | |
| | params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD") |
| | fa = params.GetFloat('exportFa', 12.0) |
| | fs = params.GetFloat('exportFs', 2.0) |
| | conv = params.GetInt('exportConvexity', 10) |
| | fafs = '$fa = %f, $fs = %f' % (fa, fs) |
| | convexity = 'convexity = %d' % conv |
| | |
| | |
| | |
| |
|
| | def center(b): |
| | if b == 2: |
| | return 'true' |
| | else: |
| | return 'false' |
| |
|
| |
|
| | def check_multmatrix(csg, ob, x, y, z): |
| | b = FreeCAD.Vector(x,y,z) |
| | if ob.Placement.isNull(): |
| | return 0 |
| | elif ob.Placement.Rotation.isNull() and \ |
| | (ob.Placement.Base - b).Length < 1e-6: |
| | return 2 |
| | else: |
| | m = ob.Placement.toMatrix() |
| | |
| | csg.write("multmatrix([["+str(m.A11)+", "+str(m.A12)+", "+str(m.A13)+",\ |
| | "+str(m.A14)+"], ["\ |
| | +str(m.A21)+", "+str(m.A22)+", "+str(m.A23)+", "+str(m.A24)+"], ["\ |
| | +str(m.A31)+", "+str(m.A32)+", "+str(m.A33)+", "+str(m.A34)+"], [\ |
| | 0, 0, 0, 1]]){\n") |
| | return 1 |
| |
|
| |
|
| | def mesh2polyhedron(mesh): |
| | pointstr = ','.join(['[%f,%f,%f]' % tuple(vec) for vec in mesh.Topology[0]]) |
| | trianglestr = ','.join(['[%d,%d,%d]' % tuple(tri) for tri in mesh.Topology[1]]) |
| | |
| | |
| | return 'polyhedron ( points = [%s], faces = [%s]);' % (pointstr, trianglestr) |
| |
|
| |
|
| | def vector2d(v): |
| | return [v[0],v[1]] |
| |
|
| |
|
| | def vertexs2polygon(vertex): |
| | pointstr = ','.join(['[%f, %f]' % tuple(vector2d(v.Point)) for v in vertex]) |
| | return 'polygon ( points = [%s], paths = undef, convexity = 1);}' % pointstr |
| |
|
| |
|
| | def shape2polyhedron(shape): |
| | import MeshPart |
| | return mesh2polyhedron(MeshPart.meshFromShape(Shape=shape,\ |
| | Deflection = params.GetFloat('meshdeflection', 0.0))) |
| |
|
| |
|
| | def process_object(csg,ob): |
| | print("Placement") |
| | print("Pos : "+str(ob.Placement.Base)) |
| | print("axis : "+str(ob.Placement.Rotation.Axis)) |
| | print("angle : "+str(ob.Placement.Rotation.Angle)) |
| |
|
| | if ob.TypeId == "Part::Sphere": |
| | print("Sphere Radius : "+str(ob.Radius)) |
| | check_multmatrix(csg, ob, 0, 0, 0) |
| | csg.write("sphere($fn = 0, "+fafs+", r = "+str(ob.Radius)+");\n") |
| |
|
| | elif ob.TypeId == "Part::Box": |
| | print("cube : ("+ str(ob.Length)+","+str(ob.Width)+","+str(ob.Height)+")") |
| | mm = check_multmatrix(csg,ob,-ob.Length/2,-ob.Width/2,-ob.Height/2) |
| | csg.write("cube (size = ["+str(ob.Length.Value)+", "+str(ob.Width.Value)+", "+str(ob.Height.Value)+"], center = "+center(mm)+");\n") |
| | if mm == 1 : csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Cylinder": |
| | print("cylinder : Height "+str(ob.Height) + " Radius "+str(ob.Radius)) |
| | mm = check_multmatrix(csg, ob, 0, 0, -ob.Height/2) |
| | csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height.Value) + ", r1 = "+str(ob.Radius.Value)+\ |
| | ", r2 = " + str(ob.Radius.Value) + ", center = "+center(mm)+");\n") |
| | if mm == 1 : csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Cone": |
| | print("cone : Height "+str(ob.Height) + " Radius1 "+str(ob.Radius1)+" Radius2 "+str(ob.Radius2)) |
| | mm = check_multmatrix(csg, ob, 0, 0, -ob.Height/2) |
| | csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height.Value)+ ", r1 = "+str(ob.Radius1.Value)+\ |
| | ", r2 = "+str(ob.Radius2.Value)+", center = "+center(mm)+");\n") |
| | if mm == 1 : csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Torus": |
| | print("Torus") |
| | print(ob.Radius1) |
| | print(ob.Radius2) |
| | if ob.Angle3 == 360.00: |
| | mm = check_multmatrix(csg, ob, 0, 0, 0) |
| | csg.write("rotate_extrude("+convexity+", $fn = 0, "+fafs+")\n") |
| | csg.write("multmatrix([[1, 0, 0, "+str(ob.Radius1)+"], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])\n") |
| | csg.write("circle($fn = 0, "+fafs+", r = "+str(ob.Radius2)+");\n") |
| | if mm == 1 : csg.write("}\n") |
| | else: |
| | csg.write('%s\n' % shape2polyhedron(ob.Shape)) |
| |
|
| | elif ob.TypeId == "Part::Prism": |
| | import math |
| | f = str(ob.Polygon) |
| | r = str(ob.Circumradius) |
| | h = str(ob.Height.Value) |
| | mm = check_multmatrix(csg, ob, 0, 0, -float(h)/2) |
| | csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\ |
| | ", r2 = "+r+", center = "+center(mm)+");\n") |
| | if mm == 1: csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::RegularPolygon": |
| | mm = check_multmatrix(csg, ob, 0, 0, -float(h)/2) |
| | csg.write("circle($fn = "+str(ob.NumberOfSides)+", "+fafs+", r = "+str(ob.Radius)+");\n") |
| | if mm == 1: csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Extrusion": |
| | print("Extrusion") |
| | print(ob.Base) |
| | print(ob.Base.Name) |
| | if ob.Base.isDerivedFrom('Part::Part2DObjectPython') and \ |
| | hasattr(ob.Base,'Proxy') and hasattr(ob.Base.Proxy, 'TypeId'): |
| | ptype = ob.Base.Proxy.TypeId |
| | if ptype == "Polygon": |
| | f = str(ob.Base.FacesNumber) |
| | r = str(ob.Base.Radius) |
| | h = str(ob.Dir[2]) |
| | print("Faces : " + f) |
| | print("Radius : " + r) |
| | print("Height : " + h) |
| | mm = check_multmatrix(csg,ob,0,0,-float(h)/2) |
| | csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\ |
| | ", r2 = "+r+", center = "+center(mm)+");\n") |
| | if mm == 1: csg.write("}\n") |
| |
|
| | elif ptype == "Circle": |
| | r = str(ob.Base.Radius) |
| | h = str(ob.Dir[2]) |
| | print("Radius : " + r) |
| | print("Height : " + h) |
| | mm = check_multmatrix(csg,ob,0,0,-float(h)/2) |
| | csg.write("cylinder($fn = 0, "+fafs+", h = "+h+", r1 = "+r+\ |
| | ", r2 = "+r+", center = "+center(mm)+");\n") |
| | if mm == 1: csg.write("}\n") |
| |
|
| | elif ptype == "Wire": |
| | print("Wire extrusion") |
| | print(ob.Base) |
| | mm = check_multmatrix(csg, ob, 0, 0, 0) |
| | csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = "+center(mm)+", "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n") |
| | csg.write(vertexs2polygon(ob.Base.Shape.Vertexes)) |
| | if mm == 1: csg.write("}\n") |
| |
|
| | elif ob.Base.isDerivedFrom('Part::Plane'): |
| | mm = check_multmatrix(csg,ob,0,0,0) |
| | csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = true, "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n") |
| | csg.write("square (size = ["+str(ob.Base.Length.Value)+", "+str(ob.Base.Width.Value)+"], center = "+center(mm)+");\n}\n") |
| | if mm == 1: csg.write("}\n") |
| | elif ob.Base.Name.startswith('this_is_a_bad_idea'): |
| | pass |
| | else: |
| | pass |
| |
|
| | elif ob.TypeId == "Part::Cut": |
| | print("Cut") |
| | csg.write("difference() {\n") |
| | process_object(csg,ob.Base) |
| | process_object(csg,ob.Tool) |
| | csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Fuse": |
| | print("union") |
| | csg.write("union() {\n") |
| | process_object(csg,ob.Base) |
| | process_object(csg,ob.Tool) |
| | csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::Common": |
| | print("intersection") |
| | csg.write("intersection() {\n") |
| | process_object(csg,ob.Base) |
| | process_object(csg,ob.Tool) |
| | csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::MultiFuse": |
| | print("Multi Fuse / union") |
| | csg.write("union() {\n") |
| | for subobj in ob.Shapes: |
| | process_object(csg,subobj) |
| | csg.write("}\n") |
| |
|
| | elif ob.TypeId == "Part::MultiCommon": |
| | print("Multi Common / intersection") |
| | csg.write("intersection() {\n") |
| | for subobj in ob.Shapes: |
| | process_object(csg,subobj) |
| | csg.write("}\n") |
| |
|
| | elif ob.isDerivedFrom('Part::Feature'): |
| | print("Part::Feature") |
| | mm = check_multmatrix(csg,ob,0,0,0) |
| | csg.write('%s\n' % shape2polyhedron(ob.Shape)) |
| | if mm == 1 : csg.write("}\n") |
| |
|
| | def export(exportList, filename): |
| | "called when FreeCAD exports a file" |
| |
|
| | |
| | print("\nStart Export 0.1d\n") |
| | print("Open Output File") |
| | csg = pyopen(filename,'w') |
| | print("Write Initial Output") |
| | |
| | csg.write("// CSG file generated from FreeCAD %s\n" % \ |
| | '.'.join(FreeCAD.Version()[0:3])) |
| | |
| | csg.write("group() {\n group(){\n") |
| | for ob in exportList: |
| | print(ob) |
| | print("Name : " + ob.Name) |
| | print("Type : " + ob.TypeId) |
| | print("Shape : ") |
| | print(ob.Shape) |
| | process_object(csg, ob) |
| |
|
| | |
| | csg.write("}\n}\n") |
| | |
| | csg.close() |
| | FreeCAD.Console.PrintMessage("successfully exported" + " " + filename) |
| |
|