FreeCAD-macros

Форк
0
422 строки · 15.3 Кб
1
import FreeCAD as app
2
from FreeCAD import Vector, Rotation
3
import Draft
4
import BOPTools.JoinFeatures
5

6

7
def create_box(materialWidth,
8
               boxWidth, boxHeight, boxLength,
9
               notchWidth,
10
               drawSides=[True, True, True, True, True, True],
11
               overhangTop=[0.0, 0.0, 0.0, 0.0],
12
               overhangBottom=[0.0, 0.0, 0.0, 0.0],
13
               doc=None):
14
    """Create a box  with interlocked notches.
15

16
    Parameters
17
    ----------
18
    - drawSides: [top, bottom, left, right, front, back]
19
    - overhangTop: [top left, top right, top front, top back]
20
    - overhangBottom: [bottom left, bottom right, bottom front, bottom back]
21
    """
22

23
    if doc is None:
24
        doc = app.activeDocument()
25

26
    if doc is None:
27
        doc = app.newDocument()
28

29
    if doc is None:
30
        app.Console.PrintError('Could not get a document where to create the box')
31
        return
32

33
    boxobjects = []
34

35
    if drawSides[1]:
36
        side1 = draw_top_bottom(doc, 'bottom', materialWidth, boxWidth, boxLength, notchWidth, drawSides, overhangBottom)
37
        boxobjects.append(side1)
38

39
    if drawSides[0]:
40
        side2 = draw_top_bottom(doc, 'top', materialWidth, boxWidth, boxLength, notchWidth, drawSides, overhangTop)
41
        side2.Placement.Base.z += boxHeight - materialWidth
42
        boxobjects.append(side2)
43

44
    if drawSides[2]:
45
        side3 = draw_left_right(doc, 'left', materialWidth, boxHeight, boxLength, notchWidth, drawSides)
46
        boxobjects.append(side3)
47

48
    if drawSides[3]:
49
        side4 = draw_left_right(doc, 'right', materialWidth, boxHeight, boxLength, notchWidth, drawSides)
50
        Draft.move([side4], Vector(boxWidth - materialWidth, 0.0, 0.0), copy=False)
51
        boxobjects.append(side4)
52

53
    if drawSides[4]:
54
        side5 = draw_front_back(doc, 'front', materialWidth, boxWidth, boxHeight, notchWidth, drawSides)
55
        boxobjects.append(side5)
56

57
    if drawSides[5]:
58
        side6 = draw_front_back(doc, 'back', materialWidth, boxWidth, boxHeight, notchWidth, drawSides)
59
        Draft.move([side6], Vector(0.0, boxLength - materialWidth, 0.0), copy=False)
60
        boxobjects.append(side6)
61

62
    comp1 = doc.addObject('Part::Compound', 'Box')
63
    comp1.Links = boxobjects
64

65
    doc.recompute()
66
    return comp1
67

68

69
def draw_top_bottom(doc, partname, materialWidth, boxWidth, boxLength, notchWidth, drawSides=[True, True, True, True, True, True], overhang=[0.0, 0.0, 0.0, 0.0]):
70
    """Create the top or bottom part of the box.
71

72
    Parameters
73
    ----------
74
    - drawSides = [top, bottom, left, right, front, back]
75
    - overhang = [left, right, front, back]
76
    """
77
    lines = []
78

79
    if overhang[2] > 0:
80
        lines += _notch_holes(boxWidth, notchWidth, materialWidth, Vector(0, 0, 0), overhang[2], drawSides[4], overhang[0], overhang[1])
81
    else:
82
        lines.append(_notch_line(boxWidth, notchWidth, materialWidth, Vector(0, 0, 0), False, False, drawSides[4]))
83

84
    if overhang[1] > 0:
85
        lines2 = _notch_holes(boxLength, notchWidth, materialWidth, Vector(0, 0, 90), overhang[1], drawSides[3], overhang[2], overhang[2])
86
        for line in lines2:
87
            line.Placement.Base.x += boxWidth
88
            lines.append(line)
89
    else:
90
        lines2 = _notch_line(boxLength, notchWidth, materialWidth, Vector(0, 0, 90), False, False, drawSides[3])
91
        lines2.Placement.Base.x += boxWidth
92
        lines.append(lines2)
93

94
    if overhang[3] > 0:
95
        lines3 = _notch_holes(boxWidth, notchWidth, materialWidth, Vector(0, 0, 180), overhang[3], drawSides[5], overhang[1], overhang[0])
96
        for line in lines3:
97
            line.Placement.Base.x += boxWidth
98
            line.Placement.Base.y += boxLength
99
            lines.append(line)
100
    else:
101
        lines3 = _notch_line(boxWidth, notchWidth, materialWidth, Vector(0, 0, 180), False, False, drawSides[5])
102
        lines3.Placement.Base.x += boxWidth
103
        lines3.Placement.Base.y += boxLength
104
        lines.append(lines3)
105

106
    if overhang[0] > 0:
107
        lines4 = _notch_holes(boxLength, notchWidth, materialWidth, Vector(0, 0, 270), overhang[0], drawSides[2], overhang[3], overhang[3])
108
        for line in lines4:
109
            line.Placement.Base.y += boxLength
110
            lines.append(line)
111
    else:
112
        lines4 = _notch_line(boxLength, notchWidth, materialWidth, Vector(0, 0, 270), False, False, drawSides[2])
113
        lines4.Placement.Base.y += boxLength
114
        lines.append(lines4)
115

116
    doc.recompute()
117
    side1 = _extrude_lines(doc, partname, lines, materialWidth)
118
    return side1
119

120

121
def draw_left_right(doc, partname, materialWidth, boxHeight, boxLength, notchWidth, drawSides=[True, True, True, True, True, True]):
122
    """Create the left or right part of the box.
123

124
    Also used to create the compartment separators inside the box.
125

126
    Parameters
127
    ----------
128
    - drawSides = [top, bottom, left, right, front, back]
129
    """
130
    line1 = _notch_line(boxLength, notchWidth, materialWidth, Vector(0, 270, 90), drawSides[4], drawSides[5], drawSides[1])
131
    if drawSides[1]:
132
        line1.Placement.Base.z += materialWidth
133

134
    line2 = _notch_line(boxHeight, notchWidth, materialWidth, Vector(90, 90, 90), drawSides[1], drawSides[0], drawSides[4])
135
    if drawSides[4]:
136
        line2.Placement.Base.y += materialWidth
137

138
    line3 = _notch_line(boxLength, notchWidth, materialWidth, Vector(0, 90, 90), drawSides[4], drawSides[5], drawSides[0])
139
    line3.Placement.Base.z += boxHeight
140
    if drawSides[0]:
141
        line3.Placement.Base.z -= materialWidth
142

143
    line4 = _notch_line(boxHeight, notchWidth, materialWidth, Vector(90, 270, 90), drawSides[1], drawSides[0], drawSides[5])
144
    line4.Placement.Base.y += boxLength
145
    if drawSides[5]:
146
        line4.Placement.Base.y -= materialWidth
147

148
    lines = [line1, line2, line3, line4]
149

150
    side3 = _extrude_lines(doc, partname, lines, materialWidth)
151
    return side3
152

153

154
def draw_front_back(doc, partname, materialWidth, boxWidth, boxHeight, notchWidth, drawSides=[True, True, True, True, True, True]):
155
    """Create the front or back part of the box."""
156
    line1 = _notch_line(boxWidth, notchWidth, materialWidth, Vector(270, 0, 0), False, False, drawSides[1])
157
    if drawSides[1]:
158
        line1.Placement.Base.z += materialWidth
159

160
    line2 = _notch_line(boxHeight, notchWidth, materialWidth, Vector(90, 0, 270), drawSides[0], drawSides[1], drawSides[2])
161
    line2.Placement.Base.z += boxHeight
162

163
    line3 = _notch_line(boxWidth, notchWidth, materialWidth, Vector(90, 0, 0), False, False, drawSides[0])
164
    line3.Placement.Base.z += boxHeight
165
    if drawSides[0]:
166
        line3.Placement.Base.z -= materialWidth
167

168
    line4 = _notch_line(boxHeight, notchWidth, materialWidth, Vector(90, 0, 90), drawSides[1], drawSides[0], drawSides[3])
169
    line4.Placement.Base.x += boxWidth
170

171
    doc.recompute()
172
    lines = [line1, line2, line3, line4]
173

174
    side5 = _extrude_lines(doc, partname, lines, materialWidth)
175
    return side5
176

177

178
def _notch_line(length, notchWidth, materialWidth, rotation=Vector(0, 0, 0), insideLeft=False, insideRight=False, drawNotches=True):
179
    """Create the lines for the notches."""
180
    if not drawNotches:
181
        if insideLeft:  x = materialWidth
182
        else:           x = 0
183

184
        if insideRight: y = length - materialWidth
185
        else:           y = length
186

187
        points = _rotate_points([Vector(x, 0.0, 0.0),
188
                               Vector(y, 0.0, 0.0)],
189
                               rotation)
190

191
        line = Draft.makeWire(points, closed=False, face=False, support=None)
192
        return line
193

194
    nrNotches = int((length - 2 * materialWidth) / (notchWidth * 2))
195
    edgeLen = (length - (notchWidth * (nrNotches * 2 - 1))) / 2
196
    x = 0
197
    if insideLeft:
198
        x = materialWidth
199
        edgeLen -= materialWidth
200

201
    points = [Vector(x, 0, 0)]
202
    x += edgeLen
203
    for count in range(0, nrNotches):
204
        points.append(Vector(x, 0, 0))
205
        points.append(Vector(x, materialWidth, 0))
206
        x = x + notchWidth
207
        points.append(Vector(x, materialWidth, 0))
208
        points.append(Vector(x, 0, 0))
209
        x = x + notchWidth
210

211
    if insideLeft and not insideRight:
212
        edgeLen += materialWidth
213

214
    points.append(Vector(x - notchWidth + edgeLen, 0, 0))
215
    line = Draft.makeWire(_rotate_points(points, rotation), closed=False, face=False, support=None)
216
    Draft.autogroup(line)
217
    return line
218

219

220
def _draw_holes(length, notchWidth, materialWidth, rotation):
221
    """Create the lines for the notch holes in a part."""
222
    lines = []
223
    nrNotches = int((length - 2 * materialWidth) / (notchWidth * 2))
224
    x = (length - (notchWidth * (nrNotches * 2 - 1))) / 2
225
    for count in range(0, nrNotches):
226
        points = [Vector(x, 0, 0), Vector(x, materialWidth, 0), Vector(x + notchWidth, materialWidth, 0), Vector(x + notchWidth, 0, 0)]
227
        points = _rotate_points(points, rotation)
228
        line = Draft.makeWire(points, closed=True, face=False, support=None)
229
        line.Label = "hole"
230
        Draft.autogroup(line)
231
        lines.append(line)
232
        x = x + notchWidth * 2
233

234
    return lines
235

236

237
def _notch_holes(length, notchWidth, materialWidth, rotation=Vector(0, 0, 0), overhang=0, drawHoles=True, overhangLeft=0, overhangRight=0):
238
    lines = []
239

240
    if drawHoles:
241
        lines = _draw_holes(length, notchWidth, materialWidth, rotation)
242

243
    points = [Vector(-overhangLeft, 0, 0),
244
              Vector(-overhangLeft, -overhang, 0),
245
              Vector(length + overhangRight, -overhang, 0),
246
              Vector(length + overhangRight, 0, 0)]
247
    points = _rotate_points(points, rotation)
248
    ohline = Draft.makeWire(points, closed=False, face=False, support=None)
249
    lines.append(ohline)
250
    return lines
251

252

253
def _extrude_lines(doc, extrudename, lines, materialWidth):
254
    doc.recompute()
255
    j = BOPTools.JoinFeatures.makeConnect(name='Outline')
256
    j.Objects = lines
257
    j.Proxy.execute(j)
258
    j.purgeTouched()
259
    for obj in j.ViewObject.Proxy.claimChildren():
260
        obj.ViewObject.hide()
261

262
    f = doc.addObject('Part::Extrusion', extrudename)
263
    f.Base = j
264
    f.DirMode = 'Normal'
265
    f.DirLink = None
266
    f.LengthFwd = materialWidth
267
    f.LengthRev = 0
268
    f.Solid = True
269
    f.Reversed = False
270
    f.Symmetric = False
271
    f.TaperAngle = 0
272
    f.TaperAngleRev = 0
273
    f.Base.ViewObject.hide()
274
    return f
275

276

277
def _rotate_points(plist, axisdegree):
278
    """Return a list of points rotated around the origin
279

280
    The rotation is defined by three angles in degrees and the rotation order is
281
    z, y, x, each around the newly rotated axis.
282

283
    Parameters
284
    ----------
285
    - plist: list of Vector.
286
    - axisdegree: Vector with angles in deg.
287
    """
288
    newlist = []
289
    for v in plist:
290
        if axisdegree.z != 0:
291
            rota = Rotation(Vector(0, 0, 1), axisdegree.z)
292
            v = rota.multVec(v)
293

294
        if axisdegree.y != 0:
295
            rota = Rotation(Vector(0, 1, 0), axisdegree.y)
296
            v = rota.multVec(v)
297

298
        if axisdegree.x != 0:
299
            rota = Rotation(Vector(1, 0, 0), axisdegree.x)
300
            v = rota.multVec(v)
301

302
        newlist.append(v)
303

304
    return newlist
305

306

307
def create_compartment(box,
308
                       direction,
309
                       offset,
310
                       materialWidth,
311
                       notchWidth,
312
                       drawSides=[True, True, True, True, True, True],
313
                       boxsize=Vector(0, 0, 0)):
314
    try:
315
        doc = box[0].Document
316
    except (IndexError, AttributeError) as e:
317
        app.Console.PrintError(
318
            'Could not get a document where to create the compartment: {}'.format(e))
319
        return
320

321
    cpos = direction * offset
322
    mybox = None
323
    if len(box) == 1 and hasattr(box[0], 'Links'):
324
        parts = box[0].Links
325
        mybox = box[0]
326
    elif isinstance(box, list):
327
        parts = box
328
    else:
329
        parts = [box]
330

331
    if boxsize == Vector(0, 0, 0):
332
        for side in parts:
333
            if hasattr(side, 'Shape'):
334
                bbox = side.Shape.BoundBox
335
                if bbox.XLength > boxsize.x: boxsize.x = bbox.XLength
336
                if bbox.YLength > boxsize.y: boxsize.y = bbox.YLength
337
                if bbox.ZLength > boxsize.z: boxsize.z = bbox.ZLength
338

339
    holes = []
340
    if direction == Vector(1, 0, 0):
341
        if boxsize.z == 0 or boxsize.y == 0:
342
            app.Console.PrintError("select a box first !\n")
343
            return
344
        compartment = draw_left_right(doc, 'compartmentX' + str(offset), materialWidth, boxsize.z, boxsize.y, notchWidth, drawSides)
345
        if drawSides[4] or drawSides[5]:
346
            holes += _draw_holes(boxsize.y, notchWidth, materialWidth, Vector(0, 0, 90))
347
        if drawSides[2] or drawSides[3]:
348
            holes += _draw_holes(boxsize.z, notchWidth, materialWidth, Vector(90, 0, 90))
349

350
        for h in holes:
351
            h.Placement.Base.x += offset + materialWidth
352

353
    elif direction == Vector(0, 1, 0):
354
        if boxsize.z == 0 or boxsize.x == 0:
355
            app.Console.PrintError("select a box first !\n")
356
            return
357

358
        sides = [drawSides[0], drawSides[1], drawSides[4], drawSides[5], drawSides[2], drawSides[3]]
359
        compartment = draw_left_right(doc, 'compartmentY' + str(offset), materialWidth, boxsize.z, boxsize.x, notchWidth, sides)
360
        doc.recompute()
361
        Draft.rotate([compartment], 270.0, Vector(0, 0, 0), axis=Vector(0.0, 0.0, 1.0), copy=False)
362
        doc.recompute()
363
        Draft.move([compartment], Vector(0, materialWidth, 0), copy=False)
364
        doc.recompute()
365
        if drawSides[0] or drawSides[1]:
366
            holes += _draw_holes(boxsize.x, notchWidth, materialWidth, Vector(0, 0, 0))
367
        if drawSides[2] or drawSides[3]:
368
            holes += _draw_holes(boxsize.z, notchWidth, materialWidth, Vector(0, 270, 0))
369

370
        for h in holes:
371
            h.Placement.Base.y += offset
372

373
    elif direction == Vector(0, 0, 1):
374
        if boxsize.x == 0 or boxsize.y == 0:
375
            app.Console.PrintError("select a box first !\n")
376
            return
377

378
        sides = [drawSides[2], drawSides[3], drawSides[0], drawSides[1], drawSides[4], drawSides[5]]
379
        compartment = draw_left_right(doc, 'compartmentZ' + str(offset), materialWidth, boxsize.x, boxsize.y, notchWidth, sides)
380
        doc.recompute()
381
        Draft.rotate([compartment], 270.0, Vector(boxsize.x, 0, 0), axis=Vector(0.0, 1.0, 0.0), copy=False)
382
        doc.recompute()
383
        Draft.move([compartment], Vector(0, 0, boxsize.x), copy=False)
384
        doc.recompute()
385
        if drawSides[0] or drawSides[1]:
386
            holes += _draw_holes(boxsize.x, notchWidth, materialWidth, Vector(270, 0, 0))
387
        if drawSides[4] or drawSides[5]:
388
            holes += _draw_holes(boxsize.y, notchWidth, materialWidth, Vector(0, 270, 90))
389

390
        for h in holes:
391
            h.Placement.Base.z += offset + materialWidth
392
    else:
393
        return None
394

395
    Draft.move([compartment], cpos, copy=False)
396

397
    doc.recompute()
398
    _add_lines_to_box_side(parts, holes)
399
    
400
    if mybox:
401
        parts.append(compartment)
402
        mybox.Links = parts
403
        doc.recompute()
404
        return mybox
405

406
    doc.recompute()
407
    return compartment
408

409

410
def _add_lines_to_box_side(box, holes):
411
    epsilon = 1e-7
412
    for side in box:
413
        if hasattr(side, 'Base') and hasattr(side.Base, 'Objects')and not side.Name.startswith("compartment"):
414
            outline = side.Base
415
            obox = outline.Shape.BoundBox
416

417
            for h in holes:
418
                h.ViewObject.hide()
419
                hbox = h.Shape.BoundBox
420
                if (hbox.XLength < epsilon and obox.XLength < epsilon) or (hbox.YLength < epsilon and obox.YLength < epsilon) or (hbox.ZLength < epsilon and obox.ZLength < epsilon):
421
                    outline.Objects += [h]
422
                    outline.Proxy.execute(outline)
423

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

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

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

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