OpenMagneticsVirtualBuilder 0.5.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3655 @@
1
+ import contextlib
2
+ import sys
3
+ import math
4
+ import os
5
+ import json
6
+ from abc import ABCMeta, abstractmethod
7
+ import copy
8
+ import pathlib
9
+ import platform
10
+ sys.path.append(os.path.dirname(__file__))
11
+ import utils
12
+
13
+ file_dir = os.path.dirname(__file__)
14
+ sys.path.append(file_dir)
15
+
16
+
17
+ if platform.system() == "Windows":
18
+ if os.path.exists(f"{os.getenv('LOCALAPPDATA')}\\Programs\\FreeCAD 1.0"):
19
+ freecad_path = f"{os.getenv('LOCALAPPDATA')}\\Programs\\FreeCAD 1.0"
20
+ elif os.path.exists(f"{os.environ['ProgramFiles']}\\FreeCAD 1.0"):
21
+ freecad_path = f"{os.environ['ProgramFiles']}\\FreeCAD 1.0"
22
+ elif os.path.exists(f"{os.getenv('LOCALAPPDATA')}\\Programs\\FreeCAD 0.21"):
23
+ freecad_path = f"{os.getenv('LOCALAPPDATA')}\\Programs\\FreeCAD 0.21"
24
+ elif os.path.exists(f"{os.environ['ProgramFiles']}\\FreeCAD 0.21"):
25
+ freecad_path = f"{os.environ['ProgramFiles']}\\FreeCAD 0.21"
26
+
27
+ sys.path.insert(0, f"{freecad_path}\\bin\\Lib\\site-packages")
28
+ sys.path.append(f"{freecad_path}\\bin")
29
+ sys.path.append(f"{freecad_path}\\Ext")
30
+ sys.path.append(f"{freecad_path}\\Mod")
31
+ sys.path.append(f"{freecad_path}\\Mod\\Draft")
32
+ sys.path.append(f"{freecad_path}\\Mod\\Part")
33
+ sys.path.append(f"{freecad_path}\\Mod\\PartDesign")
34
+ sys.path.append(f"{freecad_path}\\Mod\\Sketcher")
35
+ sys.path.append(f"{freecad_path}\\Mod\\Arch")
36
+ else:
37
+ sys.path.insert(0, "/usr/lib/python3/dist-packages")
38
+ sys.path.append("/usr/lib/freecad-daily/lib")
39
+ sys.path.append("/usr/share/freecad-daily/Ext")
40
+ sys.path.append("/usr/share/freecad-daily/Mod")
41
+ sys.path.append("/usr/share/freecad-daily/Mod/Part")
42
+ sys.path.append("/usr/share/freecad-daily/Mod/Draft")
43
+ sys.path.append("/usr/share/freecad-daily/Mod/Draft/draftobjects")
44
+ # Comment line 31 from /usr/share/freecad-daily/Mod/Draft/draftutils/params.py if it crashes at import
45
+ # import Arch_rc
46
+
47
+
48
+ import FreeCAD # noqa: E402
49
+ import Import # noqa: E402
50
+ import Mesh # noqa: E402
51
+ import Sketcher # noqa: E402
52
+ import Part # noqa: E402
53
+ from BasicShapes import Shapes # noqa: E402
54
+ import TechDraw # noqa: E402
55
+ import Draft # noqa: E402
56
+ # import clone # noqa: E402
57
+
58
+
59
+ def flatten_dimensions(data):
60
+ dimensions = data["dimensions"]
61
+ for k, v in dimensions.items():
62
+ if isinstance(v, dict):
63
+ if "nominal" not in v or v["nominal"] is None:
64
+ if "maximum" not in v or v["maximum"] is None:
65
+ v["nominal"] = v["minimum"]
66
+ elif "minimum" not in v or v["minimum"] is None:
67
+ v["nominal"] = v["maximum"]
68
+ else:
69
+ v["nominal"] = round((v["maximum"] + v["minimum"]) / 2, 6)
70
+ else:
71
+ dimensions[k] = {"nominal": v}
72
+ return {k: v["nominal"] * 1000 for k, v in dimensions.items() if k != 'alpha'}
73
+
74
+
75
+ class Builder:
76
+ """
77
+ Class for calculating the different areas and length of every shape according to EN 60205.
78
+ Each shape will create a daughter of this class and define their own equations
79
+ """
80
+
81
+ def __init__(self):
82
+ self.shapers = {
83
+ utils.ShapeFamily.ETD: Etd(),
84
+ utils.ShapeFamily.ER: Er(),
85
+ utils.ShapeFamily.EP: Ep(),
86
+ utils.ShapeFamily.EPX: Epx(),
87
+ utils.ShapeFamily.PQ: Pq(),
88
+ utils.ShapeFamily.E: E(),
89
+ utils.ShapeFamily.PM: Pm(),
90
+ utils.ShapeFamily.P: P(),
91
+ utils.ShapeFamily.RM: Rm(),
92
+ utils.ShapeFamily.EQ: Eq(),
93
+ utils.ShapeFamily.LP: Lp(),
94
+ utils.ShapeFamily.PLANAR_ER: Er(),
95
+ utils.ShapeFamily.PLANAR_E: E(),
96
+ utils.ShapeFamily.PLANAR_EL: El(),
97
+ utils.ShapeFamily.EC: Ec(),
98
+ utils.ShapeFamily.EFD: Efd(),
99
+ utils.ShapeFamily.U: U(),
100
+ utils.ShapeFamily.UR: Ur(),
101
+ utils.ShapeFamily.UT: Ut(),
102
+ utils.ShapeFamily.T: T()
103
+ }
104
+
105
+ def factory(self, data):
106
+ family = utils.ShapeFamily[data['family'].upper().replace(" ", "_")]
107
+ return self.shapers[family]
108
+
109
+ def get_families(self):
110
+ return {
111
+ shaper.name.lower()
112
+ .replace("_", " "): self.factory({'family': shaper.name})
113
+ .get_dimensions_and_subtypes()
114
+ for shaper in self.shapers
115
+ }
116
+
117
+ def get_spacer(self, geometrical_data):
118
+ document = FreeCAD.ActiveDocument
119
+ document.recompute()
120
+
121
+ spacer = document.addObject("Part::Box", "Spacer")
122
+ spacer.Length = geometrical_data["dimensions"][2] * 1000
123
+ spacer.Width = geometrical_data["dimensions"][0] * 1000
124
+ spacer.Height = geometrical_data["dimensions"][1] * 1000
125
+ spacer.Placement = FreeCAD.Placement(FreeCAD.Vector((geometrical_data["coordinates"][2] - geometrical_data["dimensions"][2] / 2) * 1000,
126
+ (geometrical_data["coordinates"][0] - geometrical_data["dimensions"][0] / 2) * 1000,
127
+ (geometrical_data["coordinates"][1] - geometrical_data["dimensions"][1] / 2) * 1000),
128
+ FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
129
+
130
+ document.recompute()
131
+ m = spacer.Placement.Matrix
132
+ m.rotateX(geometrical_data['rotation'][2])
133
+ m.rotateY(geometrical_data['rotation'][0])
134
+ m.rotateZ(geometrical_data['rotation'][1])
135
+ spacer.Placement.Matrix = m
136
+ document.recompute()
137
+ return spacer
138
+
139
+ def get_core(self, project_name, geometrical_description, output_path=f'{os.path.dirname(os.path.abspath(__file__))}/../output/', save_files=True, export_files=True):
140
+ try:
141
+ pieces_to_export = []
142
+ project_name = f"{project_name}_core".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
143
+
144
+ os.makedirs(output_path, exist_ok=True)
145
+
146
+ close_file_after_finishing = False
147
+ if FreeCAD.ActiveDocument is None:
148
+ close_file_after_finishing = True
149
+ FreeCAD.newDocument(project_name)
150
+
151
+ document = FreeCAD.ActiveDocument
152
+
153
+ for index, geometrical_part in enumerate(geometrical_description):
154
+ if geometrical_part['type'] == 'spacer':
155
+ spacer = self.get_spacer(geometrical_part)
156
+ pieces_to_export.append(spacer)
157
+ elif geometrical_part['type'] in ['half set', 'toroidal']:
158
+ shape_data = geometrical_part['shape']
159
+ part_builder = Builder().factory(shape_data)
160
+
161
+ piece = part_builder.get_piece(data=copy.deepcopy(shape_data),
162
+ name=f"Piece_{index}",
163
+ save_files=False,
164
+ export_files=False)
165
+
166
+ m = piece.Placement.Matrix
167
+ m.rotateX(geometrical_part['rotation'][2])
168
+ m.rotateY(geometrical_part['rotation'][0])
169
+ m.rotateZ(geometrical_part['rotation'][1])
170
+ piece.Placement.Matrix = m
171
+ document.recompute()
172
+
173
+ if 'machining' in geometrical_part and geometrical_part['machining'] is not None:
174
+ for machining in geometrical_part['machining']:
175
+ piece = part_builder.apply_machining(piece=piece,
176
+ machining=machining,
177
+ dimensions=flatten_dimensions(shape_data))
178
+ document.recompute()
179
+
180
+ piece.Placement.move(FreeCAD.Vector(geometrical_part['coordinates'][2] * 1000,
181
+ geometrical_part['coordinates'][0] * 1000,
182
+ geometrical_part['coordinates'][1] * 1000))
183
+
184
+ # if the piece is half a set, we add a residual gap between the pieces
185
+ if geometrical_part['type'] in ['half set']:
186
+ residual_gap = 5e-6
187
+ if geometrical_part['rotation'][0] > 0:
188
+ piece.Placement.move(FreeCAD.Vector(0, 0, residual_gap / 2 * 1000))
189
+ else:
190
+ piece.Placement.move(FreeCAD.Vector(0, 0, -residual_gap / 2 * 1000))
191
+
192
+ document.recompute()
193
+
194
+ pieces_to_export.append(piece)
195
+
196
+ if export_files:
197
+ for index, piece in enumerate(pieces_to_export):
198
+ piece.Label = f"core_part_{index}"
199
+ Import.export(pieces_to_export, f"{output_path}{os.path.sep}{project_name}.step")
200
+ Mesh.export(pieces_to_export, f"{output_path}{os.path.sep}{project_name}.obj")
201
+
202
+ if save_files:
203
+ document.saveAs(f"{output_path}{os.path.sep}{project_name}.FCStd")
204
+
205
+ if close_file_after_finishing:
206
+ FreeCAD.closeDocument(project_name)
207
+
208
+ if export_files:
209
+ return f"{output_path}{os.path.sep}{project_name}.step", f"{output_path}{os.path.sep}{project_name}.obj"
210
+ else:
211
+ return pieces_to_export
212
+
213
+ except: # noqa: E722
214
+ with contextlib.suppress(NameError):
215
+ document = FreeCAD.ActiveDocument
216
+ document.saveAs(f"{output_path}/error.FCStd")
217
+ FreeCAD.closeDocument(project_name)
218
+ return None, None
219
+
220
+ def get_core_gapping_technical_drawing(self, project_name, core_data, colors=None, output_path=f'{os.path.dirname(os.path.abspath(__file__))}/../output/', save_files=True, export_files=True):
221
+ def calculate_total_dimensions(margin):
222
+ base_width = 0
223
+ base_height = 0
224
+ for piece in geometrical_description:
225
+ if piece['type'] == "half set":
226
+ dimensions = flatten_dimensions(piece['shape'])
227
+ base_height += dimensions['B']
228
+ elif piece['type'] == "toroidal":
229
+ dimensions = flatten_dimensions(piece['shape'])
230
+ base_height += dimensions['A']
231
+ elif piece['type'] == "spacer":
232
+ base_height += piece['dimensions'][1] * 1000
233
+
234
+ if piece['type'] in ['half set', 'toroidal']:
235
+ base_width = max(base_width, dimensions['A'])
236
+
237
+ return base_width, base_height
238
+
239
+ # try:
240
+ project_name = f"{project_name}_core_gaps_FrontView".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
241
+ geometrical_description = core_data['geometricalDescription']
242
+
243
+ close_file_after_finishing = False
244
+ if FreeCAD.ActiveDocument is None:
245
+ close_file_after_finishing = True
246
+ FreeCAD.newDocument(project_name)
247
+
248
+ document = FreeCAD.ActiveDocument
249
+
250
+ pieces = self.get_core(project_name, geometrical_description, output_path, save_files=False, export_files=False)
251
+
252
+ margin = 35
253
+
254
+ base_width, base_height = calculate_total_dimensions(margin)
255
+ scale = 1000 / (1.25 * base_width)
256
+
257
+ projection_rotation = 180
258
+ for piece in geometrical_description:
259
+ if piece['type'] in ['half set', 'toroidal']:
260
+ dimensions = flatten_dimensions(piece['shape'])
261
+
262
+ if piece['shape']['family'] in ['efd']:
263
+ projection_depth = -dimensions['C'] / 2 + dimensions['K'] + dimensions['F2'] / 2
264
+ elif piece['shape']['family'] in ['epx', 'ep']:
265
+ projection_depth = dimensions['C'] / 2 - dimensions['K']
266
+ else:
267
+ projection_depth = 0
268
+
269
+ if piece['shape']['family'] in ['u', 'ur']:
270
+ projection_rotation = 0
271
+
272
+ projection_depth *= scale
273
+
274
+ front_view = self.get_front_projection(pieces, margin, scale, base_height, base_width, projection_depth, projection_rotation)
275
+ if save_files:
276
+ document.saveAs(f"{output_path}/{project_name}.FCStd")
277
+
278
+ if colors is None:
279
+ colors = {
280
+ "projection_color": "#000000",
281
+ "dimension_color": "#000000"
282
+ }
283
+
284
+ core = FreeCAD.ActiveDocument.addObject("Part::MultiFuse", "Core")
285
+ core.Shapes = pieces
286
+ FreeCAD.ActiveDocument.recompute()
287
+
288
+ core = self.cut_piece_in_half(core)
289
+
290
+ front_view_file = self.add_dimensions_and_export_view(core_data, scale, base_height, base_width, front_view, project_name, margin, colors, save_files, core)
291
+ if save_files:
292
+ document.saveAs(f"{output_path}/{project_name}.FCStd")
293
+ with open(f"{output_path}/{project_name}.svg", "w", encoding="utf-8") as svgFile:
294
+ svgFile.write(front_view_file)
295
+ if close_file_after_finishing:
296
+ FreeCAD.closeDocument(project_name)
297
+
298
+ return {"front_view": front_view_file}
299
+ # except Exception as e: # noqa: E722
300
+ # print(e)
301
+ # FreeCAD.closeDocument(project_name)
302
+ # return {"top_view": None, "front_view": None}
303
+
304
+ def cut_piece_in_half(self, piece):
305
+ document = FreeCAD.ActiveDocument
306
+
307
+ half_volume = document.addObject("Part::Box", "half_volume")
308
+ document.recompute()
309
+ size = 100000
310
+ half_volume.Length = size
311
+ half_volume.Width = size
312
+ half_volume.Height = size
313
+ half_volume.Placement = FreeCAD.Placement(FreeCAD.Vector(-size, -size / 2, -size / 2), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
314
+
315
+ piece_cut = document.addObject("Part::Cut", "Core")
316
+ piece_cut.Base = piece
317
+ piece_cut.Tool = half_volume
318
+ document.recompute()
319
+
320
+ return piece_cut
321
+
322
+ def add_dimensions_and_export_view(self, core_data, scale, base_height, base_width, view, project_name, margin, colors, save_files, core):
323
+ def create_dimension(starting_coordinates, ending_coordinates, dimension_type, dimension_label, label_offset=0, label_alignment=0):
324
+ dimension_svg = ""
325
+
326
+ if dimension_type == "DistanceY":
327
+ main_line_start = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
328
+ main_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
329
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
330
+ left_aux_line_end = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
331
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
332
+ right_aux_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
333
+
334
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + ending_coordinates[0] + label_offset - dimension_font_size / 4},{1000 - view.Y.Value + label_alignment})" stroke-linecap="square" stroke-linejoin="bevel">
335
+ <text x="0" y="0" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400" transform="rotate(-90)">{dimension_label}</text>
336
+ </g>\n""".replace(" ", "")
337
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
338
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
339
+ </g>\n""".replace(" ", "")
340
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
341
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0] + label_offset},{ending_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
342
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L3,-10 L-3,-10 L0,0"/>
343
+ </g>
344
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0] + label_offset},{starting_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
345
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-3,10 L3,10 L0,0"/>
346
+ </g>
347
+ </g>\n""".replace(" ", "")
348
+ elif dimension_type == "DistanceX":
349
+ main_line_start = [starting_coordinates[0], starting_coordinates[1] + label_offset]
350
+ main_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
351
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
352
+ left_aux_line_end = [starting_coordinates[0], starting_coordinates[1] + label_offset]
353
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
354
+ right_aux_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
355
+
356
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="square" stroke-linejoin="bevel">
357
+ <text x="0" y="{ending_coordinates[1] + label_offset - dimension_font_size / 4}" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400">{dimension_label}</text>
358
+ </g>\n""".replace(" ", "")
359
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
360
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
361
+ </g>\n""".replace(" ", "")
362
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
363
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0]},{ending_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
364
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-10,-3 L-10,3 L0,0"/>
365
+ </g>
366
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0]},{starting_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
367
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L10,3 L10,-3 L0,0"/>
368
+ </g>
369
+ </g>\n""".replace(" ", "")
370
+ return dimension_svg
371
+
372
+ projection_line_thickness = 4
373
+ dimension_line_thickness = 1
374
+ dimension_font_size = 20
375
+ horizontal_offset = 30
376
+ horizontal_offset_gaps = 60
377
+
378
+ base_width = 1000
379
+ base_height *= scale
380
+ base_height += margin
381
+ head = f"""<svg xmlns:dc="http://purl.org/dc/elements/1.1/" baseProfile="tiny" xmlns:svg="http://www.w3.org/2000/svg" version="1.2" width="100%" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 {base_width} {base_height}" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="100%" xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
382
+ <title>Open Magnetic SVG Export</title>
383
+ <desc>Drawing exported from https://openmagnetics.com</desc>
384
+ <defs/>
385
+ <g id="{view.Name}" inkscape:label="TechDraw" inkscape:groupmode="layer">
386
+ <g id="DrawingContent" fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel">""".replace(" ", "")
387
+ projetion_head = f""" <g fill-opacity="1" font-size="29.1042" font-style="normal" fill="#ffffff" font-family="MS Shell Dlg 2" stroke="none" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})">\n"""
388
+ projetion_tail = """ </g>\n"""
389
+ tail = """</g>
390
+ </g>
391
+ </svg>
392
+ """.replace(" ", "")
393
+ svgFile_data = ""
394
+ svgFile_data += head
395
+ svgFile_data += projetion_head
396
+
397
+ piece = Draft.scale(core, FreeCAD.Vector(scale, scale, scale))
398
+
399
+ m = piece.Placement.Matrix
400
+ if core_data['functionalDescription']['shape']['family'] in ['u', 'ur']:
401
+ m.rotateZ(math.radians(90))
402
+ else:
403
+ m.rotateZ(math.radians(-90))
404
+ piece.Placement.Matrix = m
405
+ m = piece.Placement.Matrix
406
+ m.rotateY(math.radians(90))
407
+ piece.Placement.Matrix = m
408
+
409
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 1., 0.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
410
+
411
+ svgFile_data += projetion_tail
412
+ geometrical_description = core_data['geometricalDescription']
413
+
414
+ center_offset = 0
415
+ if (len(core_data['processedDescription']['columns']) == 2 and core_data['processedDescription']['columns'][1]['coordinates'][2] == 0):
416
+ for piece in geometrical_description:
417
+ if piece['type'] == "half set" and piece['shape']['family'] not in ['u', 'ur']:
418
+ dimensions = flatten_dimensions(piece['shape'])
419
+ if 'F' in dimensions and dimensions['F'] > 0:
420
+ center_offset = -dimensions['A'] / 2 + dimensions['F'] / 2
421
+ elif 'E' in dimensions and dimensions['E'] > 0:
422
+ center_offset = -dimensions['A'] / 2 + (dimensions['A'] - dimensions['E']) / 4
423
+ else:
424
+ center_offset = -dimensions['A'] / 2 + dimensions['C'] / 2
425
+ break
426
+
427
+ elif piece['type'] == "toroidal":
428
+ dimensions = flatten_dimensions(piece['shape'])
429
+ center_offset = 0
430
+ break
431
+
432
+ grouped_gaps_per_column = {}
433
+
434
+ for gap in core_data['functionalDescription']['gapping']:
435
+ if gap['coordinates'] is None:
436
+ continue
437
+ if (
438
+ gap['coordinates'][0],
439
+ gap['coordinates'][2],
440
+ ) not in grouped_gaps_per_column:
441
+ grouped_gaps_per_column[gap['coordinates'][0], gap['coordinates'][2]] = []
442
+ grouped_gaps_per_column[
443
+ gap['coordinates'][0], gap['coordinates'][2]
444
+ ].append(gap)
445
+
446
+ ordered_gaps_per_column = {}
447
+ for key, value in grouped_gaps_per_column.items():
448
+ ordered_list = value
449
+ ordered_list.sort(key=lambda a: a['coordinates'][1])
450
+ ordered_gaps_per_column[key] = ordered_list
451
+
452
+ column_semi_height = core_data['processedDescription']['columns'][0]['height'] / 2
453
+ for key, gaps_per_column in ordered_gaps_per_column.items():
454
+ for gap_index, gap in enumerate(gaps_per_column):
455
+ if gap['type'] == "additive" and (gap['coordinates'][0] > 0 or gap['coordinates'][2] != 0):
456
+ if gap['length'] < 0.0001:
457
+ dimension_label = f"{round(gap['length'] * 1000000, 2)} μm"
458
+ else:
459
+ dimension_label = f"{round(gap['length'] * 1000, 2)} mm"
460
+ svgFile_data += create_dimension(starting_coordinates=[(gap['coordinates'][0] * 1000 + center_offset) * scale, -gap['length'] * scale * 1000 / 2],
461
+ ending_coordinates=[(gap['coordinates'][0] * 1000 + center_offset) * scale, gap['length'] * scale * 1000 / 2],
462
+ dimension_type="DistanceY",
463
+ dimension_label=dimension_label,
464
+ label_offset=min(base_width / 2, gap['sectionDimensions'][0] / 2 * scale * 1000 + horizontal_offset_gaps))
465
+
466
+ if gap['sectionDimensions'] is None:
467
+ continue
468
+
469
+ if gap['type'] in ["subtractive", "residual"]:
470
+ if gap['length'] < 0.0001:
471
+ dimension_label = f"{round(gap['length'] * 1000000, 2)} μm"
472
+ else:
473
+ dimension_label = f"{round(gap['length'] * 1000, 2)} mm"
474
+ svgFile_data += create_dimension(starting_coordinates=[(gap['coordinates'][0] * 1000 + center_offset) * scale, (-gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
475
+ ending_coordinates=[(gap['coordinates'][0] * 1000 + center_offset) * scale, (gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
476
+ dimension_type="DistanceY",
477
+ dimension_label=dimension_label,
478
+ label_offset=min(base_width / 2, gap['sectionDimensions'][0] / 2 * scale * 1000 + horizontal_offset_gaps),
479
+ label_alignment=-gap['coordinates'][1] * scale * 1000)
480
+ if len(gaps_per_column) > 1 and gap_index < len(gaps_per_column) - 1:
481
+ next_gap = gaps_per_column[gap_index + 1]
482
+ chunk_size = (-gap['length'] / 2 - gap['coordinates'][1]) - (next_gap['length'] / 2 - next_gap['coordinates'][1])
483
+ dimension_label = f"{round(chunk_size * 1000, 2)}"
484
+ if chunk_size * 1000 * scale > 70:
485
+ dimension_label += " mm"
486
+ svgFile_data += create_dimension(ending_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (-gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
487
+ starting_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (next_gap['length'] / 2 - next_gap['coordinates'][1]) * scale * 1000],
488
+ dimension_type="DistanceY",
489
+ dimension_label=dimension_label,
490
+ label_offset=min(base_width / 2, horizontal_offset),
491
+ label_alignment=(-gap['coordinates'][1] - gap['length'] / 2 - chunk_size / 2) * scale * 1000)
492
+
493
+ if len(gaps_per_column) > 1 and gap_index < len(gaps_per_column) - 1:
494
+ next_gap = gaps_per_column[gap_index + 1]
495
+ chunk_size = (-gap['length'] / 2 - gap['coordinates'][1]) - (next_gap['length'] / 2 - next_gap['coordinates'][1])
496
+ dimension_label = f"{round(chunk_size * 1000, 2)}"
497
+ if chunk_size * 1000 * scale > 70:
498
+ dimension_label += " mm"
499
+ svgFile_data += create_dimension(ending_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (-gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
500
+ starting_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (next_gap['length'] / 2 - next_gap['coordinates'][1]) * scale * 1000],
501
+ dimension_type="DistanceY",
502
+ dimension_label=dimension_label,
503
+ label_offset=min(base_width / 2, horizontal_offset),
504
+ label_alignment=(-gap['coordinates'][1] - gap['length'] / 2 - chunk_size / 2) * scale * 1000)
505
+
506
+ if len(gaps_per_column) > 1 and gap_index == 0:
507
+ chunk_size = column_semi_height - (gap['length'] / 2 - gap['coordinates'][1])
508
+ dimension_label = f"{round(chunk_size * 1000, 2)}"
509
+ if chunk_size * 1000 * scale > 70:
510
+ dimension_label += " mm"
511
+ svgFile_data += create_dimension(starting_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
512
+ ending_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, column_semi_height * scale * 1000],
513
+ dimension_type="DistanceY",
514
+ dimension_label=dimension_label,
515
+ label_offset=min(base_width / 2, horizontal_offset),
516
+ label_alignment=(column_semi_height - chunk_size / 2) * scale * 1000)
517
+
518
+ if len(gaps_per_column) > 1 and gap_index == len(gaps_per_column) - 1:
519
+ chunk_size = (-gap['length'] / 2 - gap['coordinates'][1]) + column_semi_height
520
+ dimension_label = f"{round(chunk_size * 1000, 2)}"
521
+ if chunk_size * 1000 * scale > 70:
522
+ dimension_label += " mm"
523
+ svgFile_data += create_dimension(ending_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, (-gap['length'] / 2 - gap['coordinates'][1]) * scale * 1000],
524
+ starting_coordinates=[((gap['coordinates'][0] + gap['sectionDimensions'][0] / 2) * 1000 + center_offset) * scale, -column_semi_height * scale * 1000],
525
+ dimension_type="DistanceY",
526
+ dimension_label=dimension_label,
527
+ label_offset=min(base_width / 2, horizontal_offset),
528
+ label_alignment=(-column_semi_height + chunk_size / 2) * scale * 1000)
529
+
530
+ svgFile_data += tail
531
+
532
+ return svgFile_data
533
+
534
+ def get_front_projection(self, pieces, margin, scale, base_height, base_width, projection_depth, projection_rotation):
535
+
536
+ document = FreeCAD.ActiveDocument
537
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
538
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
539
+ page.Template = template
540
+ document.recompute()
541
+
542
+ # cloned_piece = Draft.make_clone(pieces, forcedraft=True)
543
+
544
+ if len(pieces) > 1:
545
+ aux = document.addObject("Part::MultiFuse", "Fusion")
546
+ aux.Shapes = pieces
547
+ document.recompute()
548
+ else:
549
+ aux = pieces[0]
550
+
551
+ cloned_piece = Draft.scale(aux, FreeCAD.Vector(scale, scale, scale))
552
+ # cloned_piece.Scale = FreeCAD.Vector(scale, scale, scale)
553
+ FreeCAD.ActiveDocument.recompute()
554
+
555
+ top_view = document.addObject('TechDraw::DrawViewPart', 'TopView')
556
+ page.addView(top_view)
557
+ top_view.Source = [cloned_piece]
558
+ top_view.Rotation = 180
559
+ top_view.Direction = FreeCAD.Vector(0.00, 0.00, 1.00)
560
+ top_view.XDirection = FreeCAD.Vector(0.00, -1.00, 0.00)
561
+
562
+ document = FreeCAD.ActiveDocument
563
+ page = document.addObject('TechDraw::DrawPage', 'Front Page')
564
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
565
+ page.Template = template
566
+ document.recompute()
567
+
568
+ section_front_view = document.addObject('TechDraw::DrawViewSection', 'FrontView')
569
+ page.addView(section_front_view)
570
+ section_front_view.BaseView = document.getObject('TopView')
571
+ section_front_view.Source = document.getObject('TopView').Source
572
+ section_front_view.ScaleType = 0
573
+ section_front_view.SectionDirection = 'Down'
574
+ if projection_rotation == 0:
575
+ section_front_view.SectionNormal = FreeCAD.Vector(1.000, 0.000, 0.000)
576
+ else:
577
+ section_front_view.SectionNormal = FreeCAD.Vector(-1.000, 0.000, 0.000)
578
+ section_front_view.SectionOrigin = FreeCAD.Vector(projection_depth, 0.000, 0)
579
+ section_front_view.SectionSymbol = ''
580
+ section_front_view.Label = 'Section - '
581
+ section_front_view.Scale = 1.000000
582
+ section_front_view.ScaleType = 0
583
+ section_front_view.Rotation = projection_rotation
584
+ if projection_rotation == 0:
585
+ section_front_view.Direction = FreeCAD.Vector(1.00, 0.00, 0.00)
586
+ else:
587
+ section_front_view.Direction = FreeCAD.Vector(-1.00, 0.00, 0.00)
588
+ section_front_view.XDirection = FreeCAD.Vector(0.00, 1.00, 0.00)
589
+ section_front_view.X = margin + base_width * scale / 2
590
+ section_front_view.Y = 1000 - base_height * scale / 2 - margin
591
+ document.recompute()
592
+ return section_front_view
593
+
594
+
595
+ class IPiece(metaclass=ABCMeta):
596
+ def __init__(self):
597
+ self.output_path = f'{os.path.dirname(os.path.abspath(__file__))}/../output/'
598
+
599
+ def set_output_path(self, output_path):
600
+ self.output_path = output_path
601
+
602
+ @staticmethod
603
+ def edges_in_boundbox(part, xmin, ymin, zmin, xmax, ymax, zmax):
604
+ bb = FreeCAD.BoundBox(xmin, ymin, zmin, xmax, ymax, zmax)
605
+
606
+ return [
607
+ i
608
+ for i, edge in enumerate(part.Shape.Edges)
609
+ if bb.isInside(edge.BoundBox)
610
+ ]
611
+
612
+ @staticmethod
613
+ def create_sketch():
614
+ document = FreeCAD.ActiveDocument
615
+
616
+ document.addObject('PartDesign::Body', 'Body')
617
+ document.recompute()
618
+
619
+ sketch = document.getObject('Body').newObject('Sketcher::SketchObject', 'Sketch')
620
+ # sketch.Support = (document.getObject('XY_Plane'), [''])
621
+ sketch.MapMode = 'FlatFace'
622
+ document.recompute()
623
+ return sketch
624
+
625
+ @staticmethod
626
+ def extrude_sketch(sketch, part_name, height):
627
+ document = FreeCAD.ActiveDocument
628
+ part = document.addObject('Part::Extrusion', part_name)
629
+ part.Base = sketch
630
+ part.DirMode = "Custom"
631
+ part.Dir = FreeCAD.Vector(0., 0., 1.)
632
+ part.DirLink = None
633
+ part.LengthFwd = height
634
+ part.LengthRev = 0.
635
+ part.Solid = True
636
+ part.Reversed = False
637
+ part.Symmetric = False
638
+ part.TaperAngle = 0.
639
+ part.TaperAngleRev = 0.
640
+
641
+ return part
642
+
643
+ @abstractmethod
644
+ def get_shape_extras(self, data, piece):
645
+ return piece
646
+
647
+ def get_dimensions_and_subtypes(self):
648
+ return {1: ["A", "B", "C", "D", "E", "F"]}
649
+
650
+ def get_top_projection(self, data, piece, margin):
651
+
652
+ dimensions = data["dimensions"]
653
+
654
+ document = FreeCAD.ActiveDocument
655
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
656
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
657
+ page.Template = template
658
+ document.recompute()
659
+
660
+ top_view = document.addObject('TechDraw::DrawViewPart', 'TopView')
661
+ page.addView(top_view)
662
+ top_view.Source = [piece]
663
+ top_view.Direction = FreeCAD.Vector(0.00, 0.00, 1.00)
664
+ top_view.XDirection = FreeCAD.Vector(0.00, -1.00, 0.00)
665
+ top_view.X = margin + dimensions['A'] / 2
666
+
667
+ if data['family'] in ['p', 'rm']:
668
+ base_height = data['dimensions']['A'] + margin
669
+ elif data['family'] in ['pm']:
670
+ base_height = data['dimensions']['E'] + margin
671
+ else:
672
+ base_height = data['dimensions']['C'] + margin
673
+
674
+ top_view.Y = 1000 - base_height / 2
675
+
676
+ top_view.Scale = 1
677
+ document.recompute()
678
+ return top_view
679
+
680
+ def get_front_projection(self, data, piece, margin):
681
+
682
+ dimensions = data["dimensions"]
683
+
684
+ document = FreeCAD.ActiveDocument
685
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
686
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
687
+ page.Template = template
688
+ document.recompute()
689
+
690
+ if data['family'] in ['efd']:
691
+ semi_depth = -dimensions['C'] / 2 + dimensions['K'] + dimensions['F2'] / 2
692
+ elif data['family'] in ['epx']:
693
+ semi_depth = dimensions['C'] / 2 - dimensions['K']
694
+ else:
695
+ semi_depth = 0
696
+
697
+ section_front_view = document.addObject('TechDraw::DrawViewSection', 'FrontView')
698
+ page.addView(section_front_view)
699
+ section_front_view.BaseView = document.getObject('TopView')
700
+ section_front_view.Source = document.getObject('TopView').Source
701
+ section_front_view.ScaleType = 0
702
+ section_front_view.SectionDirection = 'Down'
703
+ section_front_view.SectionNormal = FreeCAD.Vector(-1.000, 0.000, 0.000)
704
+ section_front_view.SectionOrigin = FreeCAD.Vector(semi_depth, 0.000, 0)
705
+ section_front_view.SectionSymbol = ''
706
+ section_front_view.Label = 'Section - '
707
+ section_front_view.Scale = 1.000000
708
+ section_front_view.ScaleType = 0
709
+ section_front_view.Rotation = 0
710
+ section_front_view.Direction = FreeCAD.Vector(-1.00, 0.00, 0.00)
711
+ section_front_view.XDirection = FreeCAD.Vector(0.00, -1.00, 0.00)
712
+ section_front_view.X = margin + dimensions['A'] / 2
713
+ section_front_view.Y = 1000 - margin - dimensions['B'] / 2
714
+ document.recompute()
715
+
716
+ return section_front_view
717
+
718
+ def get_plate(self, data, save_files=False, export_files=True):
719
+ try:
720
+ project_name = f"{data['name']}_plate".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
721
+ data["dimensions"] = flatten_dimensions(data)
722
+
723
+ close_file_after_finishing = False
724
+ if FreeCAD.ActiveDocument is None:
725
+ close_file_after_finishing = True
726
+ FreeCAD.newDocument(project_name)
727
+ document = FreeCAD.ActiveDocument
728
+
729
+ sketch = self.create_sketch()
730
+ self.get_shape_base(data, sketch)
731
+
732
+ document = FreeCAD.ActiveDocument
733
+ document.recompute()
734
+
735
+ part_name = "plate"
736
+
737
+ plate = self.extrude_sketch(
738
+ sketch=sketch,
739
+ part_name=part_name,
740
+ height=data["dimensions"]["B"] - data["dimensions"]["D"]
741
+ )
742
+
743
+ document.recompute()
744
+ if export_files:
745
+ Import.export([plate], f"{self.output_path}/{project_name}.step")
746
+ Mesh.export([plate], f"{self.output_path}/{project_name}.obj")
747
+
748
+ if save_files:
749
+ document.saveAs(f"{self.output_path}/{project_name}.FCStd")
750
+
751
+ if not close_file_after_finishing:
752
+ return plate
753
+
754
+ FreeCAD.closeDocument(project_name)
755
+ return f"{self.output_path}/{project_name}.step", f"{self.output_path}/{project_name}.obj"
756
+ except: # noqa: E722
757
+ FreeCAD.closeDocument(project_name)
758
+ return None, None
759
+
760
+ def get_piece(self, data, name="Piece", save_files=False, export_files=True):
761
+ close_file_after_finishing = FreeCAD.ActiveDocument is None
762
+ try:
763
+ project_name = f"{data['name']}_piece".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
764
+
765
+ data["dimensions"] = flatten_dimensions(data)
766
+
767
+ if FreeCAD.ActiveDocument is None:
768
+ FreeCAD.newDocument(project_name)
769
+ document = FreeCAD.ActiveDocument
770
+
771
+ sketch = self.create_sketch()
772
+ self.get_shape_base(data, sketch)
773
+
774
+ document = FreeCAD.ActiveDocument
775
+ document.recompute()
776
+
777
+ part_name = "piece"
778
+
779
+ base = self.extrude_sketch(
780
+ sketch=sketch,
781
+ part_name=part_name,
782
+ height=data["dimensions"]["B"] if data["family"] != 't' else data["dimensions"]["C"]
783
+ )
784
+
785
+ document.recompute()
786
+
787
+ negative_winding_window = self.get_negative_winding_window(data["dimensions"])
788
+
789
+ if negative_winding_window is None:
790
+ piece_cut = base
791
+ else:
792
+ piece_cut = document.addObject("Part::Cut", "Cut")
793
+ piece_cut.Base = base
794
+ piece_cut.Tool = negative_winding_window
795
+ document.recompute()
796
+
797
+ piece_with_extra = self.get_shape_extras(data, piece_cut)
798
+
799
+ piece = document.addObject('Part::Refine', name)
800
+ piece.Source = piece_with_extra
801
+
802
+ document.recompute()
803
+
804
+ if data["family"] != 't':
805
+ piece.Placement.move(FreeCAD.Vector(0, 0, -data["dimensions"]["B"]))
806
+ else:
807
+ piece.Placement.move(FreeCAD.Vector(0, 0, -data["dimensions"]["C"] / 2))
808
+ m = piece.Placement.Matrix
809
+ m.rotateX(math.radians(90))
810
+ piece.Placement.Matrix = m
811
+ document.recompute()
812
+
813
+ pathlib.Path(self.output_path).mkdir(parents=True, exist_ok=True)
814
+
815
+ if export_files:
816
+ Import.export([piece], f"{self.output_path}/{project_name}.step")
817
+ Mesh.export([piece], f"{self.output_path}/{project_name}.obj")
818
+
819
+ if save_files:
820
+ document.saveAs(f"{self.output_path}/{project_name}.FCStd")
821
+
822
+ if not close_file_after_finishing:
823
+ return piece
824
+ FreeCAD.closeDocument(project_name)
825
+ return f"{self.output_path}/{project_name}.step", f"{self.output_path}/{project_name}.obj"
826
+ except: # noqa: E722
827
+ with contextlib.suppress(NameError):
828
+ FreeCAD.closeDocument(project_name)
829
+ return (None, None) if close_file_after_finishing else None
830
+
831
+ def get_piece_technical_drawing(self, data, colors=None, save_files=False):
832
+ try:
833
+ return self.try_get_piece_technical_drawing(
834
+ data, colors, save_files
835
+ )
836
+ except Exception as e: # noqa: E722
837
+ print(e)
838
+ project_name = f"{data['name']}_piece_scaled".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
839
+ FreeCAD.closeDocument(project_name)
840
+ return {"top_view": None, "front_view": None}
841
+
842
+ def try_get_piece_technical_drawing(self, data, colors, save_files):
843
+ project_name = f"{data['name']}_piece_scaled".replace(" ", "_").replace("-", "_").replace("/", "_").replace(".", "__")
844
+ if colors is None:
845
+ colors = {
846
+ "projection_color": "#000000",
847
+ "dimension_color": "#000000"
848
+ }
849
+
850
+ original_dimensions = flatten_dimensions(data)
851
+ scale = 1000 / (1.25 * original_dimensions['A'])
852
+ data["dimensions"] = {}
853
+ for k, v in original_dimensions.items():
854
+ data["dimensions"][k] = v * scale
855
+
856
+ if FreeCAD.ActiveDocument is None:
857
+ FreeCAD.newDocument(project_name)
858
+ document = FreeCAD.getDocument(project_name)
859
+
860
+ sketch = self.create_sketch()
861
+ self.get_shape_base(data, sketch)
862
+
863
+ document = FreeCAD.ActiveDocument
864
+ document.recompute()
865
+
866
+ part_name = "piece"
867
+
868
+ base = self.extrude_sketch(
869
+ sketch=sketch,
870
+ part_name=part_name,
871
+ height=data["dimensions"]["B"] if data["family"] != 't' else data["dimensions"]["C"]
872
+ )
873
+
874
+ document.recompute()
875
+
876
+ negative_winding_window = self.get_negative_winding_window(data["dimensions"])
877
+
878
+ if negative_winding_window is None:
879
+ piece_cut = base
880
+ else:
881
+ piece_cut = document.addObject("Part::Cut", "Cut")
882
+ piece_cut.Base = base
883
+ piece_cut.Tool = negative_winding_window
884
+ document.recompute()
885
+
886
+ piece_with_extra = self.get_shape_extras(data, piece_cut)
887
+
888
+ piece = document.addObject('Part::Refine', 'Refine')
889
+ piece.Source = piece_with_extra
890
+
891
+ document.recompute()
892
+
893
+ error_in_piece = False
894
+ for obj in FreeCAD.ActiveDocument.Objects:
895
+ if not obj.isValid():
896
+ error_in_piece = True
897
+ print(f"Error in part: {obj.Name}")
898
+ break
899
+
900
+ pathlib.Path(self.output_path).mkdir(parents=True, exist_ok=True)
901
+
902
+ margin = 35
903
+
904
+ if not error_in_piece:
905
+ top_view = self.get_top_projection(data, piece, margin)
906
+ front_view = self.get_front_projection(data, piece, margin)
907
+ if save_files:
908
+ document.saveAs(f"{self.output_path}/{project_name}.FCStd")
909
+ if not error_in_piece:
910
+ top_view_file = self.add_dimensions_and_export_view(data, original_dimensions, top_view, project_name, margin, colors, save_files, piece)
911
+ front_view_file = self.add_dimensions_and_export_view(data, original_dimensions, front_view, project_name, margin, colors, save_files, piece)
912
+
913
+ FreeCAD.closeDocument(project_name)
914
+
915
+ return (
916
+ {"top_view": None, "front_view": None}
917
+ if error_in_piece
918
+ else {"top_view": top_view_file, "front_view": front_view_file}
919
+ )
920
+
921
+ def add_dimensions_and_export_view(self, data, original_dimensions, view, project_name, margin, colors, save_files, piece):
922
+ def calculate_total_dimensions():
923
+ base_width = data['dimensions']['A'] + margin
924
+ base_width += horizontal_offset
925
+ top_base_width = base_width
926
+ if 'C' in dimensions:
927
+ top_base_width += increment
928
+ if 'L' in dimensions:
929
+ top_base_width += increment
930
+ if 'K' in dimensions:
931
+ top_base_width += increment
932
+ front_base_width = base_width
933
+ if 'B' in dimensions:
934
+ front_base_width += increment
935
+ if 'D' in dimensions:
936
+ front_base_width += increment
937
+
938
+ base_width = max(top_base_width, front_base_width)
939
+
940
+ if view.Name == "TopView":
941
+ # base_width = data['dimensions']['A'] + margin
942
+ # base_width += horizontal_offset
943
+ # if 'C' in dimensions:
944
+ # base_width += increment
945
+ # if 'L' in dimensions:
946
+ # base_width += increment
947
+ # if 'K' in dimensions:
948
+ # base_width += increment
949
+
950
+ if data['family'] == 'p':
951
+ base_height = data['dimensions']['A'] + margin
952
+ elif data['family'] in ['rm', 'pm']:
953
+ base_height = data['dimensions']['E'] + margin
954
+ else:
955
+ base_height = data['dimensions']['C'] + margin
956
+
957
+ if 'A' in dimensions:
958
+ base_height += increment
959
+ if 'E' in dimensions:
960
+ base_height += increment
961
+ if 'F' in dimensions:
962
+ base_height += increment
963
+ if 'G' in dimensions and dimensions['G'] > 0:
964
+ base_height += increment
965
+ if 'H' in dimensions and dimensions['H'] > 0:
966
+ base_height += increment
967
+ if 'J' in dimensions:
968
+ base_height += increment
969
+
970
+ if view.Name == "FrontView":
971
+ # base_width = data['dimensions']['A'] + margin
972
+ # base_width += horizontal_offset
973
+ # if 'B' in dimensions:
974
+ # base_width += increment
975
+ # if 'D' in dimensions:
976
+ # base_width += increment
977
+
978
+ base_height = data['dimensions']['B'] + margin * 2
979
+
980
+ return base_width, base_height
981
+
982
+ def create_dimension(starting_coordinates, ending_coordinates, dimension_type, dimension_label, label_offset=0, label_alignment=0):
983
+ dimension_svg = ""
984
+
985
+ if dimension_type == "DistanceY":
986
+ main_line_start = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
987
+ main_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
988
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
989
+ left_aux_line_end = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
990
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
991
+ right_aux_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
992
+
993
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + ending_coordinates[0] + label_offset - dimension_font_size / 4},{1000 - view.Y.Value + label_alignment})" stroke-linecap="square" stroke-linejoin="bevel">
994
+ <text x="0" y="0" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400" transform="rotate(-90)">{dimension_label}</text>
995
+ </g>\n""".replace(" ", "")
996
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
997
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
998
+ </g>\n""".replace(" ", "")
999
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
1000
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0] + label_offset},{ending_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
1001
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L6,-15 L-6,-15 L0,0"/>
1002
+ </g>
1003
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0] + label_offset},{starting_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
1004
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-6,15 L6,15 L0,0"/>
1005
+ </g>
1006
+ </g>\n""".replace(" ", "")
1007
+ elif dimension_type == "DistanceX":
1008
+ main_line_start = [starting_coordinates[0], starting_coordinates[1] + label_offset]
1009
+ main_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
1010
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
1011
+ left_aux_line_end = [starting_coordinates[0], starting_coordinates[1] + label_offset]
1012
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
1013
+ right_aux_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
1014
+
1015
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="square" stroke-linejoin="bevel">
1016
+ <text x="0" y="{ending_coordinates[1] + label_offset - dimension_font_size / 4}" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400">{dimension_label}</text>
1017
+ </g>\n""".replace(" ", "")
1018
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
1019
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
1020
+ </g>\n""".replace(" ", "")
1021
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
1022
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0]},{ending_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
1023
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-15,-6 L-15,6 L0,0"/>
1024
+ </g>
1025
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0]},{starting_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
1026
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L15,6 L15,-6 L0,0"/>
1027
+ </g>
1028
+ </g>\n""".replace(" ", "")
1029
+ return dimension_svg
1030
+
1031
+ projection_line_thickness = 4
1032
+ dimension_line_thickness = 1
1033
+ dimension_font_size = 50
1034
+ horizontal_offset = 75
1035
+ vertical_offset = 75
1036
+ correction = 0
1037
+ increment = 75
1038
+ dimensions = data["dimensions"]
1039
+ if data['family'] not in ['p']:
1040
+ shape_semi_height = dimensions['C'] / 2
1041
+ else:
1042
+ shape_semi_height = dimensions['A'] / 2
1043
+ scale = 1000 / (1.25 * original_dimensions['A'])
1044
+ base_width, base_height = calculate_total_dimensions()
1045
+ head = f"""<svg xmlns:dc="http://purl.org/dc/elements/1.1/" baseProfile="tiny" xmlns:svg="http://www.w3.org/2000/svg" version="1.2" width="100%" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 {base_width} {base_height}" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="100%" xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
1046
+ <title>Open Magnetic SVG Export</title>
1047
+ <desc>Drawing exported from https://openmagnetics.com</desc>
1048
+ <defs/>
1049
+ <g id="{view.Name}" inkscape:label="TechDraw" inkscape:groupmode="layer">
1050
+ <g id="DrawingContent" fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel">""".replace(" ", "")
1051
+ projetion_head = f""" <g fill-opacity="1" font-size="29.1042" font-style="normal" fill="#ffffff" font-family="MS Shell Dlg 2" stroke="none" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})">\n"""
1052
+ projetion_tail = """ </g>\n"""
1053
+ tail = """</g>
1054
+ </g>
1055
+ </svg>
1056
+ """.replace(" ", "")
1057
+ svgFile_data = ""
1058
+ svgFile_data += head
1059
+ svgFile_data += projetion_head
1060
+
1061
+ if view.Name == "TopView":
1062
+ m = piece.Placement.Matrix
1063
+ m.rotateZ(math.radians(90))
1064
+ piece.Placement.Matrix = m
1065
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 0., 1.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
1066
+ else:
1067
+ m = piece.Placement.Matrix
1068
+ m.rotateY(math.radians(90))
1069
+ piece.Placement.Matrix = m
1070
+ piece.Placement.move(FreeCAD.Vector(-dimensions["B"] / 2, 0, 0))
1071
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 1., 0.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
1072
+
1073
+ svgFile_data += projetion_tail
1074
+ if view.Name == "TopView":
1075
+ if "L" in dimensions and dimensions["L"] > 0:
1076
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['J'] / 2, -dimensions['L'] / 2],
1077
+ ending_coordinates=[dimensions['J'] / 2, dimensions['L'] / 2],
1078
+ dimension_type="DistanceY",
1079
+ dimension_label=f"L: {round(dimensions['L'] / scale, 2)} mm",
1080
+ label_offset=horizontal_offset + dimensions['A'] / 2 - dimensions['J'] / 2)
1081
+ horizontal_offset += increment
1082
+ k = 0
1083
+ if "K" in dimensions and dimensions["K"] > 0:
1084
+ if data['family'] == 'efd':
1085
+ height_of_dimension = dimensions['C'] / 2
1086
+ k = -dimensions['K']
1087
+ else:
1088
+ height_of_dimension = -dimensions['C'] / 2
1089
+ k = dimensions['K']
1090
+ if dimensions['K'] < 0:
1091
+ correction = dimensions['K'] / 2
1092
+ else:
1093
+ correction = 0
1094
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['F'] / 2, height_of_dimension + correction],
1095
+ ending_coordinates=[dimensions['F'] / 2, height_of_dimension + k + correction],
1096
+ dimension_type="DistanceY",
1097
+ dimension_label=f"K: {round(original_dimensions['K'], 2)} mm",
1098
+ label_offset=horizontal_offset + (dimensions['A'] / 2 - dimensions['F'] / 2),
1099
+ label_alignment=height_of_dimension + k / 2 + correction)
1100
+ horizontal_offset += increment
1101
+ if "F2" in dimensions and dimensions["F2"] > 0:
1102
+ if data['family'] in ['efd']:
1103
+ svgFile_data += create_dimension(starting_coordinates=[0, dimensions['C'] / 2 + correction - dimensions['K'] - dimensions['F2']],
1104
+ ending_coordinates=[0, dimensions['C'] / 2 + correction - dimensions['K']],
1105
+ dimension_type="DistanceY",
1106
+ dimension_label=f"F2: {round(original_dimensions['F2'], 2)} mm",
1107
+ label_offset=horizontal_offset + dimensions['A'] / 2,
1108
+ label_alignment=dimensions['F2'] / 2 + k / 2 + correction)
1109
+ else:
1110
+ svgFile_data += create_dimension(starting_coordinates=[0, -dimensions['F2'] / 2],
1111
+ ending_coordinates=[0, dimensions['F2'] / 2],
1112
+ dimension_type="DistanceY",
1113
+ dimension_label=f"F2: {round(original_dimensions['F2'], 2)} mm",
1114
+ label_offset=horizontal_offset + dimensions['A'] / 2)
1115
+ horizontal_offset += increment
1116
+ if "C" in dimensions and dimensions['C'] > 0:
1117
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['C'] / 2 + correction],
1118
+ ending_coordinates=[dimensions['A'] / 2, dimensions['C'] / 2 + correction],
1119
+ dimension_type="DistanceY",
1120
+ dimension_label=f"C: {round(original_dimensions['C'], 2)} mm",
1121
+ label_offset=horizontal_offset)
1122
+ horizontal_offset += increment
1123
+ if "H" in dimensions and dimensions['H'] > 0:
1124
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['H'] / 2, 0],
1125
+ ending_coordinates=[dimensions['H'] / 2, 0],
1126
+ dimension_type="DistanceX",
1127
+ dimension_label=f"H: {round(original_dimensions['H'], 2)} mm",
1128
+ label_offset=vertical_offset + shape_semi_height)
1129
+ vertical_offset += increment
1130
+ if "J" in dimensions and data['family'] == 'pq':
1131
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['J'] / 2, dimensions['L'] / 2],
1132
+ ending_coordinates=[dimensions['J'] / 2, dimensions['L'] / 2],
1133
+ dimension_type="DistanceX",
1134
+ dimension_label=f"J: {round(dimensions['J'] / scale, 2)} mm",
1135
+ label_offset=vertical_offset + shape_semi_height - dimensions['L'] / 2)
1136
+ vertical_offset += increment
1137
+ if data['family'] in ['ep', 'epx']:
1138
+ k = dimensions['C'] / 2 - dimensions['K']
1139
+ elif data['family'] in ['efd']:
1140
+ if dimensions['K'] < 0:
1141
+ k = - dimensions['C'] / 2 - dimensions['K'] * 2
1142
+ else:
1143
+ k = 0
1144
+
1145
+ if data['family'] not in ['p']:
1146
+ if "F" in dimensions and dimensions["F"] > 0:
1147
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['F'] / 2, -k],
1148
+ ending_coordinates=[dimensions['F'] / 2, -k],
1149
+ dimension_type="DistanceX",
1150
+ dimension_label=f"F: {round(original_dimensions['F'], 2)} mm",
1151
+ label_offset=vertical_offset + k + shape_semi_height)
1152
+ vertical_offset += increment
1153
+ if "G" in dimensions and dimensions['G'] > 0:
1154
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['G'] / 2, shape_semi_height],
1155
+ ending_coordinates=[dimensions['G'] / 2, shape_semi_height],
1156
+ dimension_type="DistanceX",
1157
+ dimension_label=f"G: {round(original_dimensions['G'], 2)} mm",
1158
+ label_offset=vertical_offset)
1159
+ vertical_offset += increment
1160
+ else:
1161
+ if "G" in dimensions and dimensions['G'] > 0:
1162
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['G'] / 2, dimensions['E'] / 2],
1163
+ ending_coordinates=[dimensions['G'] / 2, dimensions['E'] / 2],
1164
+ dimension_type="DistanceX",
1165
+ dimension_label=f"G: {round(original_dimensions['G'], 2)} mm",
1166
+ label_offset=vertical_offset + dimensions['A'] / 2 - dimensions['E'] / 2)
1167
+ vertical_offset += increment
1168
+ if "F" in dimensions and dimensions["F"] > 0:
1169
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['F'] / 2, -k],
1170
+ ending_coordinates=[dimensions['F'] / 2, -k],
1171
+ dimension_type="DistanceX",
1172
+ dimension_label=f"F: {round(original_dimensions['F'], 2)} mm",
1173
+ label_offset=vertical_offset + k + shape_semi_height)
1174
+ vertical_offset += increment
1175
+
1176
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['E'] / 2, -k],
1177
+ ending_coordinates=[dimensions['E'] / 2, -k],
1178
+ dimension_type="DistanceX",
1179
+ dimension_label=f"E: {round(original_dimensions['E'], 2)} mm",
1180
+ label_offset=vertical_offset + k + shape_semi_height)
1181
+ vertical_offset += increment
1182
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
1183
+ ending_coordinates=[dimensions['A'] / 2, 0],
1184
+ dimension_type="DistanceX",
1185
+ dimension_label=f"A: {round(original_dimensions['A'], 2)} mm",
1186
+ label_offset=vertical_offset + shape_semi_height)
1187
+ vertical_offset += increment
1188
+ else:
1189
+ starting_point_for_d = dimensions['E'] / 2
1190
+ svgFile_data += create_dimension(starting_coordinates=[starting_point_for_d, -dimensions['B'] / 2],
1191
+ ending_coordinates=[starting_point_for_d, -dimensions['B'] / 2 + dimensions['D']],
1192
+ dimension_type="DistanceY",
1193
+ dimension_label=f"D: {round(original_dimensions['D'], 2)} mm",
1194
+ label_offset=horizontal_offset + (dimensions['A'] / 2 - starting_point_for_d),
1195
+ label_alignment=-dimensions['B'] / 2 + dimensions['D'] / 2)
1196
+ horizontal_offset += increment
1197
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['B'] / 2],
1198
+ ending_coordinates=[dimensions['A'] / 2, dimensions['B'] / 2],
1199
+ dimension_type="DistanceY",
1200
+ dimension_label=f"B: {round(original_dimensions['B'], 2)} mm",
1201
+ label_offset=horizontal_offset)
1202
+
1203
+ svgFile_data += tail
1204
+
1205
+ if save_files:
1206
+ svgFile = open(f"{self.output_path}/{project_name}_{view.Name}.svg", "w")
1207
+ svgFile.write(svgFile_data)
1208
+ svgFile.close()
1209
+ return svgFile_data
1210
+
1211
+ @abstractmethod
1212
+ def get_shape_base(self, data, sketch):
1213
+ raise NotImplementedError
1214
+
1215
+ @abstractmethod
1216
+ def get_negative_winding_window(self, dimensions):
1217
+ raise NotImplementedError
1218
+
1219
+ def apply_machining(self, piece, machining, dimensions):
1220
+ document = FreeCAD.ActiveDocument
1221
+
1222
+ original_tool = document.addObject("Part::Box", "tool")
1223
+ original_tool.Length = dimensions["A"]
1224
+ x_coordinate = -dimensions["A"] / 2
1225
+ if machining['coordinates'][0] == 0:
1226
+ original_tool.Width = dimensions["F"]
1227
+ original_tool.Length = dimensions["F"]
1228
+ y_coordinate = -dimensions["F"] / 2
1229
+ x_coordinate = -dimensions["F"] / 2
1230
+ else:
1231
+ original_tool.Width = dimensions["A"] / 2
1232
+ if machining['coordinates'][0] < 0:
1233
+ y_coordinate = 0
1234
+ if machining['coordinates'][0] > 0:
1235
+ y_coordinate = -dimensions["A"] / 2
1236
+
1237
+ original_tool.Height = machining['length'] * 1000
1238
+ original_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1239
+
1240
+ if machining['coordinates'][0] == 0:
1241
+ tool = original_tool
1242
+ else:
1243
+ central_column_tool = document.addObject("Part::Box", "central_column_tool")
1244
+ central_column_width = dimensions["F"] * 1.001
1245
+ central_column_tool.Length = central_column_width
1246
+ central_column_tool.Width = central_column_width
1247
+ central_column_tool.Height = machining['length'] * 1000
1248
+ central_column_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(-central_column_width / 2, -central_column_width / 2, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1249
+
1250
+ tool = document.addObject("Part::Cut", "machined_piece")
1251
+ tool.Base = original_tool
1252
+ tool.Tool = central_column_tool
1253
+ document.recompute()
1254
+
1255
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
1256
+ machined_piece.Base = piece
1257
+ machined_piece.Tool = tool
1258
+ document.recompute()
1259
+
1260
+ return machined_piece
1261
+
1262
+
1263
+ class P(IPiece):
1264
+
1265
+ def get_dimensions_and_subtypes(self):
1266
+ return {
1267
+ 1: ["A", "B", "C", "D", "E", "F", "G", "H"],
1268
+ 2: ["A", "B", "C", "D", "E", "F", "G", "H"],
1269
+ 3: ["A", "B", "D", "E", "F", "G", "H"],
1270
+ 4: ["A", "B", "C", "D", "E", "F", "G", "H"]
1271
+ }
1272
+
1273
+ def get_shape_extras(self, data, piece):
1274
+ # rotation in order to avoid cut in projection
1275
+ m = piece.Base.Placement.Matrix
1276
+ m.rotateZ(math.radians(180))
1277
+ piece.Base.Placement.Matrix = m
1278
+
1279
+ dimensions = data["dimensions"]
1280
+ familySubtype = data["familySubtype"]
1281
+ document = FreeCAD.ActiveDocument
1282
+ if familySubtype == '3' or familySubtype == '4':
1283
+ return piece
1284
+ elif familySubtype == '1' or familySubtype == '2':
1285
+ lateral_right_cut_box = document.addObject("Part::Box", "lateral_right_cut_box")
1286
+ document.recompute()
1287
+ lateral_right_cut_box.Length = (dimensions["A"] - dimensions["F"]) / 2
1288
+ lateral_right_cut_box.Width = dimensions["G"]
1289
+ lateral_right_cut_box.Height = dimensions["D"]
1290
+ lateral_right_cut_box.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["F"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1291
+
1292
+ lateral_left_cut_box = document.addObject("Part::Box", "lateral_left_cut_box")
1293
+ document.recompute()
1294
+ lateral_left_cut_box.Length = (dimensions["A"] - dimensions["F"]) / 2
1295
+ lateral_left_cut_box.Width = dimensions["G"]
1296
+ lateral_left_cut_box.Height = dimensions["D"]
1297
+ lateral_left_cut_box.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["F"] / 2 - (dimensions["A"] - dimensions["F"]) / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1298
+
1299
+ piece_cut_only_right = document.addObject("Part::Cut", "lateral_right_cut")
1300
+ piece_cut_only_right.Base = piece
1301
+ piece_cut_only_right.Tool = lateral_right_cut_box
1302
+ document.recompute()
1303
+
1304
+ piece_cut = document.addObject("Part::Cut", "lateral_right_cut")
1305
+ piece_cut.Base = piece_cut_only_right
1306
+ piece_cut.Tool = lateral_left_cut_box
1307
+ document.recompute()
1308
+
1309
+ piece = document.addObject('Part::Refine', 'Cut')
1310
+ piece.Source = piece_cut
1311
+
1312
+ document.recompute()
1313
+ if familySubtype == '1':
1314
+ zmin = dimensions["B"] - dimensions["D"]
1315
+ internal_xmin = dimensions["F"] / 2 + dimensions["E"] / 8
1316
+ elif familySubtype == '2':
1317
+ zmin = 0
1318
+ if "C" in dimensions and dimensions['C'] > 0:
1319
+ internal_xmin = dimensions["C"] / 2 + (dimensions["E"] - dimensions["C"]) / 4
1320
+ else:
1321
+ aux_c = dimensions["E"] * math.cos(math.asin(dimensions["G"] / dimensions["E"])) * 0.9
1322
+ internal_xmin = aux_c / 2 + (dimensions["E"] - aux_c) / 4
1323
+
1324
+ external_top_right_vertex = self.edges_in_boundbox(part=piece,
1325
+ xmin=dimensions["E"] / 2,
1326
+ xmax=dimensions["A"] / 2,
1327
+ ymin=dimensions["G"] / 4,
1328
+ ymax=3 * dimensions["G"] / 4,
1329
+ zmin=zmin,
1330
+ zmax=dimensions["B"])[0]
1331
+ external_bottom_right_vertex = self.edges_in_boundbox(part=piece,
1332
+ xmin=dimensions["E"] / 2,
1333
+ xmax=dimensions["A"] / 2,
1334
+ ymax=-dimensions["G"] / 4,
1335
+ ymin=-3 * dimensions["G"] / 4,
1336
+ zmin=zmin,
1337
+ zmax=dimensions["B"])[0]
1338
+ external_top_left_vertex = self.edges_in_boundbox(part=piece,
1339
+ xmin=-dimensions["A"] / 2,
1340
+ xmax=-dimensions["E"] / 2,
1341
+ ymin=dimensions["G"] / 4,
1342
+ ymax=3 * dimensions["G"] / 4,
1343
+ zmin=zmin,
1344
+ zmax=dimensions["B"])[0]
1345
+ external_bottom_left_vertex = self.edges_in_boundbox(part=piece,
1346
+ xmin=-dimensions["A"] / 2,
1347
+ xmax=-dimensions["E"] / 2,
1348
+ ymax=-dimensions["G"] / 4,
1349
+ ymin=-3 * dimensions["G"] / 4,
1350
+ zmin=zmin,
1351
+ zmax=dimensions["B"])[0]
1352
+
1353
+ external_vertexes = [external_top_left_vertex, external_bottom_left_vertex, external_top_right_vertex, external_bottom_right_vertex]
1354
+
1355
+ internal_vertexes = []
1356
+ internal_top_right_vertex = self.edges_in_boundbox(part=piece,
1357
+ xmin=internal_xmin,
1358
+ xmax=dimensions["E"] / 2,
1359
+ ymin=dimensions["G"] / 4,
1360
+ ymax=3 * dimensions["G"] / 4,
1361
+ zmin=dimensions["B"] - dimensions["D"],
1362
+ zmax=dimensions["B"])
1363
+ if len(internal_top_right_vertex) > 0:
1364
+ internal_vertexes.append(internal_top_right_vertex[0])
1365
+ internal_bottom_right_vertex = self.edges_in_boundbox(part=piece,
1366
+ xmin=internal_xmin,
1367
+ xmax=dimensions["E"] / 2,
1368
+ ymax=-dimensions["G"] / 4,
1369
+ ymin=-3 * dimensions["G"] / 4,
1370
+ zmin=dimensions["B"] - dimensions["D"],
1371
+ zmax=dimensions["B"])
1372
+ if len(internal_bottom_right_vertex) > 0:
1373
+ internal_vertexes.append(internal_bottom_right_vertex[0])
1374
+ internal_top_left_vertex = self.edges_in_boundbox(part=piece,
1375
+ xmin=-dimensions["E"] / 2,
1376
+ xmax=-internal_xmin,
1377
+ ymin=dimensions["G"] / 4,
1378
+ ymax=3 * dimensions["G"] / 4,
1379
+ zmin=dimensions["B"] - dimensions["D"],
1380
+ zmax=dimensions["B"])
1381
+ if len(internal_top_left_vertex) > 0:
1382
+ internal_vertexes.append(internal_top_left_vertex[0])
1383
+ internal_bottom_left_vertex = self.edges_in_boundbox(part=piece,
1384
+ xmin=-dimensions["E"] / 2,
1385
+ xmax=-internal_xmin,
1386
+ ymax=-dimensions["G"] / 4,
1387
+ ymin=-3 * dimensions["G"] / 4,
1388
+ zmin=dimensions["B"] - dimensions["D"],
1389
+ zmax=dimensions["B"])
1390
+ if len(internal_bottom_left_vertex) > 0:
1391
+ internal_vertexes.append(internal_bottom_left_vertex[0])
1392
+
1393
+ if familySubtype == '2':
1394
+ if "C" not in dimensions:
1395
+ internal_xmax = dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4
1396
+ else:
1397
+ internal_xmax = internal_xmin
1398
+ base_cut_bottom_right_vertex = self.edges_in_boundbox(part=piece,
1399
+ xmin=dimensions["F"] / 2,
1400
+ xmax=internal_xmax,
1401
+ ymin=-3 * dimensions["G"] / 4,
1402
+ ymax=-dimensions["G"] / 4,
1403
+ zmin=0,
1404
+ zmax=dimensions["B"] - dimensions["D"])[0]
1405
+ base_cut_top_right_vertex = self.edges_in_boundbox(part=piece,
1406
+ xmin=dimensions["F"] / 2,
1407
+ xmax=internal_xmax,
1408
+ ymin=dimensions["G"] / 4,
1409
+ ymax=3 * dimensions["G"] / 4,
1410
+ zmin=0,
1411
+ zmax=dimensions["B"] - dimensions["D"])[0]
1412
+ base_cut_bottom_left_vertex = self.edges_in_boundbox(part=piece,
1413
+ xmin=-internal_xmax,
1414
+ xmax=-dimensions["F"] / 2,
1415
+ ymin=-3 * dimensions["G"] / 4,
1416
+ ymax=-dimensions["G"] / 4,
1417
+ zmin=0,
1418
+ zmax=dimensions["B"] - dimensions["D"])[0]
1419
+ base_cut_top_left_vertex = self.edges_in_boundbox(part=piece,
1420
+ xmin=-internal_xmax,
1421
+ xmax=-dimensions["F"] / 2,
1422
+ ymin=dimensions["G"] / 4,
1423
+ ymax=3 * dimensions["G"] / 4,
1424
+ zmin=0,
1425
+ zmax=dimensions["B"] - dimensions["D"])[0]
1426
+ base_vertexes = [base_cut_bottom_right_vertex,
1427
+ base_cut_top_right_vertex,
1428
+ base_cut_bottom_left_vertex,
1429
+ base_cut_top_left_vertex]
1430
+
1431
+ fillet_external_radius = 0.95 * utils.decimal_floor((dimensions['A'] - dimensions["E"]) / 4, 2)
1432
+ fillet_internal_radius = 0.95 * min(utils.decimal_floor((dimensions['A'] - dimensions["E"]) / 4, 2), (dimensions["E"] - dimensions["E"] * math.cos(math.asin(dimensions["G"] / dimensions["E"]))))
1433
+ fillet_base_radius = 0.95 * min(0.1 * dimensions["G"], (dimensions["E"] - dimensions["E"] * math.cos(math.asin(dimensions["G"] / dimensions["E"]))) / 4)
1434
+ fillet = document.addObject("Part::Fillet", "Fillet")
1435
+ fillet.Base = piece
1436
+ __fillets__ = []
1437
+ for i in external_vertexes:
1438
+ __fillets__.append((i + 1, fillet_external_radius, fillet_external_radius))
1439
+ for i in internal_vertexes:
1440
+ __fillets__.append((i + 1, fillet_internal_radius, fillet_internal_radius))
1441
+ if familySubtype == '2':
1442
+ for i in base_vertexes:
1443
+ __fillets__.append((i + 1, fillet_base_radius, fillet_base_radius))
1444
+ fillet.Edges = __fillets__
1445
+ document.recompute()
1446
+ return fillet
1447
+
1448
+ def get_shape_base(self, data, sketch):
1449
+ dimensions = data["dimensions"]
1450
+ familySubtype = data["familySubtype"]
1451
+
1452
+ external_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["A"] / 2), False)
1453
+ sketch.addConstraint(Sketcher.Constraint('Coincident', external_circle, 3, -1, 1))
1454
+ sketch.addConstraint(Sketcher.Constraint('Diameter', external_circle, dimensions["A"]))
1455
+ if "H" in dimensions and dimensions["H"] > 0:
1456
+ internal_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["H"] / 2), False)
1457
+ sketch.addConstraint(Sketcher.Constraint('Coincident', internal_circle, 3, -1, 1))
1458
+ sketch.addConstraint(Sketcher.Constraint('Diameter', internal_circle, dimensions["H"]))
1459
+
1460
+ if familySubtype == '1':
1461
+ pass
1462
+ elif familySubtype == '2':
1463
+ a = dimensions["A"] / 2
1464
+ if "C" in dimensions and dimensions["C"] > 0:
1465
+ c = dimensions["C"] / 2
1466
+ else:
1467
+ c = utils.decimal_floor(dimensions["E"] * math.cos(math.asin(dimensions["G"] / dimensions["E"])) / 2, 2) * 0.95
1468
+ g = dimensions["G"] / 2
1469
+ right_dent_top = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(a, g, 0), FreeCAD.Vector(c, g, 0)), False)
1470
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, g, 0), FreeCAD.Vector(c, -g, 0)), False)
1471
+ right_dent_bottom = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -g, 0), FreeCAD.Vector(a, -g, 0)), False)
1472
+ sketch.trim(right_dent_top, FreeCAD.Vector(a, g, 0))
1473
+ sketch.trim(right_dent_bottom, FreeCAD.Vector(a, -g, 0))
1474
+
1475
+ left_dent_top = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-a, g, 0), FreeCAD.Vector(-c, g, 0)), False)
1476
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, g, 0), FreeCAD.Vector(-c, -g, 0)), False)
1477
+ left_dent_bottom = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -g, 0), FreeCAD.Vector(-a, -g, 0)), False)
1478
+ sketch.trim(left_dent_top, FreeCAD.Vector(-a, g, 0))
1479
+ sketch.trim(left_dent_bottom, FreeCAD.Vector(-a, -g, 0))
1480
+
1481
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_dent_top, 2, right_dent_top, 2, c * 2))
1482
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_dent_bottom, 1, right_dent_bottom, 1, c * 2))
1483
+
1484
+ sketch.trim(external_circle, FreeCAD.Vector(-dimensions["A"] / 2, 0, 0))
1485
+ sketch.trim(external_circle, FreeCAD.Vector(dimensions["A"] / 2, 0, 0))
1486
+
1487
+ elif familySubtype == '3':
1488
+ e = dimensions["E"] / 2
1489
+ f = dimensions["F"] / 2 * 1.01 # to avoid bug in three.js
1490
+ g = dimensions["G"] / 2
1491
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(e - g, 0, 0), FreeCAD.Vector(0, 0, 1), g), -math.pi / 2, math.pi / 2))
1492
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(f + g, 0, 0), FreeCAD.Vector(0, 0, 1), g), math.pi / 2, -math.pi / 2))
1493
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(f + g, g, 0), FreeCAD.Vector(e - g, g, 0)), False)
1494
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(f + g, -g, 0), FreeCAD.Vector(e - g, -g, 0)), False)
1495
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(-(e - g), 0, 0), FreeCAD.Vector(0, 0, 1), g), math.pi / 2, -math.pi / 2))
1496
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(-(f + g), 0, 0), FreeCAD.Vector(0, 0, 1), g), -math.pi / 2, math.pi / 2))
1497
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-(f + g), g, 0), FreeCAD.Vector(-(e - g), g, 0)), False)
1498
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-(f + g), -g, 0), FreeCAD.Vector(-(e - g), -g, 0)), False)
1499
+ elif familySubtype == '4':
1500
+ g = dimensions["G"] / 2
1501
+ c = dimensions["C"]
1502
+ sketch.addGeometry(Part.Circle(FreeCAD.Vector(c, 0, 0), FreeCAD.Vector(0, 0, 1), g))
1503
+
1504
+ def get_negative_winding_window(self, dimensions):
1505
+ document = FreeCAD.ActiveDocument
1506
+ tube = Shapes.addTube(FreeCAD.ActiveDocument, "winding_window")
1507
+ tube.Height = dimensions["D"]
1508
+ tube.InnerRadius = dimensions["F"] / 2
1509
+ tube.OuterRadius = dimensions["E"] / 2
1510
+ tube.Placement = FreeCAD.Placement(FreeCAD.Vector(0, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
1511
+ document.recompute()
1512
+
1513
+ return tube
1514
+
1515
+
1516
+ class Pq(P):
1517
+ def get_dimensions_and_subtypes(self):
1518
+ return {1: ["A", "B", "C", "D", "E", "F", "G"]}
1519
+
1520
+ def get_shape_base(self, data, sketch):
1521
+ dimensions = data["dimensions"]
1522
+
1523
+ if "L" not in dimensions:
1524
+ dimensions["L"] = dimensions["F"] + (dimensions["C"] - dimensions["F"]) / 3
1525
+
1526
+ if "J" not in dimensions:
1527
+ dimensions["J"] = dimensions["F"] / 2
1528
+
1529
+ if "G" in dimensions:
1530
+ g_angle = math.asin(dimensions["G"] / dimensions["E"])
1531
+ else:
1532
+ g_angle = math.asin((dimensions["E"] - ((dimensions["E"] - dimensions["F"]) / 2)) / dimensions["E"])
1533
+
1534
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["A"] / 2, 0), FreeCAD.Vector(dimensions["C"] / 2, dimensions["A"] / 2, 0)), False)
1535
+
1536
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, dimensions["A"] / 2))
1537
+ sketch.addConstraint(Sketcher.Constraint('Block', top_line))
1538
+
1539
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["A"] / 2, 0), FreeCAD.Vector(dimensions["C"] / 2, -dimensions["A"] / 2, 0)), False)
1540
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
1541
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -dimensions["A"] / 2))
1542
+ sketch.addConstraint(Sketcher.Constraint('Block', bottom_line))
1543
+
1544
+ long_top_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["E"] / 2 * math.cos(g_angle), dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["L"] / 2, dimensions["J"] / 2, 0)), False)
1545
+ long_top_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["E"] / 2 * math.cos(g_angle), dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["L"] / 2, dimensions["J"] / 2, 0)), False)
1546
+
1547
+ side_top_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["C"] / 2, dimensions["A"] / 2, 0), FreeCAD.Vector(dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1548
+ side_corner_top_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["E"] / 2 * math.cos(g_angle), dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1549
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_right_line, 2, side_corner_top_right_line, 1))
1550
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_corner_top_right_line, 2, long_top_right_line, 1))
1551
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_top_right_line))
1552
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_corner_top_right_line))
1553
+
1554
+ side_top_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["A"] / 2, 0), FreeCAD.Vector(-dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1555
+ side_corner_top_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["E"] / 2 * math.cos(g_angle), dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1556
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_left_line, 2, side_corner_top_left_line, 1))
1557
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_corner_top_left_line, 2, long_top_left_line, 1))
1558
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_top_left_line))
1559
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_corner_top_left_line))
1560
+
1561
+ long_bottom_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["E"] / 2 * math.cos(g_angle), -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["L"] / 2, -dimensions["J"] / 2, 0)), False)
1562
+ long_bottom_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["E"] / 2 * math.cos(g_angle), -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["L"] / 2, -dimensions["J"] / 2, 0)), False)
1563
+
1564
+ side_bottom_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["C"] / 2, -dimensions["A"] / 2, 0), FreeCAD.Vector(dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1565
+ side_corner_bottom_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["E"] / 2 * math.cos(g_angle), -dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1566
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_right_line, 2, side_corner_bottom_right_line, 1))
1567
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_corner_bottom_right_line, 2, long_bottom_right_line, 1))
1568
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_bottom_right_line))
1569
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_corner_bottom_right_line))
1570
+
1571
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', long_bottom_right_line, 2, long_bottom_left_line, 2))
1572
+
1573
+ side_bottom_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["A"] / 2, 0), FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1574
+ side_corner_bottom_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["E"] / 2 * math.cos(g_angle), -dimensions["E"] / 2 * math.sin(g_angle), 0)), False)
1575
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_left_line, 2, side_corner_bottom_left_line, 1))
1576
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_corner_bottom_left_line, 2, long_bottom_left_line, 1))
1577
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_bottom_left_line))
1578
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_corner_bottom_left_line))
1579
+
1580
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_bottom_left_line, 2, side_bottom_right_line, 2))
1581
+
1582
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_right_line, 1, top_line, 2))
1583
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_left_line, 1, top_line, 1))
1584
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_right_line, 1, bottom_line, 2))
1585
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_left_line, 1, bottom_line, 1))
1586
+ fillet_radius = 0.9 * (dimensions["C"] / 2 - dimensions["E"] / 2 * math.cos(g_angle))
1587
+ sketch.fillet(side_corner_top_right_line, side_top_right_line, FreeCAD.Vector(dimensions["C"] / 2 - fillet_radius, dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle) + fillet_radius, 0), fillet_radius, True, False)
1588
+ sketch.fillet(side_corner_top_left_line, side_top_left_line, FreeCAD.Vector(-dimensions["C"] / 2 + fillet_radius, dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["C"] / 2, dimensions["E"] / 2 * math.sin(g_angle) + fillet_radius, 0), fillet_radius, True, False)
1589
+
1590
+ sketch.fillet(side_corner_bottom_right_line, side_bottom_right_line, FreeCAD.Vector(dimensions["C"] / 2 - fillet_radius, -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle) - fillet_radius, 0), fillet_radius, True, False)
1591
+ sketch.fillet(side_corner_bottom_left_line, side_bottom_left_line, FreeCAD.Vector(-dimensions["C"] / 2 + fillet_radius, -dimensions["E"] / 2 * math.sin(g_angle), 0), FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2 * math.sin(g_angle) - fillet_radius, 0), fillet_radius, True, False)
1592
+ sketch.addConstraint(Sketcher.Constraint('Block', long_top_right_line))
1593
+ sketch.addConstraint(Sketcher.Constraint('Block', long_top_left_line))
1594
+ sketch.addConstraint(Sketcher.Constraint('Block', long_bottom_right_line))
1595
+ sketch.addConstraint(Sketcher.Constraint('Block', long_bottom_left_line))
1596
+
1597
+ central_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["F"] / 2), False)
1598
+ sketch.addConstraint(Sketcher.Constraint('Block', central_circle))
1599
+ short_top_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["L"] / 2, dimensions["J"] / 2, 0), FreeCAD.Vector(dimensions["L"] / 4, dimensions["J"] / 2, 0)), False)
1600
+ short_bottom_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(dimensions["L"] / 2, -dimensions["J"] / 2, 0), FreeCAD.Vector(dimensions["L"] / 4, -dimensions["J"] / 2, 0)), False)
1601
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', short_top_right_line, 2, central_circle))
1602
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', short_bottom_right_line, 2, central_circle))
1603
+ sketch.addConstraint(Sketcher.Constraint('Coincident', short_top_right_line, 1, long_top_right_line, 2))
1604
+ sketch.addConstraint(Sketcher.Constraint('Coincident', short_bottom_right_line, 1, long_bottom_right_line, 2))
1605
+ sketch.addConstraint(Sketcher.Constraint('Perpendicular', central_circle, short_top_right_line))
1606
+ sketch.addConstraint(Sketcher.Constraint('Perpendicular', central_circle, short_bottom_right_line))
1607
+
1608
+ short_top_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["L"] / 2, dimensions["J"] / 2, 0), FreeCAD.Vector(-dimensions["L"] / 4, dimensions["J"] / 2, 0)), False)
1609
+ short_bottom_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-dimensions["L"] / 2, -dimensions["J"] / 2, 0), FreeCAD.Vector(-dimensions["L"] / 4, -dimensions["J"] / 2, 0)), False)
1610
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', short_top_left_line, 2, central_circle))
1611
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', short_bottom_left_line, 2, central_circle))
1612
+ sketch.addConstraint(Sketcher.Constraint('Coincident', short_top_left_line, 1, long_top_left_line, 2))
1613
+ sketch.addConstraint(Sketcher.Constraint('Coincident', short_bottom_left_line, 1, long_bottom_left_line, 2))
1614
+ sketch.addConstraint(Sketcher.Constraint('Perpendicular', central_circle, short_top_left_line))
1615
+ sketch.addConstraint(Sketcher.Constraint('Perpendicular', central_circle, short_bottom_left_line))
1616
+
1617
+ sketch.addConstraint(Sketcher.Constraint('Distance', short_bottom_left_line, 2, short_top_right_line, 2, dimensions["F"]))
1618
+
1619
+ sketch.trim(central_circle, FreeCAD.Vector(0, dimensions["F"] / 2, 0))
1620
+ sketch.trim(central_circle, FreeCAD.Vector(0, -dimensions["F"] / 2, 0))
1621
+
1622
+ # internal_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["E"] / 2), False)
1623
+ # sketch.addConstraint(Sketcher.Constraint('Diameter', internal_circle, dimensions["E"]))
1624
+ # sketch.addConstraint(Sketcher.Constraint('Coincident', internal_circle, 1, -1, 1))
1625
+ # sketch.addConstraint(Sketcher.Constraint('PointOnObject', long_bottom_left_line, 1, internal_circle))
1626
+ # sketch.addConstraint(Sketcher.Constraint('PointOnObject', long_bottom_right_line, 1, internal_circle))
1627
+ # sketch.addConstraint(Sketcher.Constraint('PointOnObject', long_top_left_line, 1, internal_circle))
1628
+ # sketch.addConstraint(Sketcher.Constraint('PointOnObject', long_top_right_line, 1, internal_circle))
1629
+
1630
+ for index, constraint in enumerate(sketch.Constraints):
1631
+ if constraint.Type == "Equal":
1632
+ sketch.delConstraint(index)
1633
+
1634
+ def get_shape_extras(self, data, piece):
1635
+ return piece
1636
+
1637
+
1638
+ class Rm(P):
1639
+ def get_dimensions_and_subtypes(self):
1640
+ return {
1641
+ 1: ["A", "B", "C", "D", "E", "F", "G", "H", "J"],
1642
+ 2: ["A", "B", "C", "D", "E", "F", "G", "H", "J"],
1643
+ 3: ["A", "B", "C", "D", "E", "F", "G", "H", "J"],
1644
+ 4: ["A", "B", "C", "D", "E", "F", "G", "H", "J"]
1645
+ }
1646
+
1647
+ def get_shape_base(self, data, sketch):
1648
+ dimensions = data["dimensions"]
1649
+ familySubtype = data["familySubtype"]
1650
+
1651
+ p = math.sqrt(2) * dimensions["J"] - dimensions["A"]
1652
+ alpha = math.asin(dimensions["G"] / dimensions["E"])
1653
+ z = dimensions["E"] / 2 * math.cos(alpha)
1654
+ c = dimensions["C"] / 2
1655
+ g = dimensions["G"] / 2
1656
+ a = dimensions["A"] / 2
1657
+ e = dimensions["E"] / 2
1658
+ f = dimensions["F"] / 2
1659
+
1660
+ if familySubtype == '1':
1661
+ t = 0
1662
+ n = (z - c) / g
1663
+ r = (a + p / 2 - c + n * t) / (n + 1)
1664
+ s = n * r + c
1665
+ elif familySubtype == '2':
1666
+ t = f * math.sin(math.acos(c / f))
1667
+ n = (z - c) / g
1668
+ r = (a + p / 2 - c + n * t) / (n + 1)
1669
+ s = n * r + c
1670
+ elif familySubtype == '3':
1671
+ t = c - e * math.cos(math.asin(g / e)) + g
1672
+ n = (z - c) / g
1673
+ r = (a + p / 2 - c + n * t) / (n + 1)
1674
+ s = n * r + c
1675
+ elif familySubtype == '4':
1676
+ t = 0
1677
+ n = 1
1678
+ r = (a + p / 2 - c + n * t) / (n + 1)
1679
+ s = n * r + c
1680
+
1681
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-p / 2, dimensions["A"] / 2, 0), FreeCAD.Vector(p / 2, dimensions["A"] / 2, 0)), False)
1682
+ top_right_line_45_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(p / 2, a, 0), FreeCAD.Vector(s, r, 0)), False)
1683
+ bottom_right_line_45_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(p / 2, -a, 0), FreeCAD.Vector(s, -r, 0)), False)
1684
+ top_left_line_45_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-p / 2, a, 0), FreeCAD.Vector(-s, r, 0)), False)
1685
+ bottom_left_line_45_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-p / 2, -a, 0), FreeCAD.Vector(-s, -r, 0)), False)
1686
+
1687
+ top_right_line_x_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(s, r, 0), FreeCAD.Vector(c, t, 0)), False)
1688
+ bottom_right_line_x_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(s, -r, 0), FreeCAD.Vector(c, -t, 0)), False)
1689
+ top_left_line_x_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-s, r, 0), FreeCAD.Vector(-c, t, 0)), False)
1690
+ bottom_left_line_x_degrees = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-s, -r, 0), FreeCAD.Vector(-c, -t, 0)), False)
1691
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_right_line_45_degrees, 2, top_right_line_x_degrees, 1))
1692
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_right_line_45_degrees, 2, bottom_right_line_x_degrees, 1))
1693
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_left_line_45_degrees, 2, top_left_line_x_degrees, 1))
1694
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_left_line_45_degrees, 2, bottom_left_line_x_degrees, 1))
1695
+ if c < f:
1696
+ central_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["F"] / 2), False)
1697
+ sketch.addConstraint(Sketcher.Constraint('Block', central_circle))
1698
+
1699
+ sketch.trim(central_circle, FreeCAD.Vector(0, dimensions["F"] / 2, 0))
1700
+ sketch.trim(central_circle, FreeCAD.Vector(0, -dimensions["F"] / 2, 0))
1701
+
1702
+ if 'H' in dimensions and dimensions['H'] > 0:
1703
+ hole_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["H"] / 2), False)
1704
+ sketch.addConstraint(Sketcher.Constraint('Block', hole_circle))
1705
+
1706
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, dimensions["A"] / 2))
1707
+ sketch.addConstraint(Sketcher.Constraint('Block', top_line))
1708
+
1709
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-p / 2, -dimensions["A"] / 2, 0), FreeCAD.Vector(p / 2, -dimensions["A"] / 2, 0)), False)
1710
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
1711
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -dimensions["A"] / 2))
1712
+ sketch.addConstraint(Sketcher.Constraint('Block', bottom_line))
1713
+
1714
+ if familySubtype == '3':
1715
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, t, 0), FreeCAD.Vector(c, -t, 0)), False)
1716
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, t, 0), FreeCAD.Vector(-c, -t, 0)), False)
1717
+ sketch.addConstraint(Sketcher.Constraint('Equal', right_line, left_line))
1718
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_right_line_x_degrees, 2, right_line, 1))
1719
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_right_line_x_degrees, 2, right_line, 2))
1720
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 2, dimensions["C"] / 2))
1721
+ sketch.addConstraint(Sketcher.Constraint('Block', right_line))
1722
+ if 'H' in dimensions and dimensions['H'] > 0:
1723
+ sketch.addConstraint(Sketcher.Constraint('Symmetric', left_line, 1, right_line, 2, hole_circle, 3))
1724
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_left_line_x_degrees, 2, left_line, 1))
1725
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_left_line_x_degrees, 2, left_line, 2))
1726
+ sketch.addConstraint(Sketcher.Constraint('Block', left_line))
1727
+ if familySubtype == '4':
1728
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_left_line_x_degrees, 2, bottom_left_line_x_degrees, 2))
1729
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_right_line_x_degrees, 2, bottom_right_line_x_degrees, 2))
1730
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', top_right_line_x_degrees, 2, c))
1731
+
1732
+ if familySubtype == '3' or familySubtype == '4':
1733
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_right_line_45_degrees, 1, top_line, 2))
1734
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_left_line_45_degrees, 1, top_line, 1))
1735
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_right_line_45_degrees, 1, bottom_line, 2))
1736
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_left_line_45_degrees, 1, bottom_line, 1))
1737
+ sketch.addConstraint(Sketcher.Constraint('Angle', top_right_line_45_degrees, 2, top_right_line_x_degrees, 1, math.pi / 2))
1738
+ sketch.addConstraint(Sketcher.Constraint('Angle', bottom_right_line_45_degrees, 2, bottom_right_line_x_degrees, 1, -math.pi / 2))
1739
+ sketch.addConstraint(Sketcher.Constraint('Angle', top_left_line_45_degrees, 2, top_left_line_x_degrees, 1, -math.pi / 2))
1740
+ sketch.addConstraint(Sketcher.Constraint('Angle', bottom_left_line_45_degrees, 2, bottom_left_line_x_degrees, 1, math.pi / 2))
1741
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', top_right_line_x_degrees, 2, top_left_line_x_degrees, 2, -2 * c))
1742
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', bottom_right_line_x_degrees, 2, bottom_left_line_x_degrees, 2, -2 * c))
1743
+ sketch.addConstraint(Sketcher.Constraint('Angle', top_right_line_45_degrees, 1, top_line, 2, -3 * math.pi / 4))
1744
+ sketch.addConstraint(Sketcher.Constraint('Angle', top_left_line_45_degrees, 1, top_line, 1, 3 * math.pi / 4))
1745
+ sketch.addConstraint(Sketcher.Constraint('Angle', bottom_right_line_45_degrees, 1, bottom_line, 2, 3 * math.pi / 4))
1746
+ sketch.addConstraint(Sketcher.Constraint('Angle', bottom_left_line_45_degrees, 1, bottom_line, 1, -3 * math.pi / 4))
1747
+ sketch.addConstraint(Sketcher.Constraint('Vertical', top_right_line_x_degrees, 2, bottom_right_line_x_degrees, 2))
1748
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_right_line_x_degrees, 2, top_left_line_x_degrees, 2))
1749
+
1750
+ def get_shape_extras(self, data, piece):
1751
+ # rotation in order to avoid cut in projection
1752
+ m = piece.Base.Placement.Matrix
1753
+ m.rotateZ(math.radians(180))
1754
+ piece.Base.Placement.Matrix = m
1755
+ return piece
1756
+
1757
+
1758
+ class Pm(P):
1759
+ def get_dimensions_and_subtypes(self):
1760
+ return {
1761
+ 1: ["A", "B", "C", "D", "E", "F", "G", "H", "b", "t"],
1762
+ 2: ["A", "B", "C", "D", "E", "F", "G", "H", "b", "t"]
1763
+ }
1764
+
1765
+ def get_shape_base(self, data, sketch):
1766
+ dimensions = data["dimensions"]
1767
+ familySubtype = data["familySubtype"]
1768
+
1769
+ c = dimensions["C"] / 2
1770
+ g = dimensions["G"] / 2
1771
+ a = dimensions["A"] / 2
1772
+ e = dimensions["E"] / 2
1773
+ f = dimensions["F"] / 2
1774
+ b = dimensions["b"] / 2
1775
+ t = dimensions["t"]
1776
+
1777
+ if 'alpha' not in dimensions:
1778
+ if familySubtype == '1':
1779
+ dimensions["alpha"] = 120
1780
+ else:
1781
+ dimensions["alpha"] = 90
1782
+
1783
+ alpha = dimensions["alpha"] / 180 * math.pi
1784
+
1785
+ beta = math.asin(g / e)
1786
+ xc = f
1787
+ z = c - e * math.cos(beta) + e * math.sin(beta)
1788
+
1789
+ internal_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["H"] / 2), False)
1790
+ central_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["F"] / 2), False)
1791
+ external_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["A"] / 2), False)
1792
+ winding_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["E"] / 2), False)
1793
+ sketch.addConstraint(Sketcher.Constraint('Coincident', central_circle, 3, -1, 1))
1794
+ sketch.addConstraint(Sketcher.Constraint('Coincident', external_circle, 3, -1, 1))
1795
+ sketch.addConstraint(Sketcher.Constraint('Coincident', internal_circle, 3, -1, 1))
1796
+ sketch.addConstraint(Sketcher.Constraint('Coincident', winding_circle, 3, -1, 1))
1797
+ sketch.addConstraint(Sketcher.Constraint('Diameter', central_circle, dimensions["F"]))
1798
+ sketch.addConstraint(Sketcher.Constraint('Diameter', external_circle, dimensions["A"]))
1799
+ sketch.addConstraint(Sketcher.Constraint('Diameter', internal_circle, dimensions["H"]))
1800
+ sketch.addConstraint(Sketcher.Constraint('Diameter', winding_circle, dimensions["E"]))
1801
+
1802
+ side_top_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(e * math.cos(beta), e * math.sin(beta), 0), FreeCAD.Vector(xc, 0, 0)), False)
1803
+ side_bottom_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(e * math.cos(beta), -e * math.sin(beta), 0), FreeCAD.Vector(xc, 0, 0)), False)
1804
+ side_top_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-e * math.cos(beta), e * math.sin(beta), 0), FreeCAD.Vector(-xc, 0, 0)), False)
1805
+ side_bottom_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-e * math.cos(beta), -e * math.sin(beta), 0), FreeCAD.Vector(-xc, 0, 0)), False)
1806
+
1807
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_top_right_line, 1, external_circle))
1808
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_bottom_right_line, 1, external_circle))
1809
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_top_left_line, 1, external_circle))
1810
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_bottom_left_line, 1, external_circle))
1811
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_top_right_line, 1, side_bottom_right_line, 1))
1812
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_top_left_line, 1, side_bottom_left_line, 1))
1813
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_top_left_line, 1, side_top_right_line, 1))
1814
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_top_left_line, 2, side_top_right_line, 2))
1815
+ sketch.addConstraint(Sketcher.Constraint('Angle', side_top_right_line, 2, side_bottom_right_line, 2, -alpha))
1816
+ sketch.addConstraint(Sketcher.Constraint('Angle', side_top_left_line, 2, side_bottom_left_line, 2, alpha))
1817
+ if familySubtype == '1':
1818
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', side_top_left_line, 2, -1, 1))
1819
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_top_right_line, 2, central_circle))
1820
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', side_top_left_line, 2, central_circle))
1821
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_right_line, 2, side_bottom_right_line, 2))
1822
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_left_line, 2, side_bottom_left_line, 2))
1823
+
1824
+ sketch.fillet(side_top_right_line, side_bottom_right_line, FreeCAD.Vector(e * math.cos(beta), e * math.sin(beta), 0), FreeCAD.Vector(e * math.cos(beta), -e * math.sin(beta), 0), a - c, True, False)
1825
+ right_fillet = len(sketch.Geometry) - 1
1826
+
1827
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_fillet, 1, right_fillet, 2))
1828
+ sketch.split(right_fillet, FreeCAD.Vector(c, 0, 0))
1829
+ right_fillet_bottom = len(sketch.Geometry) - 1
1830
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_fillet_bottom, 1, -1, 1, -c))
1831
+
1832
+ sketch.fillet(side_top_left_line, side_bottom_left_line, FreeCAD.Vector(-e * math.cos(beta), e * math.sin(beta), 0), FreeCAD.Vector(-e * math.cos(beta), -e * math.sin(beta), 0), a - c, True, False)
1833
+ left_fillet = len(sketch.Geometry) - 1
1834
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_fillet, 1, left_fillet, 2))
1835
+ sketch.split(left_fillet, FreeCAD.Vector(-c, 0, 0))
1836
+ left_fillet_bottom = len(sketch.Geometry) - 1
1837
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_fillet_bottom, 1, -1, 1, c))
1838
+ elif familySubtype == '2':
1839
+ side_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, z, 0), FreeCAD.Vector(c, -z, 0)), False)
1840
+ side_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, z, 0), FreeCAD.Vector(-c, -z, 0)), False)
1841
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', side_right_line, 1, -1, 1, -c))
1842
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', side_left_line, 1, -1, 1, c))
1843
+ # sketch.addConstraint(Sketcher.Constraint('Symmetric', side_right_line, 1, side_right_line, 2, -1, 1))
1844
+
1845
+ # sketch.addConstraint(Sketcher.Constraint('DistanceY', side_right_line, 1, -1, 1, -z))
1846
+ # sketch.addConstraint(Sketcher.Constraint('DistanceY', side_right_line, 2, -1, 1, z))
1847
+
1848
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_right_line, 1, side_right_line, 2))
1849
+ sketch.addConstraint(Sketcher.Constraint('Vertical', side_left_line, 1, side_left_line, 2))
1850
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_right_line, 2, side_right_line, 1))
1851
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_right_line, 2, side_right_line, 2))
1852
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_top_left_line, 2, side_left_line, 1))
1853
+ sketch.addConstraint(Sketcher.Constraint('Coincident', side_bottom_left_line, 2, side_left_line, 2))
1854
+
1855
+ sketch.trim(winding_circle, FreeCAD.Vector(e, 0, 0))
1856
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', winding_circle, 1, -1, 1, -g))
1857
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', winding_circle, 2, -1, 1, g))
1858
+
1859
+ top_dent_left = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-b, a, 0), FreeCAD.Vector(-b, a - t, 0)), False)
1860
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-b, a - t, 0), FreeCAD.Vector(b, a - t, 0)), False)
1861
+ top_dent_right = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(b, a - t, 0), FreeCAD.Vector(b, a, 0)), False)
1862
+ sketch.trim(top_dent_left, FreeCAD.Vector(-b, a, 0))
1863
+ sketch.trim(top_dent_right, FreeCAD.Vector(b, a, 0))
1864
+
1865
+ sketch.trim(external_circle, FreeCAD.Vector(-dimensions["A"] / 2, 0, 0))
1866
+ sketch.trim(external_circle, FreeCAD.Vector(dimensions["A"] / 2, 0, 0))
1867
+
1868
+ external_circle_bottom = external_circle
1869
+ external_circle_top = len(sketch.Geometry) - 1
1870
+ sketch.trim(external_circle_top, FreeCAD.Vector(0, a, 0))
1871
+
1872
+ bottom_dent_left = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-b, -a, 0), FreeCAD.Vector(-b, -a + t, 0)), False)
1873
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-b, -a + t, 0), FreeCAD.Vector(b, -a + t, 0)), False)
1874
+ bottom_dent_right = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(b, -a + t, 0), FreeCAD.Vector(b, -a, 0)), False)
1875
+ sketch.trim(bottom_dent_left, FreeCAD.Vector(-b, -a, 0))
1876
+ sketch.trim(bottom_dent_right, FreeCAD.Vector(b, -a, 0))
1877
+ sketch.trim(external_circle_bottom, FreeCAD.Vector(0, -a, 0))
1878
+ sketch.delGeometries([winding_circle])
1879
+ sketch.delGeometries([central_circle])
1880
+
1881
+ def get_shape_extras(self, data, piece):
1882
+ # rotation in order to avoid cut in projection
1883
+ m = piece.Base.Placement.Matrix
1884
+ m.rotateZ(math.radians(180))
1885
+ piece.Base.Placement.Matrix = m
1886
+ return piece
1887
+
1888
+
1889
+ class E(IPiece):
1890
+ def get_negative_winding_window(self, dimensions):
1891
+ document = FreeCAD.ActiveDocument
1892
+
1893
+ winding_window_cube = document.addObject("Part::Box", "winding_window_cube")
1894
+ winding_window_cube.Length = dimensions["C"]
1895
+ winding_window_cube.Width = dimensions["E"]
1896
+ winding_window_cube.Height = dimensions["D"]
1897
+ winding_window_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1898
+
1899
+ central_column_cube = document.addObject("Part::Box", "central_column_cube")
1900
+ central_column_cube.Length = dimensions["C"]
1901
+ central_column_cube.Width = dimensions["F"]
1902
+ central_column_cube.Height = dimensions["D"]
1903
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1904
+
1905
+ negative_winding_window = document.addObject("Part::Cut", "negative_winding_window")
1906
+ negative_winding_window.Base = winding_window_cube
1907
+ negative_winding_window.Tool = central_column_cube
1908
+ document.recompute()
1909
+
1910
+ return negative_winding_window
1911
+
1912
+ def get_shape_base(self, data, sketch):
1913
+ dimensions = data["dimensions"]
1914
+
1915
+ c = dimensions["C"] / 2
1916
+ a = dimensions["A"] / 2
1917
+
1918
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, a, 0), FreeCAD.Vector(c, a, 0)), False)
1919
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a, 0), FreeCAD.Vector(c, -a, 0)), False)
1920
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -a, 0), FreeCAD.Vector(-c, -a, 0)), False)
1921
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a, 0), FreeCAD.Vector(-c, a, 0)), False)
1922
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_line, 2, right_line, 1))
1923
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
1924
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
1925
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_line, 2, top_line, 1))
1926
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, a))
1927
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, -1, 1, -a))
1928
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_line, 1, -1, 1, c))
1929
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
1930
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_line))
1931
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_line))
1932
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_line))
1933
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
1934
+
1935
+ def get_shape_extras(self, data, piece):
1936
+ return piece
1937
+
1938
+ def apply_machining(self, piece, machining, dimensions):
1939
+ document = FreeCAD.ActiveDocument
1940
+
1941
+ original_tool = document.addObject("Part::Box", "tool")
1942
+ original_tool.Length = dimensions["A"]
1943
+ x_coordinate = -dimensions["A"] / 2
1944
+ if machining['coordinates'][0] == 0:
1945
+ original_tool.Width = dimensions["F"]
1946
+ original_tool.Length = dimensions["C"]
1947
+ y_coordinate = -dimensions["F"] / 2
1948
+ x_coordinate = -dimensions["C"] / 2
1949
+ if 'K' in dimensions:
1950
+ original_tool.Length = dimensions["C"] - dimensions['K']
1951
+ x_coordinate += dimensions['K']
1952
+ else:
1953
+ original_tool.Width = dimensions["A"] / 2
1954
+ if machining['coordinates'][0] < 0:
1955
+ y_coordinate = 0
1956
+ if machining['coordinates'][0] > 0:
1957
+ y_coordinate = -dimensions["A"] / 2
1958
+
1959
+ original_tool.Height = machining['length'] * 1000
1960
+ original_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1961
+
1962
+ if machining['coordinates'][0] == 0:
1963
+ tool = original_tool
1964
+ else:
1965
+ central_column_tool = document.addObject("Part::Box", "central_column_tool")
1966
+ central_column_width = dimensions["F"] * 1.001
1967
+ central_column_length = dimensions["C"] * 1.001
1968
+ if 'K' in dimensions:
1969
+ central_column_length = (dimensions["C"] - dimensions['K'] * 2) * 1.001
1970
+ central_column_tool.Length = central_column_length
1971
+ central_column_tool.Width = central_column_width
1972
+ central_column_tool.Height = machining['length'] * 1000
1973
+ central_column_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(-central_column_length / 2, -central_column_width / 2, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
1974
+
1975
+
1976
+ tool = document.addObject("Part::Cut", "machined_piece")
1977
+ tool.Base = original_tool
1978
+ tool.Tool = central_column_tool
1979
+ document.recompute()
1980
+
1981
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
1982
+ machined_piece.Base = piece
1983
+ machined_piece.Tool = tool
1984
+ document.recompute()
1985
+
1986
+ return machined_piece
1987
+
1988
+
1989
+ class Er(E):
1990
+ def get_dimensions_and_subtypes(self):
1991
+ return {1: ["A", "B", "C", "D", "E", "F", "G"]}
1992
+
1993
+ def get_negative_winding_window(self, dimensions):
1994
+ document = FreeCAD.ActiveDocument
1995
+ winding_window = Shapes.addTube(FreeCAD.ActiveDocument, "winding_window")
1996
+ winding_window.Height = dimensions["D"]
1997
+ winding_window.InnerRadius = dimensions["F"] / 2
1998
+ winding_window.OuterRadius = dimensions["E"] / 2
1999
+ winding_window.Placement = FreeCAD.Placement(FreeCAD.Vector(0, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2000
+ document.recompute()
2001
+
2002
+ if 'G' in dimensions and dimensions["G"] > dimensions["F"]:
2003
+ if dimensions["C"] > dimensions["F"]:
2004
+ lateral_top_cube = document.addObject("Part::Box", "lateral_top_cube")
2005
+ lateral_top_cube.Length = dimensions["C"]
2006
+ lateral_top_cube.Width = dimensions["G"] / 2 - dimensions["F"] / 2
2007
+ lateral_top_cube.Height = dimensions["D"]
2008
+ lateral_top_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2009
+
2010
+ lateral_bottom_cube = document.addObject("Part::Box", "lateral_bottom_cube")
2011
+ lateral_bottom_cube.Length = dimensions["C"]
2012
+ lateral_bottom_cube.Width = dimensions["G"] / 2 - dimensions["F"] / 2
2013
+ lateral_bottom_cube.Height = dimensions["D"]
2014
+ lateral_bottom_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2015
+
2016
+ lateral_right_cube = document.addObject("Part::Box", "lateral_right_cube")
2017
+ lateral_right_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2018
+ lateral_right_cube.Width = dimensions["G"]
2019
+ lateral_right_cube.Height = dimensions["D"]
2020
+ lateral_right_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["F"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2021
+
2022
+ lateral_left_cube = document.addObject("Part::Box", "lateral_left_cube")
2023
+ lateral_left_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2024
+ lateral_left_cube.Width = dimensions["G"]
2025
+ lateral_left_cube.Height = dimensions["D"]
2026
+ lateral_left_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2027
+ winding_window_aux = document.addObject("Part::MultiFuse", "Fusion")
2028
+ winding_window_aux.Shapes = [winding_window, lateral_top_cube, lateral_bottom_cube, lateral_right_cube, lateral_left_cube]
2029
+ else:
2030
+ lateral_top_cube = document.addObject("Part::Box", "lateral_top_cube")
2031
+ lateral_top_cube.Length = dimensions["C"]
2032
+ lateral_top_cube.Width = dimensions["G"] / 2 - dimensions["F"] / 2
2033
+ lateral_top_cube.Height = dimensions["D"]
2034
+ lateral_top_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2035
+
2036
+ lateral_bottom_cube = document.addObject("Part::Box", "lateral_bottom_cube")
2037
+ lateral_bottom_cube.Length = dimensions["C"]
2038
+ lateral_bottom_cube.Width = dimensions["G"] / 2 - dimensions["F"] / 2
2039
+ lateral_bottom_cube.Height = dimensions["D"]
2040
+ lateral_bottom_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2041
+ winding_window_aux = document.addObject("Part::MultiFuse", "Fusion")
2042
+ winding_window_aux.Shapes = [winding_window, lateral_top_cube, lateral_bottom_cube]
2043
+
2044
+ document.recompute()
2045
+ winding_window = winding_window_aux
2046
+
2047
+ return winding_window
2048
+
2049
+ def get_shape_extras(self, data, piece):
2050
+ return piece
2051
+
2052
+
2053
+ class El(E):
2054
+ def get_dimensions_and_subtypes(self):
2055
+ return {1: ["A", "B", "C", "D", "E", "F", "F2"]}
2056
+
2057
+ def get_negative_winding_window(self, dimensions):
2058
+ document = FreeCAD.ActiveDocument
2059
+
2060
+ winding_window_cube = document.addObject("Part::Box", "winding_window_cube")
2061
+ winding_window_cube.Length = dimensions["C"]
2062
+ winding_window_cube.Width = dimensions["E"]
2063
+ winding_window_cube.Height = dimensions["D"]
2064
+ winding_window_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2065
+
2066
+ central_column_cube = document.addObject("Part::Box", "central_column_cube")
2067
+ central_column_cube.Length = dimensions["F2"] - dimensions["F"]
2068
+ central_column_cube.Width = dimensions["F"]
2069
+ central_column_cube.Height = dimensions["D"]
2070
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-(dimensions["F2"] - dimensions["F"]) / 2, -dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2071
+
2072
+ cylinder_left = document.addObject("Part::Cylinder", "cylinder_left")
2073
+ cylinder_left.Height = dimensions["D"]
2074
+ cylinder_left.Radius = dimensions["F"] / 2
2075
+ cylinder_left.Angle = 180
2076
+ cylinder_left.Placement = FreeCAD.Placement(FreeCAD.Vector(-(dimensions["F2"] - dimensions["F"]) / 2, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2077
+ document.recompute()
2078
+
2079
+ cylinder_right = document.addObject("Part::Cylinder", "cylinder_right")
2080
+ cylinder_right.Height = dimensions["D"]
2081
+ cylinder_right.Radius = dimensions["F"] / 2
2082
+ cylinder_right.Angle = 180
2083
+ cylinder_right.Placement = FreeCAD.Placement(FreeCAD.Vector((dimensions["F2"] - dimensions["F"]) / 2, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(-90, 0, 0))
2084
+ document.recompute()
2085
+
2086
+ central_column = document.addObject("Part::MultiFuse", "central_column")
2087
+ central_column.Shapes = [cylinder_left, central_column_cube, cylinder_right]
2088
+
2089
+ document.recompute()
2090
+
2091
+ negative_winding_window = document.addObject("Part::Cut", "negative_winding_window")
2092
+ negative_winding_window.Base = winding_window_cube
2093
+ negative_winding_window.Tool = central_column
2094
+ document.recompute()
2095
+
2096
+ return negative_winding_window
2097
+
2098
+ def get_shape_extras(self, data, piece):
2099
+ return piece
2100
+
2101
+
2102
+ class Etd(Er):
2103
+ def get_dimensions_and_subtypes(self):
2104
+ return {1: ["A", "B", "C", "D", "E", "F"]}
2105
+
2106
+
2107
+ class Lp(Er):
2108
+ def get_dimensions_and_subtypes(self):
2109
+ return {
2110
+ 1: ["A", "B", "C", "D", "E", "F", "G"],
2111
+ }
2112
+
2113
+ def get_shape_extras(self, data, piece):
2114
+ document = FreeCAD.ActiveDocument
2115
+ dimensions = data["dimensions"]
2116
+
2117
+ refined_piece = document.addObject('Part::Refine', 'RefineAux')
2118
+ refined_piece.Source = piece
2119
+
2120
+ document.recompute()
2121
+
2122
+ right_side_vertex = self.edges_in_boundbox(part=refined_piece,
2123
+ xmin=dimensions["F"] / 2 + (dimensions["C"] - dimensions["F"]) / 4,
2124
+ xmax=dimensions["C"],
2125
+ ymin=-(dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4),
2126
+ ymax=dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4,
2127
+ zmin=(dimensions["B"] - dimensions["D"]) / 2,
2128
+ zmax=dimensions["B"] - dimensions["D"])
2129
+
2130
+ vertexes = right_side_vertex
2131
+ fillet = document.addObject("Part::Fillet", "Fillet")
2132
+ fillet.Base = refined_piece
2133
+ fillet_radius = (dimensions["B"] - dimensions["D"]) / 2
2134
+ __fillets__ = []
2135
+ for i in vertexes:
2136
+ __fillets__.append((i + 1, fillet_radius, fillet_radius))
2137
+ fillet.Edges = __fillets__
2138
+ document.recompute()
2139
+ return fillet
2140
+
2141
+ def get_negative_winding_window(self, dimensions):
2142
+ document = FreeCAD.ActiveDocument
2143
+ winding_window = Shapes.addTube(FreeCAD.ActiveDocument, "winding_window")
2144
+ winding_window.Height = dimensions["D"]
2145
+ winding_window.InnerRadius = dimensions["F"] / 2
2146
+ winding_window.OuterRadius = dimensions["E"] / 2
2147
+ winding_window.Placement = FreeCAD.Placement(FreeCAD.Vector(0, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2148
+ document.recompute()
2149
+
2150
+ lateral_top_cube = document.addObject("Part::Box", "lateral_top_cube")
2151
+ lateral_top_cube.Length = dimensions["C"] / 2
2152
+ lateral_top_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2153
+ lateral_top_cube.Height = dimensions["D"]
2154
+ lateral_top_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(0, dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2155
+
2156
+ lateral_bottom_cube = document.addObject("Part::Box", "lateral_bottom_cube")
2157
+ lateral_bottom_cube.Length = dimensions["C"] / 2
2158
+ lateral_bottom_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2159
+ lateral_bottom_cube.Height = dimensions["D"]
2160
+ lateral_bottom_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(0, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2161
+
2162
+ lateral_right_cube = document.addObject("Part::Box", "lateral_right_cube")
2163
+ lateral_right_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2164
+ lateral_right_cube.Width = dimensions["E"]
2165
+ lateral_right_cube.Height = dimensions["D"]
2166
+ lateral_right_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["F"] / 2, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2167
+
2168
+ lateral_left_cube = document.addObject("Part::Box", "lateral_left_cube")
2169
+ lateral_left_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2170
+ lateral_left_cube.Width = dimensions["G"]
2171
+ lateral_left_cube.Height = dimensions["D"]
2172
+ lateral_left_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2173
+
2174
+ winding_window_aux = document.addObject("Part::MultiFuse", "Fusion")
2175
+ winding_window_aux.Shapes = [winding_window, lateral_top_cube, lateral_bottom_cube, lateral_right_cube, lateral_left_cube]
2176
+ document.recompute()
2177
+ winding_window = winding_window_aux
2178
+
2179
+ return winding_window
2180
+
2181
+
2182
+ class Eq(Er):
2183
+ def get_dimensions_and_subtypes(self):
2184
+ return {1: ["A", "B", "C", "D", "E", "F", "G"]}
2185
+
2186
+ def get_shape_extras(self, data, piece):
2187
+ document = FreeCAD.ActiveDocument
2188
+ dimensions = data["dimensions"]
2189
+
2190
+ refined_piece = document.addObject('Part::Refine', 'RefineAux')
2191
+ refined_piece.Source = piece
2192
+
2193
+ document.recompute()
2194
+
2195
+ right_side_vertex = self.edges_in_boundbox(part=refined_piece,
2196
+ xmin=dimensions["C"] / 2 - (dimensions["C"] / 2 - dimensions["E"] / 2 * math.cos(math.asin(dimensions["G"] / dimensions["E"]))) / 2,
2197
+ xmax=dimensions["C"] / 2,
2198
+ ymin=-(dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4),
2199
+ ymax=dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4,
2200
+ zmin=(dimensions["B"] - dimensions["D"]) / 2,
2201
+ zmax=dimensions["B"] - dimensions["D"])
2202
+ left_side_vertex = self.edges_in_boundbox(part=refined_piece,
2203
+ xmin=-dimensions["C"] / 2,
2204
+ xmax=-dimensions["C"] / 2 + (dimensions["C"] / 2 - dimensions["E"] / 2 * math.cos(math.asin(dimensions["G"] / dimensions["E"]))) / 2,
2205
+ ymin=-(dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4),
2206
+ ymax=dimensions["E"] / 2 + (dimensions["A"] - dimensions["E"]) / 4,
2207
+ zmin=(dimensions["B"] - dimensions["D"]) / 2,
2208
+ zmax=dimensions["B"] - dimensions["D"])
2209
+
2210
+ vertexes = right_side_vertex
2211
+ vertexes.extend(left_side_vertex)
2212
+ fillet = document.addObject("Part::Fillet", "Fillet")
2213
+ fillet.Base = refined_piece
2214
+ fillet_radius = min(dimensions["C"] / 2 - dimensions["E"] / 2 * math.cos(math.asin(dimensions["G"] / dimensions["E"])), (dimensions["B"] - dimensions["D"]) / 2)
2215
+ __fillets__ = []
2216
+ for i in vertexes:
2217
+ __fillets__.append((i + 1, fillet_radius, fillet_radius))
2218
+ fillet.Edges = __fillets__
2219
+ document.recompute()
2220
+ return fillet
2221
+
2222
+
2223
+ class Ec(Er):
2224
+ def get_dimensions_and_subtypes(self):
2225
+ return {1: ["A", "B", "C", "D", "E", "F", "T", "s"]}
2226
+
2227
+ def get_shape_base(self, data, sketch):
2228
+ dimensions = data["dimensions"]
2229
+
2230
+ c = dimensions["C"] / 2
2231
+ a = dimensions["A"] / 2
2232
+ t = dimensions["T"] / 2
2233
+ s = dimensions["s"] / 2
2234
+
2235
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, a, 0), FreeCAD.Vector(c, a, 0)), False)
2236
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a, 0), FreeCAD.Vector(c, -a, 0)), False)
2237
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -a, 0), FreeCAD.Vector(-c, -a, 0)), False)
2238
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a, 0), FreeCAD.Vector(-c, a, 0)), False)
2239
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_line, 2, right_line, 1))
2240
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
2241
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
2242
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_line, 2, top_line, 1))
2243
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, a))
2244
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_line, 1, -1, 1, c))
2245
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
2246
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_line))
2247
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_line))
2248
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_line))
2249
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
2250
+
2251
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-s, a, 0), FreeCAD.Vector(-s, t + s, 0)), False)
2252
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(s, a, 0), FreeCAD.Vector(s, t + s, 0)), False)
2253
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-s, -a, 0), FreeCAD.Vector(-s, -t - s, 0)), False)
2254
+ sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(s, -a, 0), FreeCAD.Vector(s, -t - s, 0)), False)
2255
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(0, t + s, 0), FreeCAD.Vector(0, 0, 1), s), math.pi, 0))
2256
+ sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(0, -t - s, 0), FreeCAD.Vector(0, 0, 1), s), 0, math.pi))
2257
+
2258
+ sketch.trim(top_line, FreeCAD.Vector(0, a, 0))
2259
+ sketch.trim(bottom_line, FreeCAD.Vector(0, -a, 0))
2260
+
2261
+
2262
+ class Ep(E):
2263
+ def get_dimensions_and_subtypes(self):
2264
+ return {1: ["A", "B", "C", "D", "E", "F", "G", "K"]}
2265
+
2266
+ def get_negative_winding_window(self, dimensions):
2267
+ document = FreeCAD.ActiveDocument
2268
+ winding_window = Shapes.addTube(FreeCAD.ActiveDocument, "winding_window")
2269
+ winding_window.Height = dimensions["D"]
2270
+ winding_window.InnerRadius = dimensions["F"] / 2
2271
+ winding_window.OuterRadius = dimensions["E"] / 2
2272
+ winding_window.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2273
+ document.recompute()
2274
+
2275
+ lateral_top_cube = document.addObject("Part::Box", "lateral_top_cube")
2276
+ lateral_top_cube.Length = dimensions["C"] / 2
2277
+ lateral_top_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2278
+ lateral_top_cube.Height = dimensions["D"]
2279
+ lateral_top_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2280
+
2281
+ lateral_bottom_cube = document.addObject("Part::Box", "lateral_bottom_cube")
2282
+ lateral_bottom_cube.Length = dimensions["C"] / 2
2283
+ lateral_bottom_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2284
+ lateral_bottom_cube.Height = dimensions["D"]
2285
+ lateral_bottom_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2286
+
2287
+ lateral_right_cube = document.addObject("Part::Box", "lateral_right_cube")
2288
+ lateral_right_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2289
+ lateral_right_cube.Width = dimensions["E"]
2290
+ lateral_right_cube.Height = dimensions["D"]
2291
+ lateral_right_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] - dimensions["F"] / 2, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2292
+
2293
+ shapes = [winding_window, lateral_top_cube, lateral_bottom_cube, lateral_right_cube]
2294
+ if "G" in dimensions and dimensions['G'] > 0:
2295
+ lateral_left_cube = document.addObject("Part::Box", "lateral_left_cube")
2296
+ lateral_left_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2297
+ lateral_left_cube.Width = dimensions["G"]
2298
+ lateral_left_cube.Height = dimensions["D"]
2299
+ lateral_left_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2300
+ shapes.append(lateral_left_cube)
2301
+
2302
+ winding_window_aux = document.addObject("Part::MultiFuse", "Fusion")
2303
+ winding_window_aux.Shapes = shapes
2304
+
2305
+ document.recompute()
2306
+ winding_window = winding_window_aux
2307
+
2308
+ return winding_window
2309
+
2310
+ def apply_machining(self, piece, machining, dimensions):
2311
+ document = FreeCAD.ActiveDocument
2312
+
2313
+ original_tool = document.addObject("Part::Box", "tool")
2314
+ original_tool.Length = dimensions["C"]
2315
+ x_coordinate = -dimensions["C"] + dimensions["K"]
2316
+
2317
+ if machining['coordinates'][0] == 0 and machining['coordinates'][2] == 0:
2318
+ original_tool.Width = dimensions["F"]
2319
+ original_tool.Length = dimensions["F"]
2320
+ x_coordinate = -dimensions["F"] / 2
2321
+ y_coordinate = -dimensions["F"] / 2
2322
+ elif machining['coordinates'][0] != 0 and machining['coordinates'][2] == 0:
2323
+ original_tool.Width = dimensions["A"] / 2
2324
+ if machining['coordinates'][0] < 0:
2325
+ y_coordinate = 0
2326
+ if machining['coordinates'][0] > 0:
2327
+ y_coordinate = -dimensions["A"] / 2
2328
+ else:
2329
+ original_tool.Width = dimensions["A"]
2330
+ y_coordinate = -dimensions["A"] / 2
2331
+
2332
+ original_tool.Height = machining['length'] * 1000
2333
+ original_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2334
+
2335
+ if machining['coordinates'][0] == 0 and machining['coordinates'][2] == 0:
2336
+ tool = original_tool
2337
+ else:
2338
+ central_column_tool = document.addObject("Part::Cylinder", "central_column_tool")
2339
+ central_column_width = dimensions["F"] * 1.001
2340
+ central_column_tool.Radius = central_column_width / 2
2341
+ central_column_tool.Height = machining['length'] * 1000
2342
+ central_column_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(0, 0, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2343
+
2344
+ tool = document.addObject("Part::Cut", "machined_piece_with_central_column")
2345
+ tool.Base = original_tool
2346
+ tool.Tool = central_column_tool
2347
+ document.recompute()
2348
+
2349
+ machined_piece = document.addObject("Part::Cut", "machined_piece_with_lateral_gap")
2350
+ machined_piece.Base = piece
2351
+ machined_piece.Tool = tool
2352
+ document.recompute()
2353
+
2354
+ return machined_piece
2355
+
2356
+ def get_shape_extras(self, data, piece):
2357
+ # movement to center column
2358
+ dimensions = data["dimensions"]
2359
+
2360
+ piece.Placement.move(FreeCAD.Vector(-dimensions["C"] / 2 + dimensions["K"],
2361
+ 0,
2362
+ 0))
2363
+ return piece
2364
+
2365
+
2366
+ class Epx(E):
2367
+ def get_dimensions_and_subtypes(self):
2368
+ return {1: ["A", "B", "C", "D", "E", "F", "G", "K"]}
2369
+
2370
+ def get_negative_winding_window(self, dimensions):
2371
+ document = FreeCAD.ActiveDocument
2372
+
2373
+ if dimensions["K"] >= dimensions["F"] / 2:
2374
+ cylinder_left = document.addObject("Part::Cylinder", "cylinder_left")
2375
+ cylinder_left.Height = dimensions["D"]
2376
+ cylinder_left.Radius = dimensions["F"] / 2
2377
+ cylinder_left.Angle = 180
2378
+ cylinder_left.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2379
+ document.recompute()
2380
+
2381
+ if dimensions["K"] != dimensions["F"] / 2:
2382
+ central_column_cube = document.addObject("Part::Box", "central_column_cube")
2383
+ central_column_cube.Length = dimensions["K"] - dimensions["F"] / 2
2384
+ central_column_cube.Width = dimensions["F"]
2385
+ central_column_cube.Height = dimensions["D"]
2386
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], -dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2387
+
2388
+ cylinder_right = document.addObject("Part::Cylinder", "cylinder_right")
2389
+ cylinder_right.Height = dimensions["D"]
2390
+ cylinder_right.Radius = dimensions["F"] / 2
2391
+ cylinder_right.Angle = 180
2392
+ cylinder_right.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["F"] / 2, 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(-90, 0, 0))
2393
+ document.recompute()
2394
+ else:
2395
+ cylinder_left = document.addObject("Part::Cylinder", "cylinder_left")
2396
+ cylinder_left.Height = dimensions["D"]
2397
+ cylinder_left.Radius = dimensions["K"]
2398
+ cylinder_left.Angle = 180
2399
+ cylinder_left.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], -(dimensions["F"] / 2 - dimensions["K"]), dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(180, 0, 0))
2400
+ document.recompute()
2401
+
2402
+ central_column_cube = document.addObject("Part::Box", "central_column_cube")
2403
+ central_column_cube.Length = dimensions["K"] * 2
2404
+ central_column_cube.Width = dimensions["F"] - dimensions["K"] * 2
2405
+ central_column_cube.Height = dimensions["D"]
2406
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"] * 2, -(dimensions["F"] / 2 - dimensions["K"]), dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2407
+ document.recompute()
2408
+
2409
+ cylinder_right = document.addObject("Part::Cylinder", "cylinder_right")
2410
+ cylinder_right.Height = dimensions["D"]
2411
+ cylinder_right.Radius = dimensions["K"]
2412
+ cylinder_right.Angle = 180
2413
+ cylinder_right.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], (dimensions["F"] / 2 - dimensions["K"]), dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(0, 0, 0))
2414
+ document.recompute()
2415
+
2416
+ central_column = document.addObject("Part::MultiFuse", "central_column")
2417
+ if dimensions["K"] != dimensions["F"] / 2:
2418
+ central_column.Shapes = [cylinder_left, central_column_cube, cylinder_right]
2419
+ else:
2420
+ central_column.Shapes = [cylinder_left, cylinder_right]
2421
+
2422
+ document.recompute()
2423
+
2424
+ winding_window_cylinder_left = document.addObject("Part::Cylinder", "winding_window_cylinder_left")
2425
+ winding_window_cylinder_left.Height = dimensions["D"]
2426
+ winding_window_cylinder_left.Radius = dimensions["E"] / 2
2427
+ winding_window_cylinder_left.Angle = 180
2428
+ winding_window_cylinder_left.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], 0, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2429
+
2430
+ lateral_top_cube = document.addObject("Part::Box", "lateral_top_cube")
2431
+ lateral_top_cube.Length = dimensions["C"] / 2
2432
+ lateral_top_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2433
+ lateral_top_cube.Height = dimensions["D"]
2434
+ lateral_top_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], dimensions["F"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2435
+
2436
+ lateral_bottom_cube = document.addObject("Part::Box", "lateral_bottom_cube")
2437
+ lateral_bottom_cube.Length = dimensions["C"] / 2
2438
+ lateral_bottom_cube.Width = dimensions["E"] / 2 - dimensions["F"] / 2
2439
+ lateral_bottom_cube.Height = dimensions["D"]
2440
+ lateral_bottom_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2441
+
2442
+ lateral_right_cube = document.addObject("Part::Box", "lateral_right_cube")
2443
+ if dimensions["K"] >= dimensions["F"] / 2:
2444
+ lateral_right_cube.Length = dimensions["C"] / 2
2445
+ else:
2446
+ lateral_right_cube.Length = dimensions["K"]
2447
+ lateral_right_cube.Width = dimensions["E"]
2448
+ lateral_right_cube.Height = dimensions["D"]
2449
+ lateral_right_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(dimensions["C"] / 2 - dimensions["K"], -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2450
+
2451
+ shapes = [winding_window_cylinder_left, lateral_top_cube, lateral_bottom_cube, lateral_right_cube]
2452
+ if "G" in dimensions and dimensions["G"] > 0:
2453
+ lateral_left_cube = document.addObject("Part::Box", "lateral_left_cube")
2454
+ lateral_left_cube.Length = dimensions["C"] / 2 - dimensions["F"] / 2
2455
+ lateral_left_cube.Width = dimensions["G"]
2456
+ lateral_left_cube.Height = dimensions["D"]
2457
+ lateral_left_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["G"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2458
+ shapes.append(lateral_left_cube)
2459
+
2460
+ winding_window_aux = document.addObject("Part::MultiFuse", "Fusion")
2461
+ winding_window_aux.Shapes = shapes
2462
+
2463
+ document.recompute()
2464
+
2465
+ winding_window = document.addObject("Part::Cut", "winding_window")
2466
+ winding_window.Base = winding_window_aux
2467
+ winding_window.Tool = central_column
2468
+
2469
+ document.recompute()
2470
+
2471
+ return winding_window
2472
+
2473
+ def apply_machining(self, piece, machining, dimensions):
2474
+ document = FreeCAD.ActiveDocument
2475
+
2476
+ original_tool = document.addObject("Part::Box", "tool")
2477
+ original_tool.Length = dimensions["A"]
2478
+ x_coordinate = -dimensions["A"] / 2
2479
+ if machining['coordinates'][0] == 0 and machining['coordinates'][2] == 0:
2480
+ original_tool.Width = dimensions["F"]
2481
+ original_tool.Length = dimensions["F"] / 2 + dimensions["K"]
2482
+ x_coordinate = (dimensions["C"] / 2 - (dimensions["F"] / 2 + dimensions["K"]))
2483
+ y_coordinate = -dimensions["F"] / 2
2484
+ elif machining['coordinates'][0] != 0 and machining['coordinates'][2] == 0:
2485
+ original_tool.Width = dimensions["A"] / 2
2486
+ if machining['coordinates'][0] < 0:
2487
+ y_coordinate = 0
2488
+ if machining['coordinates'][0] > 0:
2489
+ y_coordinate = -dimensions["A"] / 2
2490
+ else:
2491
+ original_tool.Width = dimensions["A"]
2492
+ y_coordinate = -dimensions["A"] / 2
2493
+
2494
+ original_tool.Height = machining['length'] * 1000
2495
+ original_tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2496
+
2497
+ if machining['coordinates'][0] == 0 and machining['coordinates'][2] == 0:
2498
+ tool = original_tool
2499
+ else:
2500
+ central_column_tool = document.addObject("Part::Box", "central_column_tool")
2501
+ central_column_length = (dimensions["F"] / 2 + dimensions["K"]) * 1.01
2502
+ central_column_width = dimensions["F"] * 1.01
2503
+ central_column_tool.Length = central_column_length
2504
+ central_column_tool.Width = central_column_width
2505
+ central_column_tool.Height = machining['length'] * 1000
2506
+ central_column_tool.Placement = FreeCAD.Placement(FreeCAD.Vector((dimensions["C"] / 2 * 1.01 - central_column_length), -central_column_width / 2, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2507
+
2508
+ tool = document.addObject("Part::Cut", "machined_piece")
2509
+ tool.Base = original_tool
2510
+ tool.Tool = central_column_tool
2511
+ document.recompute()
2512
+
2513
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
2514
+ machined_piece.Base = piece
2515
+ machined_piece.Tool = tool
2516
+ document.recompute()
2517
+
2518
+ return machined_piece
2519
+
2520
+
2521
+ class Efd(E):
2522
+ def get_dimensions_and_subtypes(self):
2523
+ return {
2524
+ 1: ["A", "B", "C", "D", "E", "F", "F2", "K", "q"],
2525
+ 2: ["A", "B", "C", "D", "E", "F", "F2", "K", "q"]
2526
+ }
2527
+
2528
+ def get_shape_base(self, data, sketch):
2529
+ dimensions = data["dimensions"]
2530
+
2531
+ c = dimensions["C"] / 2
2532
+ a = dimensions["A"] / 2
2533
+ e = dimensions["E"] / 2
2534
+ f1 = dimensions["F"] / 2
2535
+ f2 = dimensions["F2"]
2536
+ k = dimensions["K"]
2537
+ q = dimensions["q"]
2538
+
2539
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, a, 0), FreeCAD.Vector(c, a, 0)), False)
2540
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a, 0), FreeCAD.Vector(c, -a, 0)), False)
2541
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -a, 0), FreeCAD.Vector(-c, -a, 0)), False)
2542
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a, 0), FreeCAD.Vector(-c, a, 0)), False)
2543
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_line, 2, right_line, 1))
2544
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
2545
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
2546
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_line, 2, top_line, 1))
2547
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, a))
2548
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, -1, 1, -a))
2549
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_line, 1, -1, 1, c))
2550
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
2551
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_line))
2552
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_line))
2553
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_line))
2554
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
2555
+ right_notch_left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector((f2 + k) / 3, f1, 0), FreeCAD.Vector((f2 + k) / 3, -f1, 0)), False)
2556
+ right_notch_top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, f1, 0), FreeCAD.Vector((f2 + k) / 3, f1, 0)), False)
2557
+ right_notch_bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -f1, 0), FreeCAD.Vector((f2 + k) / 3, -f1, 0)), False)
2558
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_notch_left_line))
2559
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', right_notch_top_line, 1, right_line))
2560
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', right_notch_bottom_line, 1, right_line))
2561
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_notch_top_line, 2, right_notch_left_line, 1))
2562
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_notch_bottom_line, 2, right_notch_left_line, 2))
2563
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', right_notch_top_line, 1, -1, 1, -(e - f1)))
2564
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', right_notch_bottom_line, 1, -1, 1, (e - f1)))
2565
+ sketch.addConstraint(Sketcher.Constraint('Angle', right_notch_left_line, 1, right_notch_bottom_line, 2, 75 / 180 * math.pi))
2566
+ sketch.addConstraint(Sketcher.Constraint('Angle', right_notch_left_line, 2, right_notch_top_line, 2, -75 / 180 * math.pi))
2567
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_notch_left_line, 1, -1, 1, -(f2 + k) / 3))
2568
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_notch_bottom_line, 1, -1, 1, -c))
2569
+ sketch.trim(right_line, FreeCAD.Vector(c, 0, 0))
2570
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', bottom_line, 1, -1, 1, -c))
2571
+
2572
+ if dimensions["K"] > 0:
2573
+ left_notch_right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector((-c + k), (f1 - q), 0), FreeCAD.Vector((-c + k), -(f1 - q), 0)), False)
2574
+ left_notch_top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, (f1 - q), 0), FreeCAD.Vector((-c + k), (f1 - q), 0)), False)
2575
+ left_notch_bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -(f1 - q), 0), FreeCAD.Vector((-c + k), -(f1 - q), 0)), False)
2576
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_notch_right_line))
2577
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', left_notch_top_line, 1, left_line))
2578
+ sketch.addConstraint(Sketcher.Constraint('PointOnObject', left_notch_bottom_line, 1, left_line))
2579
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_notch_top_line, 2, left_notch_right_line, 1))
2580
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_notch_bottom_line, 2, left_notch_right_line, 2))
2581
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', left_notch_top_line, 1, -1, 1, -(e - (f1 - q))))
2582
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', left_notch_bottom_line, 1, -1, 1, (e - (f1 - q))))
2583
+ sketch.addConstraint(Sketcher.Constraint('Angle', left_notch_right_line, 1, left_notch_bottom_line, 2, -75 / 180 * math.pi))
2584
+ sketch.addConstraint(Sketcher.Constraint('Angle', left_notch_right_line, 2, left_notch_top_line, 2, 75 / 180 * math.pi))
2585
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_notch_right_line, 1, -1, 1, -(-c + k)))
2586
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_notch_top_line, 1, -1, 1, c))
2587
+ sketch.trim(left_line, FreeCAD.Vector(c, 0, 0))
2588
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', top_line, 1, -1, 1, c))
2589
+
2590
+ def get_negative_winding_window(self, dimensions):
2591
+ document = FreeCAD.ActiveDocument
2592
+ if dimensions["K"] < 0:
2593
+ k = dimensions["K"]
2594
+ else:
2595
+ k = 0
2596
+
2597
+ winding_window_cube = document.addObject("Part::Box", "winding_window_cube")
2598
+ winding_window_cube.Width = dimensions["E"]
2599
+ winding_window_cube.Height = dimensions["D"]
2600
+ winding_window_cube.Length = dimensions["C"] - k
2601
+ winding_window_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2 + k, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2602
+
2603
+ document.recompute()
2604
+
2605
+ return winding_window_cube
2606
+
2607
+ def get_shape_extras(self, data, piece):
2608
+ dimensions = data["dimensions"]
2609
+ document = FreeCAD.ActiveDocument
2610
+ central_column_cube = document.addObject("Part::Box", "central_column_cube")
2611
+ central_column_cube.Length = dimensions["F2"]
2612
+ central_column_cube.Width = dimensions["F"]
2613
+ central_column_cube.Height = dimensions["B"]
2614
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["F2"] / 2, -dimensions["F"] / 2, 0), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2615
+ top_right_vertex = self.edges_in_boundbox(part=central_column_cube,
2616
+ xmin=0,
2617
+ xmax=dimensions["F2"] / 2,
2618
+ ymin=0,
2619
+ ymax=dimensions["F"] / 2,
2620
+ zmin=0,
2621
+ zmax=dimensions["B"])[0]
2622
+ top_left_vertex = self.edges_in_boundbox(part=central_column_cube,
2623
+ xmin=-dimensions["F2"] / 2,
2624
+ xmax=0,
2625
+ ymin=0,
2626
+ ymax=dimensions["F"] / 2,
2627
+ zmin=0,
2628
+ zmax=dimensions["B"])[0]
2629
+ bottom_right_vertex = self.edges_in_boundbox(part=central_column_cube,
2630
+ xmin=0,
2631
+ xmax=dimensions["F2"] / 2,
2632
+ ymin=-dimensions["F"] / 2,
2633
+ ymax=0,
2634
+ zmin=0,
2635
+ zmax=dimensions["B"])[0]
2636
+ bottom_left_vertex = self.edges_in_boundbox(part=central_column_cube,
2637
+ xmin=-dimensions["F2"] / 2,
2638
+ xmax=0,
2639
+ ymin=-dimensions["F"] / 2,
2640
+ ymax=0,
2641
+ zmin=0,
2642
+ zmax=dimensions["B"])[0]
2643
+ vertexes = [top_right_vertex, top_left_vertex, bottom_right_vertex, bottom_left_vertex]
2644
+ chamfer = document.addObject("Part::Chamfer", "Chamfer")
2645
+ chamfer.Base = central_column_cube
2646
+ __chamfers__ = []
2647
+ for i in vertexes:
2648
+ __chamfers__.append((i + 1, dimensions["q"], dimensions["q"]))
2649
+ chamfer.Edges = __chamfers__
2650
+ central_column_cube.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2 + dimensions["K"], -dimensions["F"] / 2, 0), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2651
+ document.recompute()
2652
+
2653
+ piece_with_column = document.addObject("Part::MultiFuse", "Fusion")
2654
+ piece_with_column.Shapes = [piece, chamfer]
2655
+ document.recompute()
2656
+ return piece_with_column
2657
+
2658
+
2659
+ class U(E):
2660
+ def get_dimensions_and_subtypes(self):
2661
+ return {1: ["A", "B", "C", "D", "E"]}
2662
+
2663
+ def get_negative_winding_window(self, dimensions):
2664
+ document = FreeCAD.ActiveDocument
2665
+ central_hole = document.addObject("Part::Box", "central_hole")
2666
+ central_hole.Length = dimensions["C"]
2667
+ central_hole.Width = dimensions["E"]
2668
+ central_hole.Height = dimensions["D"]
2669
+ central_hole.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["E"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2670
+ return central_hole
2671
+
2672
+ def apply_machining(self, piece, machining, dimensions):
2673
+ document = FreeCAD.ActiveDocument
2674
+
2675
+ tool = document.addObject("Part::Box", "tool")
2676
+ winding_column_width = (dimensions["A"] - dimensions["E"]) / 2
2677
+ tool.Length = dimensions["A"]
2678
+ tool.Width = winding_column_width
2679
+ x_coordinate = -dimensions["A"] / 2
2680
+ if machining['coordinates'][0] == 0:
2681
+ y_coordinate = -winding_column_width / 2
2682
+ else:
2683
+ y_coordinate = winding_column_width / 2 + dimensions["E"]
2684
+
2685
+ tool.Height = machining['length'] * 1000
2686
+ tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2687
+
2688
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
2689
+ machined_piece.Base = piece
2690
+ machined_piece.Tool = tool
2691
+ document.recompute()
2692
+
2693
+ return machined_piece
2694
+
2695
+ def get_shape_extras(self, data, piece):
2696
+ dimensions = data["dimensions"]
2697
+ piece.Placement.move(FreeCAD.Vector(0,
2698
+ -(dimensions['E'] / 2 + (dimensions['A'] - dimensions['E']) / 4),
2699
+ 0))
2700
+ return piece
2701
+
2702
+
2703
+ class Ur(IPiece):
2704
+ def get_dimensions_and_subtypes(self):
2705
+ return {
2706
+ 1: ["A", "B", "C", "D", "H"],
2707
+ 2: ["A", "B", "C", "D", "H"],
2708
+ 3: ["A", "B", "C", "D", "F", "H"],
2709
+ 4: ["A", "B", "C", "D", "F", "G", "H"]
2710
+ }
2711
+
2712
+ def get_shape_extras(self, data, piece):
2713
+ dimensions = data["dimensions"]
2714
+ document = FreeCAD.ActiveDocument
2715
+ familySubtype = data["familySubtype"]
2716
+
2717
+ if familySubtype == '1' or familySubtype == '2':
2718
+ top_diameter = dimensions["C"]
2719
+ bottom_diameter = dimensions["C"]
2720
+ elif familySubtype == '3':
2721
+ top_diameter = dimensions["F"]
2722
+ bottom_diameter = dimensions["C"]
2723
+ elif familySubtype == '4':
2724
+ top_diameter = dimensions["F"]
2725
+ bottom_diameter = dimensions["F"]
2726
+
2727
+ top_column = document.addObject("Part::Cylinder", "top_column")
2728
+ top_column.Height = dimensions["D"]
2729
+ top_column.Radius = top_diameter / 2
2730
+ top_column.Placement = FreeCAD.Placement(FreeCAD.Vector(0, (dimensions["A"] - top_diameter) / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2731
+
2732
+ if familySubtype == '1' or familySubtype == '3':
2733
+ bottom_column = document.addObject("Part::Box", "bottom_column")
2734
+ bottom_column.Length = bottom_diameter
2735
+ bottom_column.Width = dimensions["H"]
2736
+ bottom_column.Height = dimensions["D"]
2737
+ bottom_column.Placement = FreeCAD.Placement(FreeCAD.Vector(-bottom_diameter / 2, -dimensions["A"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2738
+ elif familySubtype == '2' or familySubtype == '4':
2739
+ bottom_column = document.addObject("Part::Cylinder", "bottom_column")
2740
+ bottom_column.Height = dimensions["D"]
2741
+ bottom_column.Radius = bottom_diameter / 2
2742
+ bottom_column.Placement = FreeCAD.Placement(FreeCAD.Vector(0, -(dimensions["A"] - bottom_diameter) / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(90, 0, 0))
2743
+
2744
+ if familySubtype == '4':
2745
+ top_column_hole = document.addObject("Part::Cylinder", "top_column_hole")
2746
+ top_column_hole.Height = dimensions["B"]
2747
+ top_column_hole.Radius = dimensions["G"] / 2
2748
+ top_column_hole.Placement = FreeCAD.Placement(FreeCAD.Vector(0, (dimensions["A"] - top_diameter) / 2, 0), FreeCAD.Rotation(90, 0, 0))
2749
+
2750
+ bottom_column_hole = document.addObject("Part::Cylinder", "bottom_column_hole")
2751
+ bottom_column_hole.Height = dimensions["B"]
2752
+ bottom_column_hole.Radius = dimensions["G"] / 2
2753
+ bottom_column_hole.Placement = FreeCAD.Placement(FreeCAD.Vector(0, -(dimensions["A"] - bottom_diameter) / 2, 0), FreeCAD.Rotation(90, 0, 0))
2754
+
2755
+ columns = document.addObject("Part::MultiFuse", "columns")
2756
+ columns.Shapes = [piece, bottom_column, top_column]
2757
+ document.recompute()
2758
+
2759
+ if familySubtype == '4':
2760
+ top_cut = document.addObject("Part::Cut", "top_cut")
2761
+ top_cut.Base = columns
2762
+ top_cut.Tool = top_column_hole
2763
+ document.recompute()
2764
+ columns = top_cut
2765
+
2766
+ bottom_cut = document.addObject("Part::Cut", "bottom_cut")
2767
+ bottom_cut.Base = columns
2768
+ bottom_cut.Tool = bottom_column_hole
2769
+ document.recompute()
2770
+ columns = bottom_cut
2771
+
2772
+ columns.Placement.move(FreeCAD.Vector(0,
2773
+ -dimensions['A'] / 2 + top_diameter / 2,
2774
+ 0))
2775
+ return columns
2776
+
2777
+ def get_shape_base(self, data, sketch):
2778
+ dimensions = data["dimensions"]
2779
+ familySubtype = data["familySubtype"]
2780
+
2781
+ c = dimensions["C"] / 2
2782
+ a = dimensions["A"] / 2
2783
+ if familySubtype == '1' or familySubtype == '2' or familySubtype == '3':
2784
+ f = dimensions["C"] / 2
2785
+ else:
2786
+ f = dimensions["F"] / 2
2787
+
2788
+ if familySubtype == '1' or familySubtype == '3':
2789
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a - f, 0), FreeCAD.Vector(c, -a, 0)), False)
2790
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a, 0), FreeCAD.Vector(-c, a - f, 0)), False)
2791
+ elif familySubtype == '2' or familySubtype == '4':
2792
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a - f, 0), FreeCAD.Vector(c, -a + f, 0)), False)
2793
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a + f, 0), FreeCAD.Vector(-c, a - f, 0)), False)
2794
+
2795
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_line, 1, -1, 1, c))
2796
+ # sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
2797
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_line))
2798
+
2799
+ if familySubtype == '1' or familySubtype == '3':
2800
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -a, 0), FreeCAD.Vector(-c, -a, 0)), False)
2801
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
2802
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
2803
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, a))
2804
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
2805
+ elif familySubtype == '2' or familySubtype == '4':
2806
+ bottom_arc = sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(0, -(a - f), 0), FreeCAD.Vector(0, 0, 1), f), -math.pi, 0))
2807
+ sketch.addConstraint(Sketcher.Constraint('Diameter', bottom_arc, 2 * f))
2808
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_arc, 3, -1, 1, a - f))
2809
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_arc, 2, -1, 1, a - f))
2810
+ if familySubtype != '4':
2811
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_arc, 2, right_line, 2))
2812
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_arc, 1, left_line, 1))
2813
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_arc, 1, bottom_arc, 2))
2814
+
2815
+ top_arc = sketch.addGeometry(Part.ArcOfCircle(Part.Circle(FreeCAD.Vector(0, a - f, 0), FreeCAD.Vector(0, 0, 1), f), 0, -math.pi))
2816
+ sketch.addConstraint(Sketcher.Constraint('Diameter', top_arc, 2 * f))
2817
+ if familySubtype == '1':
2818
+ sketch.addConstraint(Sketcher.Constraint('Vertical', top_arc, 3, -1, 1))
2819
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_arc, 3, -1, 1, -(a - f)))
2820
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_arc, 2, -1, 1, -(a - f)))
2821
+ if familySubtype != '4':
2822
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_arc, 1, right_line, 1))
2823
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_arc, 2, left_line, 2))
2824
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_arc, 1, top_arc, 2))
2825
+ if familySubtype == '4':
2826
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -(a - f), 0), FreeCAD.Vector(-c, -(a - f), 0)), False)
2827
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
2828
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
2829
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, (a - f)))
2830
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
2831
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a - f, 0), FreeCAD.Vector(-c, a - f, 0)), False)
2832
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 1, top_line, 1))
2833
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_line, 2, left_line, 2))
2834
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, -1, 1, -(a - f)))
2835
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_line))
2836
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_line))
2837
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
2838
+ sketch.addConstraint(Sketcher.Constraint('Vertical', top_arc, 3, -1, 1))
2839
+ sketch.addConstraint(Sketcher.Constraint('Vertical', bottom_arc, 3, -1, 1))
2840
+ sketch.trim(bottom_line, FreeCAD.Vector(0, -(a - f), 0))
2841
+ sketch.trim(top_line, FreeCAD.Vector(0, a - f, 0))
2842
+
2843
+ def get_negative_winding_window(self, dimensions):
2844
+ document = FreeCAD.ActiveDocument
2845
+ central_hole = document.addObject("Part::Box", "central_hole")
2846
+ central_hole.Length = dimensions["C"]
2847
+ central_hole.Width = dimensions["A"]
2848
+ central_hole.Height = dimensions["D"]
2849
+ central_hole.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["A"] / 2, dimensions["B"] - dimensions["D"]), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
2850
+ return central_hole
2851
+
2852
+ def add_dimensions_and_export_view(self, data, original_dimensions, view, project_name, margin, colors, save_files, piece):
2853
+ def calculate_total_dimensions():
2854
+ if view.Name == "TopView":
2855
+ base_width = data['dimensions']['A'] + margin
2856
+ base_width += horizontal_offset
2857
+ if 'C' in dimensions:
2858
+ base_width += increment
2859
+
2860
+ base_height = data['dimensions']['C'] + margin
2861
+
2862
+ base_height += vertical_offset
2863
+ if 'A' in dimensions:
2864
+ base_height += increment
2865
+ if 'E' in dimensions:
2866
+ base_height += increment
2867
+ if 'F' in dimensions:
2868
+ base_height += increment
2869
+ if 'G' in dimensions and dimensions['G'] > 0:
2870
+ base_height += increment
2871
+ if 'H' in dimensions and dimensions['H'] > 0:
2872
+ base_height += increment
2873
+
2874
+ if view.Name == "FrontView":
2875
+ base_width = data['dimensions']['A'] + margin
2876
+ base_width += horizontal_offset
2877
+ if 'B' in dimensions:
2878
+ base_width += increment
2879
+ if 'D' in dimensions:
2880
+ base_width += increment
2881
+
2882
+ base_height = data['dimensions']['B'] + margin * 2
2883
+
2884
+ return base_width, base_height
2885
+
2886
+ def create_dimension(starting_coordinates, ending_coordinates, dimension_type, dimension_label, label_offset=0, label_alignment=0):
2887
+ dimension_svg = ""
2888
+
2889
+ if dimension_type == "DistanceY":
2890
+ main_line_start = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
2891
+ main_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
2892
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
2893
+ left_aux_line_end = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
2894
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
2895
+ right_aux_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
2896
+
2897
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + ending_coordinates[0] + label_offset - dimension_font_size / 4},{1000 - view.Y.Value + label_alignment})" stroke-linecap="square" stroke-linejoin="bevel">
2898
+ <text x="0" y="0" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400" transform="rotate(-90)">{dimension_label}</text>
2899
+ </g>\n""".replace(" ", "")
2900
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
2901
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
2902
+ </g>\n""".replace(" ", "")
2903
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
2904
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0] + label_offset},{ending_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
2905
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L6,-15 L-6,-15 L0,0"/>
2906
+ </g>
2907
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0] + label_offset},{starting_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
2908
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-6,15 L6,15 L0,0"/>
2909
+ </g>
2910
+ </g>\n""".replace(" ", "")
2911
+ elif dimension_type == "DistanceX":
2912
+ main_line_start = [starting_coordinates[0], starting_coordinates[1] + label_offset]
2913
+ main_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
2914
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
2915
+ left_aux_line_end = [starting_coordinates[0], starting_coordinates[1] + label_offset]
2916
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
2917
+ right_aux_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
2918
+
2919
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + label_alignment},{1000 - view.Y.Value})" stroke-linecap="square" stroke-linejoin="bevel">
2920
+ <text x="0" y="{ending_coordinates[1] + label_offset - dimension_font_size / 4}" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400">{dimension_label}</text>
2921
+ </g>\n""".replace(" ", "")
2922
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
2923
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
2924
+ </g>\n""".replace(" ", "")
2925
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
2926
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0]},{ending_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
2927
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-15,-6 L-15,6 L0,0"/>
2928
+ </g>
2929
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0]},{starting_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
2930
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L15,6 L15,-6 L0,0"/>
2931
+ </g>
2932
+ </g>\n""".replace(" ", "")
2933
+ return dimension_svg
2934
+
2935
+ projection_line_thickness = 4
2936
+ dimension_line_thickness = 1
2937
+ dimension_font_size = 30
2938
+ horizontal_offset = 75
2939
+ vertical_offset = 75
2940
+ increment = 50
2941
+ dimensions = data["dimensions"]
2942
+ shape_semi_height = dimensions['C'] / 2
2943
+ base_width, base_height = calculate_total_dimensions()
2944
+ head = f"""<svg xmlns:dc="http://purl.org/dc/elements/1.1/" baseProfile="tiny" xmlns:svg="http://www.w3.org/2000/svg" version="1.2" width="100%" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 {base_width} {base_height}" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="100%" xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
2945
+ <title>FreeCAD SVG Export</title>
2946
+ <desc>Drawing page: {view.Name} exported from FreeCAD document: {project_name}</desc>
2947
+ <defs/>
2948
+ <g id="{view.Name}" inkscape:label="TechDraw" inkscape:groupmode="layer">
2949
+ <g id="DrawingContent" fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel">""".replace(" ", "")
2950
+ projetion_head = f""" <g fill-opacity="1" font-size="29.1042" font-style="normal" fill="#ffffff" font-family="MS Shell Dlg 2" stroke="none" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})">\n"""
2951
+ projetion_tail = """ </g>\n"""
2952
+ tail = """</g>
2953
+ </g>
2954
+ </svg>
2955
+ """.replace(" ", "")
2956
+ svgFile_data = ""
2957
+ svgFile_data += head
2958
+ svgFile_data += projetion_head
2959
+ if 'F' not in dimensions:
2960
+ dimensions['F'] = dimensions['C']
2961
+
2962
+ if view.Name == "TopView":
2963
+ m = piece.Placement.Matrix
2964
+ m.rotateZ(math.radians(90))
2965
+ piece.Placement.Matrix = m
2966
+ piece.Placement.move(FreeCAD.Vector(-dimensions["A"] / 2 + dimensions["F"] / 2, 0, 0))
2967
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 0., 1.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
2968
+ else:
2969
+ m = piece.Placement.Matrix
2970
+ m.rotateY(math.radians(90))
2971
+ piece.Placement.Matrix = m
2972
+ piece.Placement.move(FreeCAD.Vector(-dimensions["B"] / 2, 0, 0))
2973
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 1., 0.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
2974
+
2975
+ svgFile_data += projetion_tail
2976
+ if 'F' not in original_dimensions:
2977
+ original_dimensions['F'] = original_dimensions['C']
2978
+
2979
+ if 'E' not in original_dimensions:
2980
+ original_dimensions['E'] = original_dimensions['A'] - original_dimensions['F'] - original_dimensions['H']
2981
+
2982
+ if 'E' not in dimensions:
2983
+ dimensions['E'] = dimensions['A'] - dimensions['F'] - dimensions['H']
2984
+
2985
+ if view.Name == "TopView":
2986
+ if "C" in dimensions and dimensions["C"] > 0:
2987
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['C'] / 2],
2988
+ ending_coordinates=[dimensions['A'] / 2, dimensions['C'] / 2],
2989
+ dimension_type="DistanceY",
2990
+ dimension_label=f"C: {round(original_dimensions['C'], 2)} mm",
2991
+ label_offset=horizontal_offset)
2992
+ horizontal_offset += increment
2993
+
2994
+ if "G" in dimensions and dimensions['G'] > 0:
2995
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2 + dimensions['F'] / 2 - dimensions['G'] / 2, 0],
2996
+ ending_coordinates=[-dimensions['A'] / 2 + dimensions['F'] / 2 + dimensions['G'] / 2, 0],
2997
+ dimension_type="DistanceX",
2998
+ dimension_label=f"G: {round(original_dimensions['G'], 2)} mm",
2999
+ label_offset=vertical_offset + shape_semi_height,
3000
+ label_alignment=-dimensions['A'] / 2 + dimensions['F'] / 2)
3001
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2 - dimensions['F'] / 2 + dimensions['G'] / 2, 0],
3002
+ ending_coordinates=[dimensions['A'] / 2 - dimensions['F'] / 2 - dimensions['G'] / 2, 0],
3003
+ dimension_type="DistanceX",
3004
+ dimension_label=f"G: {round(original_dimensions['G'], 2)} mm",
3005
+ label_offset=vertical_offset + shape_semi_height,
3006
+ label_alignment=dimensions['A'] / 2 - dimensions['F'] / 2)
3007
+ vertical_offset += increment
3008
+ if "F" in dimensions and dimensions["F"] > 0:
3009
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
3010
+ ending_coordinates=[-dimensions['A'] / 2 + dimensions['F'], 0],
3011
+ dimension_type="DistanceX",
3012
+ dimension_label=f"F: {round(original_dimensions['F'], 2)} mm",
3013
+ label_offset=vertical_offset + shape_semi_height,
3014
+ label_alignment=-dimensions['A'] / 2 + dimensions['F'] / 2)
3015
+ if "H" in dimensions and dimensions["H"] > 0:
3016
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2 - dimensions['H'], 0],
3017
+ ending_coordinates=[dimensions['A'] / 2, 0],
3018
+ dimension_type="DistanceX",
3019
+ dimension_label=f"H: {round(original_dimensions['H'], 2)} mm",
3020
+ label_offset=vertical_offset + shape_semi_height,
3021
+ label_alignment=dimensions['A'] / 2 - dimensions['H'] / 2)
3022
+
3023
+ if 'F' in dimensions:
3024
+ left_column_diameter = dimensions['F']
3025
+ else:
3026
+ left_column_diameter = dimensions['C']
3027
+
3028
+ if 'H' in dimensions:
3029
+ right_column_diameter = dimensions['H']
3030
+ else:
3031
+ right_column_diameter = dimensions['C']
3032
+
3033
+ if 'E' not in original_dimensions:
3034
+ original_dimensions['E'] = original_dimensions['A'] - original_dimensions['F'] - original_dimensions['']
3035
+
3036
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2 + left_column_diameter, 0],
3037
+ ending_coordinates=[dimensions['A'] / 2 - right_column_diameter, 0],
3038
+ dimension_type="DistanceX",
3039
+ dimension_label=f"E: Min {round(original_dimensions['E'], 2)} mm",
3040
+ label_offset=vertical_offset + shape_semi_height,
3041
+ label_alignment=-dimensions['A'] / 2 + left_column_diameter + (dimensions['A'] - left_column_diameter - right_column_diameter) / 2)
3042
+ vertical_offset += increment
3043
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
3044
+ ending_coordinates=[dimensions['A'] / 2, 0],
3045
+ dimension_type="DistanceX",
3046
+ dimension_label=f"A: {round(original_dimensions['A'], 2)} mm",
3047
+ label_offset=vertical_offset + shape_semi_height)
3048
+ vertical_offset += increment
3049
+ else:
3050
+ if 'H' in dimensions:
3051
+ starting_point_for_d = dimensions['H'] / 2
3052
+ else:
3053
+ starting_point_for_d = dimensions['E'] / 2
3054
+ svgFile_data += create_dimension(starting_coordinates=[starting_point_for_d, -dimensions['B'] / 2],
3055
+ ending_coordinates=[starting_point_for_d, -dimensions['B'] / 2 + dimensions['D']],
3056
+ dimension_type="DistanceY",
3057
+ dimension_label=f"D: {round(original_dimensions['D'], 2)} mm",
3058
+ label_offset=horizontal_offset + (dimensions['A'] / 2 - starting_point_for_d),
3059
+ label_alignment=-dimensions['B'] / 2 + dimensions['D'] / 2)
3060
+ horizontal_offset += increment
3061
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['B'] / 2],
3062
+ ending_coordinates=[dimensions['A'] / 2, dimensions['B'] / 2],
3063
+ dimension_type="DistanceY",
3064
+ dimension_label=f"B: {round(original_dimensions['B'], 2)} mm",
3065
+ label_offset=horizontal_offset)
3066
+
3067
+ svgFile_data += tail
3068
+
3069
+ if save_files:
3070
+ svgFile = open(f"{self.output_path}/{project_name}_{view.Name}.svg", "w")
3071
+ svgFile.write(svgFile_data)
3072
+ svgFile.close()
3073
+ return svgFile_data
3074
+
3075
+ def apply_machining(self, piece, machining, dimensions):
3076
+ document = FreeCAD.ActiveDocument
3077
+
3078
+ tool = document.addObject("Part::Box", "tool")
3079
+ if 'F' in dimensions and dimensions['F'] > 0:
3080
+ winding_column_width = dimensions["F"]
3081
+ else:
3082
+ winding_column_width = dimensions["C"]
3083
+ tool.Length = dimensions["A"]
3084
+ tool.Width = winding_column_width
3085
+ x_coordinate = -dimensions["A"] / 2
3086
+ if machining['coordinates'][0] == 0:
3087
+ tool.Width = winding_column_width
3088
+ y_coordinate = -winding_column_width / 2
3089
+ else:
3090
+ tool.Width = dimensions["A"]
3091
+ y_coordinate = winding_column_width / 2
3092
+
3093
+ tool.Height = machining['length'] * 1000
3094
+ tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
3095
+
3096
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
3097
+ machined_piece.Base = piece
3098
+ machined_piece.Tool = tool
3099
+ document.recompute()
3100
+
3101
+ return machined_piece
3102
+
3103
+
3104
+ class Ut(IPiece):
3105
+ def get_dimensions_and_subtypes(self):
3106
+ return {
3107
+ 1: ["A", "B", "C", "D", "E", "F"],
3108
+ }
3109
+
3110
+ def get_shape_extras(self, data, piece):
3111
+ dimensions = data["dimensions"]
3112
+ document = FreeCAD.ActiveDocument
3113
+
3114
+ top_column = document.addObject("Part::Box", "top_column")
3115
+ top_column.Length = dimensions["C"]
3116
+ top_column.Width = dimensions["F"]
3117
+ top_column.Height = dimensions["D"]
3118
+ top_column.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["A"] / 2, (dimensions["B"] - dimensions["D"]) / 2), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
3119
+
3120
+ bottom_column_width = dimensions["A"] - dimensions["E"] - dimensions["F"]
3121
+ bottom_column = document.addObject("Part::Box", "bottom_column")
3122
+ bottom_column.Length = dimensions["C"]
3123
+ bottom_column.Width = bottom_column_width
3124
+ bottom_column.Height = dimensions["D"]
3125
+ bottom_column.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, dimensions["A"] / 2 - bottom_column_width, (dimensions["B"] - dimensions["D"]) / 2), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
3126
+
3127
+ columns = document.addObject("Part::MultiFuse", "columns")
3128
+ columns.Shapes = [piece, bottom_column, top_column]
3129
+ document.recompute()
3130
+
3131
+ columns.Placement.move(FreeCAD.Vector(0, 0, dimensions["B"] / 2))
3132
+
3133
+ return columns
3134
+
3135
+ def get_shape_base(self, data, sketch):
3136
+ dimensions = data["dimensions"]
3137
+ c = dimensions["C"] / 2
3138
+ a = dimensions["A"] / 2
3139
+
3140
+ top_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, a, 0), FreeCAD.Vector(c, a, 0)), False)
3141
+ right_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, a, 0), FreeCAD.Vector(c, -a, 0)), False)
3142
+ bottom_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(c, -a, 0), FreeCAD.Vector(-c, -a, 0)), False)
3143
+ left_line = sketch.addGeometry(Part.LineSegment(FreeCAD.Vector(-c, -a, 0), FreeCAD.Vector(-c, a, 0)), False)
3144
+ sketch.addConstraint(Sketcher.Constraint('Coincident', top_line, 2, right_line, 1))
3145
+ sketch.addConstraint(Sketcher.Constraint('Coincident', right_line, 2, bottom_line, 1))
3146
+ sketch.addConstraint(Sketcher.Constraint('Coincident', bottom_line, 2, left_line, 1))
3147
+ sketch.addConstraint(Sketcher.Constraint('Coincident', left_line, 2, top_line, 1))
3148
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', bottom_line, 1, -1, 1, a))
3149
+ sketch.addConstraint(Sketcher.Constraint('DistanceY', top_line, 1, -1, 1, -a))
3150
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', left_line, 1, -1, 1, c))
3151
+ sketch.addConstraint(Sketcher.Constraint('DistanceX', right_line, 1, -1, 1, -c))
3152
+ sketch.addConstraint(Sketcher.Constraint('Vertical', right_line))
3153
+ sketch.addConstraint(Sketcher.Constraint('Vertical', left_line))
3154
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', top_line))
3155
+ sketch.addConstraint(Sketcher.Constraint('Horizontal', bottom_line))
3156
+
3157
+ def get_negative_winding_window(self, dimensions):
3158
+ document = FreeCAD.ActiveDocument
3159
+ central_hole = document.addObject("Part::Box", "central_hole")
3160
+ central_hole.Length = dimensions["C"]
3161
+ central_hole.Width = dimensions["A"]
3162
+ central_hole.Height = dimensions["D"]
3163
+ central_hole.Placement = FreeCAD.Placement(FreeCAD.Vector(-dimensions["C"] / 2, -dimensions["A"] / 2, (dimensions["B"] - dimensions["D"]) / 2), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
3164
+ return central_hole
3165
+
3166
+ def get_top_projection(self, data, piece, margin):
3167
+
3168
+ dimensions = data["dimensions"]
3169
+
3170
+ document = FreeCAD.ActiveDocument
3171
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
3172
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
3173
+ page.Template = template
3174
+ document.recompute()
3175
+
3176
+ aux_view = document.addObject('TechDraw::DrawViewPart', 'AuxView')
3177
+ page.addView(aux_view)
3178
+ aux_view.Source = [piece]
3179
+ aux_view.Direction = FreeCAD.Vector(1.00, 0.00, 0.00)
3180
+ aux_view.XDirection = FreeCAD.Vector(0.00, 1.00, 0.00)
3181
+ aux_view.X = margin + dimensions['A'] / 2
3182
+
3183
+ semi_height = dimensions['B'] / 2
3184
+
3185
+ top_view = document.addObject('TechDraw::DrawViewSection', 'TopView')
3186
+ page.addView(top_view)
3187
+ top_view.BaseView = document.getObject('AuxView')
3188
+ top_view.Source = document.getObject('AuxView').Source
3189
+ top_view.ScaleType = 0
3190
+ top_view.SectionDirection = 'Down'
3191
+ top_view.SectionNormal = FreeCAD.Vector(0.000, 0.000, 1.000)
3192
+ top_view.SectionOrigin = FreeCAD.Vector(0, 0.000, semi_height)
3193
+ top_view.SectionSymbol = ''
3194
+ top_view.Label = 'Section - '
3195
+ top_view.Scale = 1.000000
3196
+ top_view.ScaleType = 0
3197
+ top_view.Rotation = 0
3198
+ top_view.Direction = FreeCAD.Vector(0.00, 0.00, 1.00)
3199
+ top_view.XDirection = FreeCAD.Vector(0.00, 1.00, 0.00)
3200
+ top_view.X = margin + dimensions['A'] / 2
3201
+
3202
+ base_height = data['dimensions']['C'] + margin
3203
+
3204
+ top_view.Y = 1000 - base_height / 2
3205
+
3206
+ top_view.Scale = 1
3207
+ document.recompute()
3208
+ return top_view
3209
+
3210
+ def get_front_projection(self, data, piece, margin):
3211
+
3212
+ dimensions = data["dimensions"]
3213
+
3214
+ document = FreeCAD.ActiveDocument
3215
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
3216
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
3217
+ page.Template = template
3218
+ document.recompute()
3219
+
3220
+ front_view = document.addObject('TechDraw::DrawViewPart', 'FrontView')
3221
+ page.addView(front_view)
3222
+ front_view.Source = [piece]
3223
+ front_view.Direction = FreeCAD.Vector(1.00, 0.00, 0.00)
3224
+ front_view.XDirection = FreeCAD.Vector(0.00, 1.00, 0.00)
3225
+ front_view.X = margin + dimensions['A'] / 2
3226
+ front_view.Y = 1000 - margin - dimensions['B'] / 2
3227
+
3228
+ document.recompute()
3229
+
3230
+ return front_view
3231
+
3232
+ def add_dimensions_and_export_view(self, data, original_dimensions, view, project_name, margin, colors, save_files, piece):
3233
+ def calculate_total_dimensions():
3234
+ if view.Name == "TopView":
3235
+ base_width = data['dimensions']['A'] + margin
3236
+ base_width += horizontal_offset
3237
+ if 'C' in dimensions:
3238
+ base_width += increment
3239
+
3240
+ base_height = data['dimensions']['C'] + margin
3241
+
3242
+ base_height += vertical_offset
3243
+ if 'A' in dimensions:
3244
+ base_height += increment
3245
+ if 'E' in dimensions:
3246
+ base_height += increment
3247
+ if 'F' in dimensions:
3248
+ base_height += increment
3249
+
3250
+ if view.Name == "FrontView":
3251
+ base_width = data['dimensions']['A'] + margin
3252
+ base_width += horizontal_offset
3253
+ if 'B' in dimensions:
3254
+ base_width += increment
3255
+ if 'D' in dimensions:
3256
+ base_width += increment
3257
+
3258
+ base_height = data['dimensions']['B'] + margin * 2
3259
+
3260
+ return base_width, base_height
3261
+
3262
+ def create_dimension(starting_coordinates, ending_coordinates, dimension_type, dimension_label, label_offset=0, label_alignment=0):
3263
+ dimension_svg = ""
3264
+
3265
+ if dimension_type == "DistanceY":
3266
+ main_line_start = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
3267
+ main_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
3268
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
3269
+ left_aux_line_end = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
3270
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
3271
+ right_aux_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
3272
+
3273
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + ending_coordinates[0] + label_offset - dimension_font_size / 4},{1000 - view.Y.Value + label_alignment})" stroke-linecap="square" stroke-linejoin="bevel">
3274
+ <text x="0" y="0" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400" transform="rotate(-90)">{dimension_label}</text>
3275
+ </g>\n""".replace(" ", "")
3276
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3277
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
3278
+ </g>\n""".replace(" ", "")
3279
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3280
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0] + label_offset},{ending_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
3281
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L6,-15 L-6,-15 L0,0"/>
3282
+ </g>
3283
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0] + label_offset},{starting_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
3284
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-6,15 L6,15 L0,0"/>
3285
+ </g>
3286
+ </g>\n""".replace(" ", "")
3287
+ elif dimension_type == "DistanceX":
3288
+ main_line_start = [starting_coordinates[0], starting_coordinates[1] + label_offset]
3289
+ main_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
3290
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
3291
+ left_aux_line_end = [starting_coordinates[0], starting_coordinates[1] + label_offset]
3292
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
3293
+ right_aux_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
3294
+
3295
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + label_alignment},{1000 - view.Y.Value})" stroke-linecap="square" stroke-linejoin="bevel">
3296
+ <text x="0" y="{ending_coordinates[1] + label_offset - dimension_font_size / 4}" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400">{dimension_label}</text>
3297
+ </g>\n""".replace(" ", "")
3298
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3299
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
3300
+ </g>\n""".replace(" ", "")
3301
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3302
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0]},{ending_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
3303
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-15,-6 L-15,6 L0,0"/>
3304
+ </g>
3305
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0]},{starting_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
3306
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L15,6 L15,-6 L0,0"/>
3307
+ </g>
3308
+ </g>\n""".replace(" ", "")
3309
+ return dimension_svg
3310
+
3311
+ projection_line_thickness = 4
3312
+ dimension_line_thickness = 1
3313
+ dimension_font_size = 30
3314
+ horizontal_offset = 75
3315
+ vertical_offset = 75
3316
+ increment = 50
3317
+ dimensions = data["dimensions"]
3318
+ shape_semi_height = dimensions['C'] / 2
3319
+ base_width, base_height = calculate_total_dimensions()
3320
+ head = f"""<svg xmlns:dc="http://purl.org/dc/elements/1.1/" baseProfile="tiny" xmlns:svg="http://www.w3.org/2000/svg" version="1.2" width="100%" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 {base_width} {base_height}" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="100%" xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
3321
+ <title>FreeCAD SVG Export</title>
3322
+ <desc>Drawing page: {view.Name} exported from FreeCAD document: {project_name}</desc>
3323
+ <defs/>
3324
+ <g id="{view.Name}" inkscape:label="TechDraw" inkscape:groupmode="layer">
3325
+ <g id="DrawingContent" fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel">""".replace(" ", "")
3326
+ projetion_head = f""" <g fill-opacity="1" font-size="29.1042" font-style="normal" fill="#ffffff" font-family="MS Shell Dlg 2" stroke="none" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})">\n"""
3327
+ projetion_tail = """ </g>\n"""
3328
+ tail = """</g>
3329
+ </g>
3330
+ </svg>
3331
+ """.replace(" ", "")
3332
+ svgFile_data = ""
3333
+ svgFile_data += head
3334
+ svgFile_data += projetion_head
3335
+
3336
+ if view.Name == "TopView":
3337
+ m = piece.Placement.Matrix
3338
+ m.rotateZ(math.radians(90))
3339
+ piece.Placement.Matrix = m
3340
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 0., 1.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
3341
+ else:
3342
+ m = piece.Placement.Matrix
3343
+ m.rotateY(math.radians(90))
3344
+ piece.Placement.Matrix = m
3345
+ piece.Placement.move(FreeCAD.Vector(-dimensions["B"], 0, 0))
3346
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 1., 0.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
3347
+ svgFile_data += projetion_tail
3348
+ if view.Name == "TopView":
3349
+ if "C" in dimensions and dimensions["C"] > 0:
3350
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['C'] / 2],
3351
+ ending_coordinates=[dimensions['A'] / 2, dimensions['C'] / 2],
3352
+ dimension_type="DistanceY",
3353
+ dimension_label=f"C: {round(original_dimensions['C'], 2)} mm",
3354
+ label_offset=horizontal_offset)
3355
+ horizontal_offset += increment
3356
+
3357
+ if "F" in dimensions and dimensions["F"] > 0:
3358
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
3359
+ ending_coordinates=[-dimensions['A'] / 2 + dimensions['F'], 0],
3360
+ dimension_type="DistanceX",
3361
+ dimension_label=f"F: {round(original_dimensions['F'], 2)} mm",
3362
+ label_offset=vertical_offset + shape_semi_height,
3363
+ label_alignment=-dimensions['A'] / 2 + dimensions['F'] / 2)
3364
+
3365
+ left_column_diameter = dimensions['F']
3366
+ right_column_diameter = dimensions['A'] - dimensions['E'] - dimensions['F']
3367
+
3368
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2 + left_column_diameter, 0],
3369
+ ending_coordinates=[dimensions['A'] / 2 - right_column_diameter, 0],
3370
+ dimension_type="DistanceX",
3371
+ dimension_label=f"E: {round(original_dimensions['E'], 2)} mm",
3372
+ label_offset=vertical_offset + shape_semi_height,
3373
+ label_alignment=-dimensions['A'] / 2 + left_column_diameter + (dimensions['A'] - left_column_diameter - right_column_diameter) / 2)
3374
+ vertical_offset += increment
3375
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
3376
+ ending_coordinates=[dimensions['A'] / 2, 0],
3377
+ dimension_type="DistanceX",
3378
+ dimension_label=f"A: {round(original_dimensions['A'], 2)} mm",
3379
+ label_offset=vertical_offset + shape_semi_height)
3380
+ vertical_offset += increment
3381
+ else:
3382
+ if 'H' in dimensions:
3383
+ starting_point_for_d = dimensions['H'] / 2
3384
+ else:
3385
+ starting_point_for_d = dimensions['E'] / 2
3386
+ svgFile_data += create_dimension(starting_coordinates=[starting_point_for_d, -dimensions['D']/ 2],
3387
+ ending_coordinates=[starting_point_for_d, dimensions['D'] / 2],
3388
+ dimension_type="DistanceY",
3389
+ dimension_label=f"D: {round(original_dimensions['D'], 2)} mm",
3390
+ label_offset=horizontal_offset + (dimensions['A'] / 2 - starting_point_for_d),
3391
+ label_alignment=-dimensions['B'] / 2 + dimensions['D'] / 2)
3392
+ horizontal_offset += increment
3393
+ svgFile_data += create_dimension(starting_coordinates=[dimensions['A'] / 2, -dimensions['B'] / 2],
3394
+ ending_coordinates=[dimensions['A'] / 2, dimensions['B'] / 2],
3395
+ dimension_type="DistanceY",
3396
+ dimension_label=f"B: {round(original_dimensions['B'], 2)} mm",
3397
+ label_offset=horizontal_offset)
3398
+
3399
+ svgFile_data += tail
3400
+
3401
+ if save_files:
3402
+ svgFile = open(f"{self.output_path}/{project_name}_{view.Name}.svg", "w")
3403
+ svgFile.write(svgFile_data)
3404
+ svgFile.close()
3405
+ return svgFile_data
3406
+
3407
+ def apply_machining(self, piece, machining, dimensions):
3408
+ document = FreeCAD.ActiveDocument
3409
+
3410
+ tool = document.addObject("Part::Box", "tool")
3411
+ tool.Length = dimensions["A"]
3412
+ tool.Width = dimensions["A"] / 2
3413
+ x_coordinate = -dimensions["A"] / 2
3414
+ if machining['coordinates'][0] == 0:
3415
+ y_coordinate = -dimensions["A"] / 2
3416
+ else:
3417
+ y_coordinate = 0
3418
+
3419
+ tool.Height = machining['length'] * 1000
3420
+ tool.Placement = FreeCAD.Placement(FreeCAD.Vector(x_coordinate, y_coordinate, (machining['coordinates'][1] - machining['length'] / 2) * 1000), FreeCAD.Rotation(FreeCAD.Vector(0.00, 0.00, 1.00), 0.00))
3421
+
3422
+ machined_piece = document.addObject("Part::Cut", "machined_piece")
3423
+ machined_piece.Base = piece
3424
+ machined_piece.Tool = tool
3425
+ document.recompute()
3426
+
3427
+ return machined_piece
3428
+
3429
+
3430
+ class T(IPiece):
3431
+ def get_dimensions_and_subtypes(self):
3432
+ return {1: ["A", "B", "C"]}
3433
+
3434
+ def get_negative_winding_window(self, dimensions):
3435
+ return None
3436
+
3437
+ def get_shape_base(self, data, sketch):
3438
+ dimensions = data["dimensions"]
3439
+
3440
+ inner_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["B"] / 2), False)
3441
+ sketch.addConstraint(Sketcher.Constraint('Coincident', inner_circle, 3, -1, 1))
3442
+ sketch.addConstraint(Sketcher.Constraint('Diameter', inner_circle, dimensions["B"]))
3443
+ outer_circle = sketch.addGeometry(Part.Circle(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), dimensions["A"] / 2), False)
3444
+ sketch.addConstraint(Sketcher.Constraint('Coincident', outer_circle, 3, -1, 1))
3445
+ sketch.addConstraint(Sketcher.Constraint('Diameter', outer_circle, dimensions["A"]))
3446
+
3447
+ def get_shape_extras(self, data, piece):
3448
+ # rotation in order to avoid cut in projection
3449
+ m = piece.Base.Placement.Matrix
3450
+ m.rotateZ(math.radians(180))
3451
+ piece.Base.Placement.Matrix = m
3452
+ return piece
3453
+
3454
+
3455
+ def get_top_projection(self, data, piece, margin):
3456
+
3457
+ dimensions = data["dimensions"]
3458
+
3459
+ document = FreeCAD.ActiveDocument
3460
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
3461
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
3462
+ page.Template = template
3463
+ document.recompute()
3464
+
3465
+ top_view = document.addObject('TechDraw::DrawViewPart', 'TopView')
3466
+ page.addView(top_view)
3467
+ top_view.Source = [piece]
3468
+ top_view.Direction = FreeCAD.Vector(0.00, 0.00, 1.00)
3469
+ top_view.XDirection = FreeCAD.Vector(0.00, -1.00, 0.00)
3470
+ top_view.X = margin + dimensions['A'] / 2
3471
+ top_view.Y = 1000 - data['dimensions']['A'] / 2 - margin / 2
3472
+
3473
+ top_view.Scale = 1
3474
+ document.recompute()
3475
+ return top_view
3476
+
3477
+ def get_front_projection(self, data, piece, margin):
3478
+
3479
+ dimensions = data["dimensions"]
3480
+
3481
+ document = FreeCAD.ActiveDocument
3482
+ page = document.addObject('TechDraw::DrawPage', 'Top Page')
3483
+ template = document.addObject('TechDraw::DrawSVGTemplate', 'Template')
3484
+ page.Template = template
3485
+ document.recompute()
3486
+
3487
+ semi_depth = 0
3488
+
3489
+ section_front_view = document.addObject('TechDraw::DrawViewSection', 'FrontView')
3490
+ page.addView(section_front_view)
3491
+ section_front_view.BaseView = document.getObject('TopView')
3492
+ section_front_view.Source = document.getObject('TopView').Source
3493
+ section_front_view.ScaleType = 0
3494
+ section_front_view.SectionDirection = 'Down'
3495
+ section_front_view.SectionNormal = FreeCAD.Vector(-1.000, 0.000, 0.000)
3496
+ section_front_view.SectionOrigin = FreeCAD.Vector(semi_depth, 0.000, 0)
3497
+ section_front_view.SectionSymbol = ''
3498
+ section_front_view.Label = 'Section - '
3499
+ section_front_view.Scale = 1.000000
3500
+ section_front_view.ScaleType = 0
3501
+ section_front_view.Rotation = 0
3502
+ section_front_view.Direction = FreeCAD.Vector(-1.00, 0.00, 0.00)
3503
+ section_front_view.XDirection = FreeCAD.Vector(0.00, -1.00, 0.00)
3504
+ section_front_view.X = margin + dimensions['A'] / 2
3505
+ section_front_view.Y = 1000 - margin - dimensions['C'] / 2
3506
+ document.recompute()
3507
+
3508
+ return section_front_view
3509
+
3510
+ def add_dimensions_and_export_view(self, data, original_dimensions, view, project_name, margin, colors, save_files, piece):
3511
+ def calculate_total_dimensions():
3512
+ if view.Name == "TopView":
3513
+ base_width = data['dimensions']['A'] + margin
3514
+ base_width += horizontal_offset
3515
+
3516
+ base_height = data['dimensions']['A'] + margin
3517
+ base_height += vertical_offset
3518
+ base_height += increment
3519
+
3520
+ if view.Name == "FrontView":
3521
+ base_width = data['dimensions']['A'] + margin
3522
+ base_width += horizontal_offset
3523
+
3524
+ base_height = data['dimensions']['C'] + margin
3525
+ base_height += vertical_offset
3526
+
3527
+ return base_width, base_height
3528
+
3529
+ def create_dimension(starting_coordinates, ending_coordinates, dimension_type, dimension_label, label_offset=0, label_alignment=0):
3530
+ dimension_svg = ""
3531
+
3532
+ if dimension_type == "DistanceY":
3533
+ main_line_start = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
3534
+ main_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
3535
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
3536
+ left_aux_line_end = [starting_coordinates[0] + label_offset, starting_coordinates[1]]
3537
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
3538
+ right_aux_line_end = [ending_coordinates[0] + label_offset, ending_coordinates[1]]
3539
+
3540
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + ending_coordinates[0] + label_offset - dimension_font_size / 4},{1000 - view.Y.Value + label_alignment})" stroke-linecap="square" stroke-linejoin="bevel">
3541
+ <text x="0" y="0" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400" transform="rotate(-90)">{dimension_label}</text>
3542
+ </g>\n""".replace(" ", "")
3543
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3544
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
3545
+ </g>\n""".replace(" ", "")
3546
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3547
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0] + label_offset},{ending_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
3548
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L6,-15 L-6,-15 L0,0"/>
3549
+ </g>
3550
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0] + label_offset},{starting_coordinates[1]})" stroke-linecap="round" stroke-linejoin="bevel">
3551
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-6,15 L6,15 L0,0"/>
3552
+ </g>
3553
+ </g>\n""".replace(" ", "")
3554
+ elif dimension_type == "DistanceX":
3555
+ main_line_start = [starting_coordinates[0], starting_coordinates[1] + label_offset]
3556
+ main_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
3557
+ left_aux_line_start = [starting_coordinates[0], starting_coordinates[1]]
3558
+ left_aux_line_end = [starting_coordinates[0], starting_coordinates[1] + label_offset]
3559
+ right_aux_line_start = [ending_coordinates[0], ending_coordinates[1]]
3560
+ right_aux_line_end = [ending_coordinates[0], ending_coordinates[1] + label_offset]
3561
+
3562
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value + label_alignment},{1000 - view.Y.Value})" stroke-linecap="square" stroke-linejoin="bevel">
3563
+ <text x="0" y="{ending_coordinates[1] + label_offset - dimension_font_size / 4}" text-anchor="middle" fill-opacity="1" font-size="{dimension_font_size}" font-style="normal" fill="{colors['dimension_color']}" font-family="osifont" stroke="none" xml:space="preserve" font-weight="400">{dimension_label}</text>
3564
+ </g>\n""".replace(" ", "")
3565
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3566
+ <path fill-rule="evenodd" vector-effect="none" d="M{main_line_start[0]},{main_line_start[1]} L{main_line_end[0]},{main_line_end[1]} M{left_aux_line_start[0]},{left_aux_line_start[1]} L{left_aux_line_end[0]},{left_aux_line_end[1]} M{right_aux_line_start[0]},{right_aux_line_start[1]} L{right_aux_line_end[0]},{right_aux_line_end[1]}"/>
3567
+ </g>\n""".replace(" ", "")
3568
+ dimension_svg += f""" <g font-size="29.1042" font-style="normal" stroke-opacity="1" fill="none" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="{dimension_line_thickness}" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})" stroke-linecap="round" stroke-linejoin="bevel">
3569
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{ending_coordinates[0]},{ending_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
3570
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L-15,-6 L-15,6 L0,0"/>
3571
+ </g>
3572
+ <g fill-opacity="1" font-size="29.1042" font-style="normal" stroke-opacity="1" fill="{colors['dimension_color']}" font-family="MS Shell Dlg 2" stroke="{colors['dimension_color']}" stroke-width="1" font-weight="400" transform="matrix(1,0,0,1,{starting_coordinates[0]},{starting_coordinates[1] + label_offset})" stroke-linecap="round" stroke-linejoin="bevel">
3573
+ <path fill-rule="evenodd" vector-effect="none" d="M0,0 L15,6 L15,-6 L0,0"/>
3574
+ </g>
3575
+ </g>\n""".replace(" ", "")
3576
+ return dimension_svg
3577
+
3578
+ projection_line_thickness = 4
3579
+ dimension_line_thickness = 1
3580
+ dimension_font_size = 30
3581
+ horizontal_offset = 75
3582
+ vertical_offset = 75
3583
+ increment = 50
3584
+ dimensions = data["dimensions"]
3585
+ shape_semi_height = dimensions['A'] / 2
3586
+ base_width, base_height = calculate_total_dimensions()
3587
+ head = f"""<svg xmlns:dc="http://purl.org/dc/elements/1.1/" baseProfile="tiny" xmlns:svg="http://www.w3.org/2000/svg" version="1.2" width="100%" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 {base_width} {base_height}" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" height="100%" xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
3588
+ <title>FreeCAD SVG Export</title>
3589
+ <desc>Drawing page: {view.Name} exported from FreeCAD document: {project_name}</desc>
3590
+ <defs/>
3591
+ <g id="{view.Name}" inkscape:label="TechDraw" inkscape:groupmode="layer">
3592
+ <g id="DrawingContent" fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel">""".replace(" ", "")
3593
+ projetion_head = f""" <g fill-opacity="1" font-size="29.1042" font-style="normal" fill="#ffffff" font-family="MS Shell Dlg 2" stroke="none" font-weight="400" transform="matrix(1,0,0,1,{view.X.Value},{1000 - view.Y.Value})">\n"""
3594
+ projetion_tail = """ </g>\n"""
3595
+ tail = """</g>
3596
+ </g>
3597
+ </svg>
3598
+ """.replace(" ", "")
3599
+ svgFile_data = ""
3600
+ svgFile_data += head
3601
+ svgFile_data += projetion_head
3602
+
3603
+ if view.Name == "TopView":
3604
+ m = piece.Placement.Matrix
3605
+ m.rotateZ(math.radians(90))
3606
+ piece.Placement.Matrix = m
3607
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 0., 1.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
3608
+ else:
3609
+ m = piece.Placement.Matrix
3610
+ m.rotateY(math.radians(90))
3611
+ piece.Placement.Matrix = m
3612
+ piece.Placement.move(FreeCAD.Vector(-dimensions["B"] / 2, 0, 0))
3613
+ svgFile_data += TechDraw.projectToSVG(piece.Shape, FreeCAD.Vector(0., 1., 0.)).replace("><", ">\n<").replace("<", " <").replace("stroke-width=\"0.7\"", f"stroke-width=\"{projection_line_thickness}\"").replace("#000000", colors['projection_color']).replace("rgb(0, 0, 0)", colors['projection_color'])
3614
+ svgFile_data += projetion_tail
3615
+ if view.Name == "TopView":
3616
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['B'] / 2, 0],
3617
+ ending_coordinates=[dimensions['B'] / 2, 0],
3618
+ dimension_type="DistanceX",
3619
+ dimension_label=f"B: {round(original_dimensions['B'], 2)} mm",
3620
+ label_offset=vertical_offset + shape_semi_height)
3621
+ vertical_offset += increment
3622
+ svgFile_data += create_dimension(starting_coordinates=[-dimensions['A'] / 2, 0],
3623
+ ending_coordinates=[dimensions['A'] / 2, 0],
3624
+ dimension_type="DistanceX",
3625
+ dimension_label=f"A: {round(original_dimensions['A'], 2)} mm",
3626
+ label_offset=vertical_offset + shape_semi_height)
3627
+ vertical_offset += increment
3628
+ else:
3629
+ svgFile_data += create_dimension(starting_coordinates=[0, -dimensions['C'] / 2],
3630
+ ending_coordinates=[0, dimensions['C'] / 2],
3631
+ dimension_type="DistanceY",
3632
+ dimension_label=f"C: {round(original_dimensions['C'], 2)} mm",
3633
+ label_offset=horizontal_offset)
3634
+
3635
+ svgFile_data += tail
3636
+
3637
+ if save_files:
3638
+ svgFile = open(f"{self.output_path}/{project_name}_{view.Name}.svg", "w")
3639
+ svgFile.write(svgFile_data)
3640
+ svgFile.close()
3641
+ return svgFile_data
3642
+
3643
+
3644
+
3645
+ if __name__ == '__main__': # pragma: no cover
3646
+
3647
+ with open(f'{os.path.dirname(os.path.abspath(__file__))}/../../MAS/data/core_shapes.ndjson', 'r') as f:
3648
+ for ndjson_line in f.readlines():
3649
+ data = json.loads(ndjson_line)
3650
+ if data["name"] == "PQ 40/40":
3651
+ # if data["family"] in ['pm']:
3652
+ # if data["family"] not in ['ui']:
3653
+ core = Builder().factory(data)
3654
+ core.get_core(data, None)
3655
+ # break