FreeCAD

Форк
0
/
exportCSG.py 
275 строк · 11.7 Кб
1

2
#***************************************************************************
3
#*   Copyright (c) 2012 Keith Sloan <keith@sloan-home.co.uk>               *
4
#*                                                                         *
5
#*   This program is free software; you can redistribute it and/or modify  *
6
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
7
#*   as published by the Free Software Foundation; either version 2 of     *
8
#*   the License, or (at your option) any later version.                   *
9
#*   for detail see the LICENCE text file.                                 *
10
#*                                                                         *
11
#*   This program is distributed in the hope that it will be useful,       *
12
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
#*   GNU Library General Public License for more details.                  *
15
#*                                                                         *
16
#*   You should have received a copy of the GNU Library General Public     *
17
#*   License along with this program; if not, write to the Free Software   *
18
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
19
#*   USA                                                                   *
20
#*                                                                         *
21
#*   Acknowledgements :                                                    *
22
#*                                                                         *
23
#*     Thanks to shoogen on the FreeCAD forum for programming advice       *
24
#*     and some code.                                                      *
25
#*                                                                         *
26
#***************************************************************************
27
__title__ = "FreeCAD OpenSCAD Workbench - CSG exporter Version"
28
__author__ = "Keith Sloan <keith@sloan-home.co.uk>"
29
__url__ = ["http://www.sloan-home.co.uk/Export/Export.html"]
30

31
import FreeCAD
32

33
if FreeCAD.GuiUp:
34
    gui = True
35
else:
36
    gui = False
37

38
#***************************************************************************
39
# Tailor following to your requirements ( Should all be strings )          *
40
#fafs = '$fa = 12, $fs = 2'
41
#convexity = 'convexity = 10'
42
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD")
43
fa = params.GetFloat('exportFa', 12.0)
44
fs = params.GetFloat('exportFs', 2.0)
45
conv = params.GetInt('exportConvexity', 10)
46
fafs = '$fa = %f, $fs = %f' % (fa, fs)
47
convexity = 'convexity = %d' % conv
48
#***************************************************************************
49
# Radius values not fixed for value apart from cylinder & Cone
50
# no doubt there will be a problem when they do implement Value
51
if open.__module__ in ['__builtin__', 'io']:
52
    pythonopen = open # to distinguish python built-in open function from the one declared here
53

54

55
def center(b):
56
    if b == 2:
57
        return 'true'
58
    else:
59
        return 'false'
60

61

62
def check_multmatrix(csg, ob, x, y, z):
63
    b = FreeCAD.Vector(x,y,z)
64
    if ob.Placement.isNull():
65
        return 0 # center = false no mm
66
    elif ob.Placement.Rotation.isNull() and \
67
        (ob.Placement.Base - b).Length < 1e-6:
68
        return 2 # center = true and no mm
69
    else:
70
        m = ob.Placement.toMatrix()
71
        # adjust position for center displacements
72
        csg.write("multmatrix([["+str(m.A11)+", "+str(m.A12)+", "+str(m.A13)+",\
73
            "+str(m.A14)+"], ["\
74
             +str(m.A21)+", "+str(m.A22)+", "+str(m.A23)+", "+str(m.A24)+"], ["\
75
             +str(m.A31)+", "+str(m.A32)+", "+str(m.A33)+", "+str(m.A34)+"], [\
76
             0, 0, 0, 1]]){\n")
77
        return 1 # center = false and mm
78

79

80
def mesh2polyhedron(mesh):
81
    pointstr = ','.join(['[%f,%f,%f]' % tuple(vec) for vec in mesh.Topology[0]])
82
    trianglestr = ','.join(['[%d,%d,%d]' % tuple(tri) for tri in mesh.Topology[1]])
83
    #avoid deprecation warning by changing triangles to faces
84
    #return 'polyhedron ( points = [%s], triangles = [%s]);' % (pointstr, trianglestr)
85
    return 'polyhedron ( points = [%s], faces = [%s]);' % (pointstr, trianglestr)
86

87

88
def vector2d(v):
89
    return [v[0],v[1]]
90

91

92
def vertexs2polygon(vertex):
93
    pointstr = ','.join(['[%f, %f]'  % tuple(vector2d(v.Point)) for v in vertex])
94
    return 'polygon ( points = [%s], paths = undef, convexity = 1);}' % pointstr
95

96

97
def shape2polyhedron(shape):
98
    import MeshPart
99
    return mesh2polyhedron(MeshPart.meshFromShape(Shape=shape,\
100
        Deflection = params.GetFloat('meshdeflection', 0.0)))
101

102

103
def process_object(csg,ob):
104
    print("Placement")
105
    print("Pos   : "+str(ob.Placement.Base))
106
    print("axis  : "+str(ob.Placement.Rotation.Axis))
107
    print("angle : "+str(ob.Placement.Rotation.Angle))
108

109
    if ob.TypeId == "Part::Sphere":
110
        print("Sphere Radius : "+str(ob.Radius))
111
        check_multmatrix(csg, ob, 0, 0, 0)
112
        csg.write("sphere($fn = 0, "+fafs+", r = "+str(ob.Radius)+");\n")
113

114
    elif ob.TypeId == "Part::Box":
115
        print("cube : ("+ str(ob.Length)+","+str(ob.Width)+","+str(ob.Height)+")")
116
        mm = check_multmatrix(csg,ob,-ob.Length/2,-ob.Width/2,-ob.Height/2)
117
        csg.write("cube (size = ["+str(ob.Length.Value)+", "+str(ob.Width.Value)+", "+str(ob.Height.Value)+"], center = "+center(mm)+");\n")
118
        if mm == 1 : csg.write("}\n")
119

120
    elif ob.TypeId == "Part::Cylinder":
121
        print("cylinder : Height "+str(ob.Height) + " Radius "+str(ob.Radius))
122
        mm = check_multmatrix(csg, ob, 0, 0, -ob.Height/2)
123
        csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height.Value) + ", r1 = "+str(ob.Radius.Value)+\
124
                  ", r2 = " + str(ob.Radius.Value) + ", center = "+center(mm)+");\n")
125
        if mm == 1 : csg.write("}\n")
126

127
    elif ob.TypeId == "Part::Cone":
128
        print("cone : Height "+str(ob.Height) + " Radius1 "+str(ob.Radius1)+" Radius2 "+str(ob.Radius2))
129
        mm = check_multmatrix(csg, ob, 0, 0, -ob.Height/2)
130
        csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height.Value)+ ", r1 = "+str(ob.Radius1.Value)+\
131
                  ", r2 = "+str(ob.Radius2.Value)+", center = "+center(mm)+");\n")
132
        if mm == 1 : csg.write("}\n")
133

134
    elif ob.TypeId == "Part::Torus":
135
        print("Torus")
136
        print(ob.Radius1)
137
        print(ob.Radius2)
138
        if ob.Angle3 == 360.00:
139
            mm = check_multmatrix(csg, ob, 0, 0, 0)
140
            csg.write("rotate_extrude("+convexity+", $fn = 0, "+fafs+")\n")
141
            csg.write("multmatrix([[1, 0, 0, "+str(ob.Radius1)+"], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])\n")
142
            csg.write("circle($fn = 0, "+fafs+", r = "+str(ob.Radius2)+");\n")
143
            if mm == 1 : csg.write("}\n")
144
        else: # Cannot convert to rotate extrude so best effort is polyhedron
145
            csg.write('%s\n' % shape2polyhedron(ob.Shape))
146

147
    elif ob.TypeId == "Part::Prism":
148
        import math
149
        f = str(ob.Polygon)
150
#        r = str(ob.Length/2.0/math.sin(math.pi/ob.Polygon))
151
        r = str(ob.Circumradius) # length seems to be the outer radius
152
        h = str(ob.Height.Value)
153
        mm = check_multmatrix(csg, ob, 0, 0, -float(h)/2)
154
        csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\
155
                  ", r2 = "+r+", center = "+center(mm)+");\n")
156
        if mm == 1: csg.write("}\n")
157

158
    elif ob.TypeId == "Part::RegularPolygon":
159
        mm = check_multmatrix(csg, ob, 0, 0, -float(h)/2)
160
        csg.write("circle($fn = "+str(ob.NumberOfSides)+", "+fafs+", r = "+str(ob.Radius)+");\n")
161
        if mm == 1: csg.write("}\n")
162

163
    elif ob.TypeId == "Part::Extrusion":
164
        print("Extrusion")
165
        print(ob.Base)
166
        print(ob.Base.Name)
167
        if ob.Base.isDerivedFrom('Part::Part2DObjectPython') and \
168
            hasattr(ob.Base,'Proxy') and hasattr(ob.Base.Proxy, 'TypeId'):
169
            ptype = ob.Base.Proxy.TypeId
170
            if ptype == "Polygon":
171
                f = str(ob.Base.FacesNumber)
172
                r = str(ob.Base.Radius)
173
                h = str(ob.Dir[2])
174
                print("Faces : " + f)
175
                print("Radius : " + r)
176
                print("Height : " + h)
177
                mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
178
                csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\
179
                          ", r2 = "+r+", center = "+center(mm)+");\n")
180
                if mm == 1: csg.write("}\n")
181

182
            elif ptype == "Circle":
183
                r = str(ob.Base.Radius)
184
                h = str(ob.Dir[2])
185
                print("Radius : " + r)
186
                print("Height : " + h)
187
                mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
188
                csg.write("cylinder($fn = 0, "+fafs+", h = "+h+", r1 = "+r+\
189
                          ", r2 = "+r+", center = "+center(mm)+");\n")
190
                if mm == 1: csg.write("}\n")
191

192
            elif ptype == "Wire":
193
                print("Wire extrusion")
194
                print(ob.Base)
195
                mm = check_multmatrix(csg, ob, 0, 0, 0)
196
                csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = "+center(mm)+", "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n")
197
                csg.write(vertexs2polygon(ob.Base.Shape.Vertexes))
198
                if mm == 1: csg.write("}\n")
199

200
        elif ob.Base.isDerivedFrom('Part::Plane'):
201
            mm = check_multmatrix(csg,ob,0,0,0)
202
            csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = true, "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n")
203
            csg.write("square (size = ["+str(ob.Base.Length.Value)+", "+str(ob.Base.Width.Value)+"], center = "+center(mm)+");\n}\n")
204
            if mm == 1: csg.write("}\n")
205
        elif ob.Base.Name.startswith('this_is_a_bad_idea'):
206
            pass
207
        else:
208
            pass # There should be a fallback solution
209

210
    elif ob.TypeId == "Part::Cut":
211
        print("Cut")
212
        csg.write("difference() {\n")
213
        process_object(csg,ob.Base)
214
        process_object(csg,ob.Tool)
215
        csg.write("}\n")
216

217
    elif ob.TypeId == "Part::Fuse":
218
        print("union")
219
        csg.write("union() {\n")
220
        process_object(csg,ob.Base)
221
        process_object(csg,ob.Tool)
222
        csg.write("}\n")
223

224
    elif ob.TypeId == "Part::Common":
225
        print("intersection")
226
        csg.write("intersection() {\n")
227
        process_object(csg,ob.Base)
228
        process_object(csg,ob.Tool)
229
        csg.write("}\n")
230

231
    elif ob.TypeId == "Part::MultiFuse":
232
        print("Multi Fuse / union")
233
        csg.write("union() {\n")
234
        for subobj in ob.Shapes:
235
            process_object(csg,subobj)
236
        csg.write("}\n")
237

238
    elif ob.TypeId == "Part::MultiCommon":
239
        print("Multi Common / intersection")
240
        csg.write("intersection() {\n")
241
        for subobj in ob.Shapes:
242
            process_object(csg,subobj)
243
        csg.write("}\n")
244

245
    elif ob.isDerivedFrom('Part::Feature'):
246
        print("Part::Feature")
247
        mm = check_multmatrix(csg,ob,0,0,0)
248
        csg.write('%s\n' % shape2polyhedron(ob.Shape))
249
        if mm == 1 : csg.write("}\n")
250

251
def export(exportList, filename):
252
    "called when FreeCAD exports a file"
253

254
    # process Objects
255
    print("\nStart Export 0.1d\n")
256
    print("Open Output File")
257
    csg = pythonopen(filename,'w')
258
    print("Write Initial Output")
259
    # Not sure if comments as per scad are allowed in csg file
260
    csg.write("// CSG file generated from FreeCAD %s\n" % \
261
            '.'.join(FreeCAD.Version()[0:3]))
262
    #write initial group statements - not sure if required
263
    csg.write("group() {\n group(){\n")
264
    for ob in exportList:
265
        print(ob)
266
        print("Name : " + ob.Name)
267
        print("Type : " + ob.TypeId)
268
        print("Shape : ")
269
        print(ob.Shape)
270
        process_object(csg, ob)
271

272
    # write closing group braces
273
    csg.write("}\n}\n")
274
    # close file
275
    csg.close()
276
    FreeCAD.Console.PrintMessage("successfully exported" + " " + filename)
277

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.