load objects before linking materials (minor change)
[blender-addons.git] / io_import_scene_dxf.py
blobf45d964d3789d3a121fa1a53ac406ee4f395215a
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 bl_info = {
20 "name": "Import Autocad DXF Format (.dxf)",
21 "author": "Thomas Larsson, Remigiusz Fiedler",
22 "version": (0, 1, 6),
23 "blender": (2, 63, 0),
24 "location": "File > Import > Autocad (.dxf)",
25 "description": "Import files in the Autocad DXF format (.dxf)",
26 "warning": "Under construction! Visit Wiki for details.",
27 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
28 "Scripts/Import-Export/DXF_Importer",
29 "tracker_url": "https://projects.blender.org/tracker/index.php?"
30 "func=detail&aid=23480",
31 "support": "OFFICIAL",
32 "category": "Import-Export",
35 """
36 Release note by migius (DXF support maintainer) 2011.01.02:
37 Script supports only a small part of DXF specification:
38 - imports LINE, ARC, CIRCLE, ELLIPSE, SOLID, TRACE, POLYLINE, LWPOLYLINE
39 - imports TEXT, MTEXT
40 - supports 3d-rotation of entities (210 group)
41 - supports THICKNESS for SOLID, TRACE, LINE, ARC, CIRCLE, ELLIPSE
42 - ignores WIDTH, THICKNESS, BULGE in POLYLINE/LWPOLYLINE
43 - ignores face-data in POLYFACE / POLYMESH
44 - ignores TEXT 2d-rotation
45 - ignores hierarchies (BLOCK, INSERT, GROUP)
46 - ignores LAYER
47 - ignores COLOR, LINEWIDTH, LINESTYLE
49 This script is a temporary solution.
50 No functionality improvements are planed for this version.
51 The advanced importer from 2.49 will replace it in the future.
53 Installation:
54 Place this file to Blender addons directory
55 (on Windows it is %Blender_directory%\2.53\scripts\addons\)
56 The script must be activated in "Addons" tab (user preferences).
57 Access it from File > Import menu.
59 History:
60 ver 0.1.6 - 2012.01.03 by migius and trumanblending for r.42615
61 - modified for recent changes to matrix indexing
62 ver 0.1.5 - 2011.02.05 by migius for r.34661
63 - changed support level to OFFICIAL
64 - fixed missing last point at building Mesh-ARCs (by pildanovak)
65 - fixed for changes in API and mathutils by campbell
66 ver 0.1.4 - 2011.01.13 by migius
67 - modified for latest API in rev.34300 (by Filiciss Muhgue)
68 ver 0.1.3 - 2011.01.02 by migius
69 - added draw curves as sequence for "Draw_as_Curve"
70 - added toggle "Draw as one" as user preset in UI
71 - added draw POINT as mesh-vertex
72 - added draw_THICKNESS for LINE, ARC, CIRCLE, ELLIPSE, LWPOLYLINE and POLYLINE
73 - added draw_THICKNESS for SOLID, TRACE
74 ver 0.1.2 - 2010.12.27 by migius
75 - added draw() for TRACE
76 - fixed wrong vertex order in SOLID
77 - added CIRCLE resolution as user preset in UI
78 - added closing segment for circular LWPOLYLINE and POLYLINE
79 - fixed registering for 2.55beta
80 ver 0.1.1 - 2010.09.07 by migius
81 - fixed dxf-file names recognition limited to ".dxf"
82 - fixed registering for 2.53beta
83 ver 0.1 - 2010.06.10 by Thomas Larsson
84 """
86 __version__ = '.'.join([str(s) for s in bl_info['version']])
88 import os
89 import codecs
90 import math
91 from math import sin, cos, radians
92 import bpy
93 from mathutils import Vector, Matrix
96 # Global flags
99 T_Merge = 0x01
100 T_NewScene = 0x02
101 T_Curves = 0x04
102 T_DrawOne = 0x08
103 T_Debug = 0x10
104 T_Verbose = 0x20
105 T_ThicON = 0x40
107 toggle = T_Merge | T_NewScene | T_DrawOne | T_ThicON
108 theCircleRes = 32
109 theMergeLimit = 1e-4
112 # class CSection:
115 class CSection:
116 type = None
118 def __init__(self):
119 self.data = []
121 def display(self):
122 print("Section", self.type)
123 for datum in self.data:
124 datum.display()
127 # class CTable:
130 class CTable:
131 def __init__(self):
132 self.type = None
133 self.name = None
134 self.handle = None
135 self.owner = None
136 self.subclass = None
137 self.nEntries = 0
138 def display(self):
139 print("Table %s %s %s %s %s %d" % (self.type, self.name, self.handle, self.owner, self.subclass, self.nEntries))
142 # class CEntity:
144 class CEntity:
145 def __init__(self, typ, drawtype):
146 self.type = typ
147 self.drawtype = drawtype
148 self.handle = None
149 self.owner = None
150 self.subclass = None
151 self.layer = 0
152 self.color = 0
153 self.invisible = 0
154 self.linetype_name = ''
155 self.linetype_scale = 1.0
156 self.paperspace = 0
157 #self.normal = Vector((0,0,1))
159 def display(self):
160 print("Entity %s %s %s %s %s %s %x" %
161 (self.type, self.handle, self.owner, self.subclass, self.layer, self.color, self.invisible))
163 def build(self, vn=0):
164 global toggle
165 if toggle & T_Debug:
166 raise NameError("Warning: can not build - unsupported entity type: %s" % self.type)
167 return(([], [], [], vn))
169 def draw(self):
170 global toggle
171 if toggle & T_Debug:
172 raise NameError("Warning: can not draw - unsupported entity type: %s" % self.type)
173 return
176 DxfCommonAttributes = {
177 5 : 'handle',
178 6 : 'linetype_name',
179 8 : 'layer',
180 48 : 'linetype_scale',
181 60 : 'invisible',
182 62 : 'color',
183 67 : 'paperspace',
184 100 : 'subclass',
185 330 : 'owner',
186 360 : 'owner',
190 # class C3dFace(CEntity):
191 # 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
192 # 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
193 # 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
194 # 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
195 # 70 : 'flags',
198 class C3dFace(CEntity):
199 def __init__(self):
200 CEntity.__init__(self, '3DFACE', 'Mesh')
201 self.point0 = Vector()
202 self.point1 = Vector()
203 self.point2 = Vector()
204 self.point3 = Vector()
206 def display(self):
207 CEntity.display(self)
208 print(self.point0)
209 print(self.point1)
210 print(self.point2)
211 print(self.point3)
213 def build(self, vn=0):
214 verts = [self.point0, self.point1, self.point2]
215 if self.point3 == Vector((0,0,0)) or self.point2 == self.point3:
216 faces = [(vn+0, vn+1, vn+2)]
217 vn += 3
218 else:
219 verts.append( self.point3 )
220 faces = [(vn+0, vn+1, vn+2, vn+3)]
221 vn += 4
222 return((verts, [], faces, vn))
225 # class C3dSolid(CEntity):
226 # 1 : 'data', 3 : 'more', 70 : 'version',
229 class C3dSolid(CEntity):
230 def __init__(self):
231 CEntity.__init__(self, '3DSOLID', 'Mesh')
232 self.data = None
233 self.more = None
234 self.version = 0
237 # class CAcadProxyEntity(CEntity):
238 # 70 : 'format',
239 # 90 : 'id', 91 : 'class', 92 : 'graphics_size', 93 : 'entity_size', 95: 'format',
240 # 310 : 'data', 330 : 'id1', 340 : 'id2', 350 : 'id3', 360 : 'id4',
243 class CAcadProxyEntity(CEntity):
244 def __init__(self):
245 CEntity.__init__(self, 'ACAD_PROXY_ENTITY', None)
249 # class CArc(CEntity):
250 # 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
251 # 40 : 'radius',
252 # 50 : 'start_angle', 51 : 'end_angle'
255 class CArc(CEntity):
256 def __init__(self):
257 CEntity.__init__(self, 'ARC', 'Mesh')
258 self.center = Vector()
259 self.radius = 0.0
260 self.start_angle = 0.0
261 self.end_angle = 0.0
262 self.thickness = 0.0
263 self.normal = Vector((0,0,1))
265 def display(self):
266 CEntity.display(self)
267 print(self.center)
268 print("%.4f %.4f %.4f " % (self.radius, self.start_angle, self.end_angle))
270 def build(self, vn=0):
271 start, end = self.start_angle, self.end_angle
272 if end > 360: end = end % 360.0
273 if end < start: end +=360.0
274 # angle = end - start # UNUSED
276 deg2rad = math.pi/180.0
277 start *= deg2rad
278 end *= deg2rad
279 dphi = end - start
280 phi0 = start
281 w = dphi/theCircleRes
282 r = self.radius
283 center = self.center
284 v0 = vn
285 points = []
286 edges, faces = [], []
287 for n in range(theCircleRes + 1):
288 s = math.sin(n*w + phi0)
289 c = math.cos(n*w + phi0)
290 v = center + Vector((r*c, r*s, 0.0))
291 points.append(v)
292 pn = len(points)
293 thic = self.thickness
294 t_vector = Vector((0, 0, thic))
295 if thic != 0 and (toggle & T_ThicON):
296 thic_points = [v + t_vector for v in points]
297 if thic < 0.0:
298 thic_points.extend(points)
299 points = thic_points
300 else:
301 points.extend(thic_points)
302 faces = [(v0+nr+0,v0+nr+1,v0+pn+nr+1,v0+pn+nr+0) for nr in range(pn)]
303 faces.pop()
304 self.drawtype = 'Mesh'
305 vn += 2*pn
306 else:
307 edges = [(v0+nr+0,v0+nr+1) for nr in range(pn)]
308 edges.pop()
309 vn += pn
311 if self.normal!=Vector((0,0,1)):
312 ma = getOCS(self.normal)
313 if ma:
314 #ma.invert()
315 points = [ma * v for v in points]
316 #print ('arc vn=', vn)
317 #print ('faces=', len(faces))
318 return ((points, edges, faces, vn))
321 # class CArcAlignedText(CEntity):
322 # 1 : 'text', 2 : 'font', 3 : 'bigfont', 7 : 'style',
323 # 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
324 # 40 : 'radius', 41 : 'width', 42 : 'height', 43 : 'spacing',
325 # 44 : 'offset', 45 : 'right_offset', 46 : 'left_offset',
326 # 50 : 'start_angle', 51 : 'end_angle',
327 # 70 : 'order', 71 : 'direction', 72 : 'alignment', 73 : 'side',
328 # 74 : 'bold', 75 : 'italic', 76 : 'underline',
329 # 77 : 'character_set', 78 : 'pitch', 79 'fonttype',
330 # 90 : 'color',
331 # 280 : 'wizard', 330 : 'id'
334 class CArcAlignedText(CEntity):
335 def __init__(self):
336 CEntity.__init__(self, 'ARCALIGNEDTEXT', 'Mesh')
337 self.text = ""
338 self.style = ""
339 self.center = Vector()
340 self.radius = 0.0
341 self.width = 1.0
342 self.height = 1.0
343 self.spacing = 1.0
344 self.offset = 0.0
345 self.right_offset = 0.0
346 self.left_offset = 0.0
347 self.start_angle = 0.0
348 self.end_angle = 0.0
349 self.order = 0
350 self.directions = 0
351 self.alignment = 0
352 self.side = 0
353 self.bold = 0
354 self.italic = 0
355 self.underline = 0
356 self.character_set = 0
357 self.pitch = 0
358 self.fonttype = 0
359 self.color = 0
360 self.wizard = None
361 self.id = None
362 self.normal = Vector((0,0,1))
366 # class CAttdef(CEntity):
367 # 1 : 'text', 2 : 'tag', 3 : 'prompt', 7 : 'style',
368 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
369 # 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
370 # 40 : 'height', 41 : 'x_scale',
371 # 50 : 'rotation_angle', 51 : 'oblique_angle',
372 # 70 : 'flags', 71 : 'text_generation_flags',
373 # 72 : 'horizontal_justification', 74 : 'vertical_justification',
376 class CAttdef(CEntity):
377 def __init__(self):
378 CEntity.__init__(self, 'ATTDEF', None)
379 self.value = ""
380 self.tag = ""
381 self.prompt = ""
382 self.style = ""
383 self.insertion_point = Vector()
384 self.alignment_point = Vector()
385 self.height = 1.0
386 self.x_scale = 1.0
387 self.rotation_angle = 0.0
388 self.oblique_angle = 0.0
389 self.flags = 0
390 self.text_generation_flags = 0
391 self.horizontal_justification = 0.0
392 self.vertical_justification = 0.0
393 self.normal = Vector((0,0,1))
395 def draw(self):
396 drawText(self.text, self.insertion_point, self.height, self.x_scale, self.rotation_angle, self.oblique_angle, self.normal)
397 return
400 # class CAttrib(CEntity):
401 # 1 : 'text', 2 : 'tag', 3 : 'prompt', 7 : 'style',
402 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
403 # 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
404 # 40 : 'height', 41 : 'x_scale',
405 # 50 : 'rotation_angle', 51 : 'oblique_angle',
406 # 70 : 'flags', 73 : 'length',
407 # 71 : 'text_generation_flags', 72 : 'horizontal_justification', 74 : 'vertical_justification',
410 class CAttrib(CEntity):
411 def __init__(self):
412 CEntity.__init__(self, 'ATTRIB', None)
413 self.text = ""
414 self.tag = ""
415 self.prompt = ""
417 self.style = ""
418 self.insertion_point = Vector()
419 self.alignment_point = Vector()
420 self.height = 1.0
421 self.x_scale = 1.0
422 self.rotation_angle = 0.0
423 self.oblique_angle = 0.0
424 self.flags = 0
425 self.length = 1.0
426 self.text_generation_flags = 0
427 self.horizontal_justification = 0.0
428 self.vertical_justification = 0.0
429 self.normal = Vector((0,0,1))
431 def draw(self):
432 drawText(self.text, self.insertion_point, self.height, self.x_scale, self.rotation_angle, self.oblique_angle, self.normal)
433 return
437 # class CBlock(CEntity):
438 # 1 : 'xref', 2 : 'name', 3 : 'also_name',
439 # 10 : 'base_point.x', 20 : 'base_point.y', 30 : 'base_point.z',
440 # 40 : 'size', 41 : 'x_scale',
441 # 50 : 'rotation_angle', 51 : 'oblique_angle',
442 # 70 : 'flags',
445 class CBlock(CEntity):
446 def __init__(self):
447 CEntity.__init__(self, 'BLOCK', None)
448 self.xref = ""
449 self.name = ""
450 self.also_name = ""
451 self.base_point = Vector()
452 self.size = 1.0
453 self.x_scale = 1.0
454 self.rotation_angle = 0.0
455 self.oblique_angle = 0.0
456 self.flags = 0
457 self.normal = Vector((0,0,1))
459 def display(self):
460 CEntity.display(self)
461 print("%s %s %s " % (self.xref, self.name, self.also_name))
462 print(self.base_point)
464 def draw(self):
465 # Todo
466 return
469 # class CCircle(CEntity):
470 # 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
471 # 40 : 'radius'
474 class CCircle(CEntity):
475 def __init__(self):
476 CEntity.__init__(self, 'CIRCLE', 'Mesh')
477 self.center = Vector()
478 self.radius = 0.0
479 self.thickness = 0.0
480 self.normal = Vector((0,0,1))
482 def display(self):
483 CEntity.display(self)
484 print(self.center)
485 print("%.4f" % self.radius)
487 def build(self, vn=0):
488 w = 2*math.pi/theCircleRes
489 r = self.radius
490 center = self.center
491 points = []
492 edges, faces = [], []
493 v0 = vn
494 for n in range(theCircleRes):
495 s = math.sin(n*w)
496 c = math.cos(n*w)
497 v = center + Vector((r*c, r*s, 0))
498 points.append(v)
500 pn = len(points)
501 thic = self.thickness
502 t_vector = Vector((0, 0, thic))
503 if thic != 0 and (toggle & T_ThicON):
504 thic_points = [v + t_vector for v in points]
505 if thic < 0.0:
506 thic_points.extend(points)
507 points = thic_points
508 else:
509 points.extend(thic_points)
510 faces = [(v0+nr,v0+nr+1,pn+v0+nr+1,pn+v0+nr) for nr in range(pn)]
511 nr = pn -1
512 faces[-1] = (v0+nr,v0,pn+v0,pn+v0+nr)
513 self.drawtype = 'Mesh'
514 vn += 2*pn
515 else:
516 edges = [(v0+nr,v0+nr+1) for nr in range(pn)]
517 nr = pn -1
518 edges[-1] = (v0+nr,v0)
519 vn += pn
520 if self.normal!=Vector((0,0,1)):
521 ma = getOCS(self.normal)
522 if ma:
523 #ma.invert()
524 points = [ma * v for v in points]
525 #print ('cir vn=', vn)
526 #print ('faces=',len(faces))
527 return( (points, edges, faces, vn) )
530 # class CDimension(CEntity):
531 # 1 : 'text', 2 : 'name', 3 : 'style',
532 # 10 : 'def_point.x', 20 : 'def_point.y', 30 : 'def_point.z',
533 # 11 : 'mid_point.x', 21 : 'mid_point.y', 31 : 'mid_point.z',
534 # 12 : 'vector.x', 22 : 'vector.y', 32 : 'vector.z',
535 # 13 : 'def_point2.x', 23 : 'def_point2.y', 33 : 'def_point2.z',
536 # 14 : 'vector2.x', 24 : 'vector2.y', 34 : 'vector2.z',
537 # 15 : 'vector3.x', 25 : 'vector3.y', 35 : 'vector3.z',
538 # 16 : 'vector4.x', 26 : 'vector4.y', 36 : 'vector4.z',
539 # 70 : 'dimtype',
542 class CDimension(CEntity):
543 def __init__(self):
544 CEntity.__init__(self, 'DIMENSION', None)
545 self.text = ""
546 self.name = ""
547 self.style = ""
548 self.def_point = Vector()
549 self.mid_point = Vector()
550 self.vector = Vector()
551 self.def_point2 = Vector()
552 self.vector2 = Vector()
553 self.vector3 = Vector()
554 self.vector4 = Vector()
555 self.dimtype = 0
556 self.normal = Vector((0,0,1))
558 def draw(self):
559 return
562 # class CEllipse(CEntity):
563 # 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
564 # 11 : 'end_point.x', 21 : 'end_point.y', 31 : 'end_point.z',
565 # 40 : 'ratio', 41 : 'start', 42 : 'end',
568 class CEllipse(CEntity):
569 def __init__(self):
570 CEntity.__init__(self, 'ELLIPSE', 'Mesh')
571 self.center = Vector()
572 self.end_point = Vector()
573 self.ratio = 1.0
574 self.start = 0.0
575 self.end = 2*math.pi
576 self.thickness = 0.0
577 self.normal = Vector((0,0,1))
579 def display(self):
580 CEntity.display(self)
581 print(self.center)
582 print("%.4f" % self.ratio)
584 def build(self, vn=0):
585 dphi = (self.end - self.start)
586 phi0 = self.start
587 w = dphi/theCircleRes
588 r = self.end_point.length
589 f = self.ratio
590 a = self.end_point.x/r
591 b = self.end_point.y/r
592 center = self.center
593 v0 = vn
594 points = []
595 edges, faces = [], []
596 for n in range(theCircleRes):
597 x = r*math.sin(n*w + phi0)
598 y = f*r*math.cos(n*w + phi0)
599 v = (center.x - a*x + b*y, center.y - a*y - b*x, center.z)
600 points.append(v)
602 pn = len(points)
603 thic = self.thickness
604 t_vector = Vector((0, 0, thic))
605 if thic != 0 and (toggle & T_ThicON):
606 thic_points = [v + t_vector for v in points]
607 if thic < 0.0:
608 thic_points.extend(points)
609 points = thic_points
610 else:
611 points.extend(thic_points)
612 faces = [(v0+nr,v0+nr+1,pn+v0+nr+1,pn+v0+nr) for nr in range(pn)]
613 nr = pn -1
614 faces[-1] = (v0+nr,v0,pn+v0,pn+v0+nr)
615 #self.drawtype = 'Mesh'
616 vn += 2*pn
617 else:
618 edges = [(v0+nr,v0+nr+1) for nr in range(pn)]
619 nr = pn -1
620 edges[-1] = (v0+nr,v0)
621 vn += pn
624 if thic != 0 and (toggle & T_ThicON):
625 pass
626 if self.normal!=Vector((0,0,1)):
627 ma = getOCS(self.normal)
628 if ma:
629 #ma.invert()
630 points = [ma * v for v in points]
631 return ((points, edges, faces, vn))
634 # class CHatch(CEntity):
635 # 2 : 'pattern',
636 # 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
637 # 41 : 'scale', 47 : 'pixelsize', 52 : 'angle',
638 # 70 : 'fill', 71 : 'associativity', 75: 'style', 77 : 'double',
639 # 78 : 'numlines', 91 : 'numpaths', 98 : 'numseeds',
642 class CHatch(CEntity):
643 def __init__(self):
644 CEntity.__init__(self, 'HATCH', None)
645 self.pattern = 0
646 self.point = Vector()
647 self.scale = 1.0
648 self.pixelsize = 1.0
649 self.angle = 0.0
650 self.fill = 0
651 self.associativity = 0
652 self.style = 0
653 self.double = 0
654 self.numlines = 0
655 self.numpaths = 0
656 self.numseeds = 0
657 self.normal = Vector((0,0,1))
660 # class CImage(CEntity):
661 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
662 # 11 : 'u_vector.x', 21 : 'u_vector.y', 31 : 'u_vector.z',
663 # 12 : 'v_vector.x', 22 : 'v_vector.y', 32 : 'v_vector.z',
664 # 13 : 'size.x', 23 : 'size.y', 33 : 'size.z',
665 # 14 : 'clip.x', 24 : 'clip.y', 34 : 'clip.z',
666 # 70 : 'display', 71 : 'cliptype',
667 # 90 : 'version',
668 # 280 : 'clipstate', 281 : 'brightness', 282 : 'contrast', 283 : 'fade',
669 # 340 : 'image', 360 : 'reactor'
672 class CImage(CEntity):
673 def __init__(self):
674 CEntity.__init__(self, 'IMAGE', None)
675 self.insertion_point = Vector()
676 self.u_vector = Vector()
677 self.v_vector = Vector()
678 self.size = Vector()
679 self.clip = Vector()
680 self.display = 0
681 self.cliptype = 0
682 self.version = 1
683 self.clipstate = 0
684 self.brightness = 0
685 self.constrast = 0
686 self.fade = 0
687 self.image = None
688 self.reactor = None
689 self.normal = Vector((0,0,1))
692 # class CInsert(CEntity):
693 # 1 : 'attributes_follow', 2 : 'name',
694 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
695 # 41 : 'x_scale', 42 : 'y_scale', 43 : 'z_scale',
696 # 44 : 'column_spacing', 45 : 'row_spacing',
697 # 50 : 'rotation_angle', 66 : 'attributes_follow',
698 # 70 : 'column_count', 71 : 'row_count',
701 class CInsert(CEntity):
702 def __init__(self):
703 CEntity.__init__(self, 'INSERT', None)
704 self.attributes_follow = 1
705 self.name = ""
706 self.insertion_point = Vector()
707 self.x_scale = 1.0
708 self.y_scale = 1.0
709 self.z_scale = 1.0
710 self.column_spacing = 1.0
711 self.row_spacing = 1.0
712 self.rotation_angle = 0.0
713 self.column_count = 1
714 self.row_count = 1
715 self.attributes_follow = 0
716 self.normal = Vector((0,0,1))
718 def display(self):
719 CEntity.display(self)
720 print(self.insertion_point)
722 def draw(self):
723 # Todo
724 return
727 # class CLeader(CEntity):
728 # 3 : 'style',
729 # 10 : ['new_vertex(data)'], 20 : 'vertex.y', 30 : 'vertex.z',
730 # 40 : 'height', 41 : 'width',
731 # 71 : 'arrowhead', 72 : 'pathtype', 73 : 'creation',
732 # 74 : 'hookdir', 75 : 'hookline', 76 : 'numverts', 77 : 'color',
733 # 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
734 # 211 : 'horizon.x', 221 : 'horizon.y', 231 : 'horizon.z',
735 # 212 : 'offset_ins.x', 222 : 'offset_ins.y', 232 : 'offset_ins.z',
736 # 213 : 'offset_ann.x', 223 : 'offset_ann.y', 233 : 'offset_ann.z',
739 class CLeader(CEntity):
740 def __init__(self):
741 CEntity.__init__(self, 'LEADER', 'Mesh')
742 self.style = ""
743 self.vertex = None
744 self.verts = []
745 self.height = 1.0
746 self.width = 1.0
747 self.arrowhead = 0
748 self.pathtype = 0
749 self.creation = 0
750 self.hookdir = 0
751 self.hookline = 0
752 self.numverts = 0
753 self.color = 0
754 self.normal = Vector((0,0,1))
755 self.horizon = Vector()
756 self.offset_ins = Vector()
757 self.offset_ann = Vector()
759 def new_vertex(self, data):
760 self.vertex = Vector()
761 self.vertex.x = data
762 self.verts.append(self.vertex)
764 def build(self, vn=0):
765 edges = []
766 for v in self.verts:
767 edges.append((vn, vn+1))
768 vn += 1
769 edges.pop()
770 return (self.verts, edges, [], vn)
772 # class CLwPolyLine(CEntity):
773 # 10 : ['new_vertex(data)'], 20 : 'vertex.y', 30 : 'vertex.z',
774 # 38 : 'elevation', 39 : 'thickness',
775 # 40 : 'start_width', 41 : 'end_width', 42 : 'bulge', 43 : 'constant_width',
776 # 70 : 'flags', 90 : 'numverts'
779 class CLWPolyLine(CEntity):
780 def __init__(self):
781 CEntity.__init__(self, 'LWPOLYLINE', None)
782 self.vertex = None
783 self.verts = []
784 self.elevation = 0
785 self.thickness = 0.0
786 self.start_width = 0.0
787 self.end_width = 0.0
788 self.bulge = 0.0
789 self.constant_width = 0.0
790 self.flags = 0
791 self.numverts = 0
792 self.normal = Vector((0,0,1))
794 def new_vertex(self, data):
795 self.vertex = Vector()
796 self.vertex.x = data
797 self.verts.append(self.vertex)
799 def build(self, vn=0):
800 edges = []
801 v_start = vn
802 for v in self.verts:
803 edges.append((vn, vn+1))
804 vn += 1
805 if self.flags & PL_CLOSED:
806 edges[-1] = (vn-1, v_start)
807 else:
808 edges.pop()
809 verts = self.verts
810 if self.normal!=Vector((0,0,1)):
811 ma = getOCS(self.normal)
812 if ma:
813 #ma.invert()
814 verts = [ma * v for v in verts]
815 return (verts, edges, [], vn-1)
818 # class CLine(CEntity):
819 # 10 : 'start_point.x', 20 : 'start_point.y', 30 : 'start_point.z',
820 # 11 : 'end_point.x', 21 : 'end_point.y', 31 : 'end_point.z',
821 # 39 : 'thickness',
824 class CLine(CEntity):
825 def __init__(self):
826 CEntity.__init__(self, 'LINE', 'Mesh')
827 self.start_point = Vector()
828 self.end_point = Vector()
829 self.thickness = 0.0
830 self.normal = Vector((0,0,1))
832 def display(self):
833 CEntity.display(self)
834 print(self.start_point)
835 print(self.end_point)
837 def build(self, vn=0):
838 points = [self.start_point, self.end_point]
839 faces, edges = [], []
840 n = vn
841 thic = self.thickness
842 if thic != 0 and (toggle & T_ThicON):
843 t_vector = thic * self.normal
844 #print 'deb:thic_vector: ', t_vector #---------------------
845 points.extend([v + t_vector for v in points])
846 faces = [[0+n, 1+n, 3+n, 2+n]]
847 self.drawtype = 'Mesh'
848 else:
849 edges = [[0+n, 1+n]]
850 vn +=2
851 return((points, edges, faces, vn))
853 # class CMLine(CEntity):
854 # 10 : 'start_point.x', 20 : 'start_point.y', 30 : 'start_point.z',
855 # 11 : ['new_vertex(data)'], 21 : 'vertex.y', 31 : 'vertex.z',
856 # 12 : ['new_seg_dir(data)'], 22 : 'seg_dir.y', 32 : 'seg_dir.z',
857 # 13 : ['new_miter_dir(data)'], 23 : 'miter_dir.y', 33 : 'miter_dir.z',
858 # 40 : 'scale', 41 : 'elem_param', 42 : 'fill_param',
859 # 70 : 'justification', 71 : 'flags'
860 # 72 : 'numverts', 73 : 'numelems', 74 : 'numparam', 75 : 'numfills',
861 # 340 : 'id'
864 class CMLine(CEntity):
865 def __init__(self):
866 CEntity.__init__(self, 'MLINE', None)
867 self.start_point = Vector()
868 self.vertex = None
869 self.seg_dir = None
870 self.miter_dir = None
871 self.verts = []
872 self.seg_dirs = []
873 self.miter_dirs = []
874 self.scale = 1.0
875 self.elem_param = 0
876 self.fill_param = 0
877 self.justification = 0
878 self.flags = 0
879 self.numverts = 0
880 self.numelems = 0
881 self.numparam = 0
882 self.numfills = 0
883 self.id = 0
884 self.normal = Vector((0,0,1))
886 def new_vertex(self, data):
887 self.vertex = Vector()
888 self.vertex.x = data
889 self.verts.append(self.vertex)
891 def new_seg_dir(self, data):
892 self.seg_dir = Vector()
893 self.seg_dir.x = data
894 self.seg_dirs.append(self.seg_dir)
896 def new_miter_dir(self, data):
897 self.miter_dir = Vector()
898 self.miter_dir.x = data
899 self.miter_dirs.append(self.miter_dir)
904 # class CMText(CText):
905 # 1 : 'text', 3: 'more_text', 7 : 'style',
906 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
907 # 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
908 # 40 : 'nominal_height', 41 : 'reference_width', 42: 'width', 43 : 'height', 44 : 'line_spacing',
909 # 50 : 'rotation_angle',
910 # 71 : 'attachment_point', 72 : 'drawing_direction', 73 : 'spacing_style',
913 class CMText(CEntity):
914 def __init__(self):
915 CEntity.__init__(self, 'MTEXT', 'Text')
916 self.text = ""
917 self.more_text = ""
918 self.style = ""
919 self.insertion_point = Vector()
920 self.alignment_point = Vector()
921 self.nominal_height = 1.0
922 self.reference_width = 1.0
923 self.width = 1.0
924 self.height = 1.0
925 self.rotation_angle = 0.0
926 self.attachment_point = 0
927 self.drawing_direction = 0
928 self.spacing_style = 0
929 self.normal = Vector((0,0,1))
931 def display(self):
932 CEntity.display(self)
933 print("%s %s" % (self.text, self.style))
934 print('MTEXTinsertion_point=',self.insertion_point)
935 print('MTEXTalignment_point=',self.alignment_point)
937 def draw(self):
938 drawText(self.text, self.insertion_point, self.height, self.width, self.rotation_angle, 0.0, self.normal)
939 return
942 # class CPoint(CEntity):
943 # 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
944 # 39 : 'thickness', 50 : 'orientation'
947 class CPoint(CEntity):
948 def __init__(self):
949 CEntity.__init__(self, 'POINT', 'Mesh')
950 self.point = Vector()
951 self.thickness = 0.0
952 self.orientation = 0.0
954 def display(self):
955 CEntity.display(self)
956 print(self.point)
957 print("%.4f" % self.orientation)
959 def build(self, vn=0):
960 # draw as mesh-vertex
961 verts = [self.point]
962 return((verts, [], [], vn+1))
964 def draw(self):
965 #todo
966 # draw as empty-object
967 # loc = self.point # UNUSED
968 #bpy.ops.object.new('DXFpoint')
969 pass
972 # class CPolyLine(CEntity):
973 # 1 : 'verts_follow', 2 : 'name',
974 # 10 : 'elevation.x', 20 : 'elevation.y', 30 : 'elevation.z',
975 # 40 : 'start_width', 41 : 'end_width',
976 # 66 : 'verts_follow_flag',
977 # 70 : 'flags', 71 : 'row_count', 72 : 'column_count',
978 # 73 : 'row_density', 74 : 'column_density', 75 : 'linetype',
981 class CPolyLine(CEntity):
982 def __init__(self):
983 CEntity.__init__(self, 'POLYLINE', 'Mesh')
984 self.verts = []
985 self.verts_follow = 1
986 self.name = ""
987 self.elevation = Vector()
988 self.thickness = 0.0
989 self.start_width = 0.0
990 self.end_width = 0.0
991 self.verts_follow_flags = 0
992 self.flags = 0
993 self.row_count = 1
994 self.column_count = 1
995 self.row_density = 1.0
996 self.column_density = 1.0
997 self.linetype = 1
998 self.normal = Vector((0,0,1))
1000 def display(self):
1001 CEntity.display(self)
1002 print("VERTS")
1003 for v in self.verts:
1004 print(v.location)
1005 print("END VERTS")
1007 def build(self, vn=0):
1008 verts = []
1009 lines = []
1010 v_start = vn
1011 for vert in self.verts:
1012 verts.append(vert.location)
1013 lines.append((vn, vn+1))
1014 vn += 1
1015 if self.flags & PL_CLOSED:
1016 lines[-1] = (vn-1, v_start)
1017 else:
1018 lines.pop()
1019 if self.normal!=Vector((0,0,1)):
1020 ma = getOCS(self.normal)
1021 if ma:
1022 verts = [ma * v for v in verts]
1023 return((verts, lines, [], vn-1))
1026 # class CShape(CEntity):
1027 # 2 : 'name',
1028 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1029 # 39 : 'thickness',
1030 # 40 : 'size', 41 : 'x_scale',
1031 # 50 : 'rotation_angle', 51 : 'oblique_angle',
1034 class CShape(CEntity):
1035 def __init__(self):
1036 CEntity.__init__(self, 'SHAPE', None)
1037 self.name = ""
1038 self.insertion_point = Vector()
1039 self.thickness = 0.0
1040 self.size = 1.0
1041 self.x_scale = 1.0
1042 self.rotation_angle = 0.0
1043 self.oblique_angle = 0.0
1045 def display(self):
1046 CEntity.display(self)
1047 print("%s" % (self.name))
1048 print(self.insertion_point)
1051 # class CSpline(CEntity):
1052 # 10 : ['new_control_point(data)'], 20 : 'control_point.y', 30 : 'control_point.z',
1053 # 11 : ['new_fit_point(data)'], 21 : 'fit_point.y', 31 : 'fit_point.z',
1054 # 40 : ['new_knot_value(data)'],
1055 # 12 : 'start_tangent.x', 22 : 'start_tangent.y', 32 : 'start_tangent.z',
1056 # 13 : 'end_tangent.x', 23 : 'end_tangent.y', 33 : 'end_tangent.z',
1057 # 41 : 'weight', 42 : 'knot_tol', 43 : 'control_point_tol', 44 : 'fit_tol',
1058 # 70 : 'flag', 71 : 'degree',
1059 # 72 : 'num_knots', 73 : 'num_control_points', 74 : 'num_fit_points',
1060 # 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1063 class CSpline(CEntity):
1064 def __init__(self):
1065 CEntity.__init__(self, 'SPLINE', 'Mesh')
1066 self.control_points = []
1067 self.fit_points = []
1068 self.knot_values = []
1069 self.control_point = None
1070 self.fit_point = None
1071 self.knot_value = None
1072 self.start_tangent = Vector()
1073 self.end_tangent = Vector()
1074 self.weight = 1.0
1075 self.knot_tol = 1e-6
1076 self.control_point_tol = 1e-6
1077 self.fit_tol = 1e-6
1078 self.flag = 0
1079 self.degree = 3
1080 self.num_knots = 0
1081 self.num_control_points = 0
1082 self.num_fit_points = 0
1083 self.thickness = 0.0
1084 self.normal = Vector((0,0,1))
1086 def new_control_point(self, data):
1087 self.control_point = Vector()
1088 self.control_point.x = data
1089 self.control_points.append(self.control_point)
1091 def new_fit_point(self, data):
1092 self.fit_point = Vector()
1093 self.fit_point.x = data
1094 self.fit_points.append(self.fit_point)
1096 def new_knot_value(self, data):
1097 self.knot_value = data
1098 self.knot_values.append(self.knot_value)
1100 def display(self):
1101 #not testet yet (migius)
1102 CEntity.display(self)
1103 print("CONTROL")
1104 for p in self.control_points:
1105 print(p)
1106 print("FIT")
1107 for p in self.fit_points:
1108 print(p)
1109 print("KNOT")
1110 for v in self.knot_values:
1111 print(v)
1113 def build(self, vn=0):
1114 verts = []
1115 lines = []
1116 for vert in self.control_points:
1117 verts.append(vert)
1118 lines.append((vn, vn+1))
1119 vn += 1
1120 lines.pop()
1121 return((verts, lines, [], vn))
1125 # class CSolid(CEntity):
1126 # 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
1127 # 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
1128 # 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
1129 # 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
1130 # 39 : 'thickness',
1133 class CSolid(CEntity):
1134 def __init__(self):
1135 CEntity.__init__(self, 'SOLID', 'Mesh')
1136 self.point0 = Vector()
1137 self.point1 = Vector()
1138 self.point2 = Vector()
1139 self.point3 = Vector()
1140 self.normal = Vector((0,0,1))
1141 self.thickness = 0.0
1143 def display(self):
1144 CEntity.display(self)
1145 print(self.point0)
1146 print(self.point1)
1147 print(self.point2)
1148 print(self.point3)
1150 def build(self, vn=0):
1151 points, edges, faces = [],[],[]
1152 if self.point2 == self.point3:
1153 points = [self.point0, self.point1, self.point2]
1154 else:
1155 points = [self.point0, self.point1, self.point2, self.point3]
1156 pn = len(points)
1157 v0 = vn
1159 thic = self.thickness
1160 t_vector = Vector((0, 0, thic))
1161 if thic != 0 and (toggle & T_ThicON):
1162 thic_points = [v + t_vector for v in points]
1163 if thic < 0.0:
1164 thic_points.extend(points)
1165 points = thic_points
1166 else:
1167 points.extend(thic_points)
1169 if pn == 4:
1170 faces = [[0,1,3,2], [4,6,7,5], [0,4,5,1],
1171 [1,5,7,3], [3,7,6,2], [2,6,4,0]]
1172 elif pn == 3:
1173 faces = [[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]]
1174 elif pn == 2: faces = [[0,1,3,2]]
1175 vn += 2*pn
1176 else:
1177 if pn == 4: faces = [[0,2,3,1]]
1178 elif pn == 3: faces = [[0,2,1]]
1179 elif pn == 2:
1180 edges = [[0,1]]
1181 self.drawtype = 'Mesh'
1182 vn += pn
1183 if self.normal!=Vector((0,0,1)):
1184 ma = getOCS(self.normal)
1185 if ma:
1186 points = [ma * v for v in points]
1187 return((points, edges, faces, vn))
1190 # class CText(CEntity):
1191 # 1 : 'text', 7 : 'style',
1192 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1193 # 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
1194 # 40 : 'height', 41 : 'x_scale',
1195 # 50 : 'rotation_angle', 51 : 'oblique_angle',
1196 # 71 : 'flags', 72 : 'horizontal_justification', 73 : 'vertical_justification',
1199 class CText(CEntity):
1200 def __init__(self):
1201 CEntity.__init__(self, 'TEXT', 'Text')
1202 self.text = ""
1203 self.style = ""
1204 self.insertion_point = Vector()
1205 self.alignment_point = Vector()
1206 self.height = 1.0
1207 self.x_scale = 1.0
1208 self.rotation_angle = 0.0
1209 self.oblique_angle = 0.0
1210 self.flags = 0
1211 self.horizontal_justification = 0.0
1212 self.vertical_justification = 0.0
1213 self.thickness = 0.0
1214 self.normal = Vector((0,0,1))
1216 def display(self):
1217 CEntity.display(self)
1218 print("%s %s" % (self.text, self.style))
1219 print(self.insertion_point)
1220 print(self.alignment_point)
1222 def draw(self):
1223 drawText(self.text, self.insertion_point, self.height, self.x_scale, self.rotation_angle, self.oblique_angle, self.normal)
1224 return
1227 def drawText(text, loc, size, spacing, angle, shear, normal=Vector((0,0,1))):
1228 #print('angle_deg=',angle)
1229 bpy.ops.object.text_add(
1230 view_align=False,
1231 enter_editmode=False,
1232 location= loc,
1233 #rotation=(0, 0, angle), #need radians here
1235 cu = bpy.context.object.data
1236 cu.body = text
1237 cu.size = size #up 2.56
1238 cu.space_word = spacing #up 2.56
1239 cu.shear = shear
1240 if angle!=0.0 or normal!=Vector((0,0,1)):
1241 obj = bpy.context.object
1242 transform(normal, angle, obj)
1243 return
1246 # class CTolerance(CEntity):
1247 # 3 : 'style',
1248 # 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1249 # 11 : 'direction.x', 21 : 'direction.y', 31 : 'direction.z',
1252 class CTolerance(CEntity):
1253 def __init__(self):
1254 CEntity.__init__(self, 'TOLERANCE', None)
1255 self.stype = ""
1256 self.insertion_point = Vector()
1257 self.direction = Vector()
1260 # class CTrace(CEntity):
1261 # 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
1262 # 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
1263 # 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
1264 # 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
1265 # 39 : 'thickness',
1268 class CTrace(CEntity):
1269 def __init__(self):
1270 CEntity.__init__(self, 'TRACE', 'Mesh')
1271 self.point0 = Vector()
1272 self.point1 = Vector()
1273 self.point2 = Vector()
1274 self.point3 = Vector()
1275 self.normal = Vector((0,0,1))
1276 self.thickness = 0.0
1278 def display(self):
1279 CEntity.display(self)
1280 print(self.point0)
1281 print(self.point1)
1282 print(self.point2)
1283 print(self.point3)
1285 def build(self, vn=0):
1286 points, edges, faces = [],[],[]
1287 if self.point2 == self.point3:
1288 points = [self.point0, self.point2, self.point1]
1289 else:
1290 points = [self.point0, self.point2, self.point1, self.point3]
1291 pn = len(points)
1292 v0 = vn
1293 thic = self.thickness
1294 t_vector = Vector((0, 0, thic))
1295 if thic != 0 and (toggle & T_ThicON):
1296 thic_points = [v + t_vector for v in points]
1297 if thic < 0.0:
1298 thic_points.extend(points)
1299 points = thic_points
1300 else:
1301 points.extend(thic_points)
1303 if pn == 4:
1304 faces = [[0,1,3,2], [4,6,7,5], [0,4,5,1],
1305 [1,5,7,3], [3,7,6,2], [2,6,4,0]]
1306 elif pn == 3:
1307 faces = [[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]]
1308 elif pn == 2: faces = [[0,1,3,2]]
1309 vn += 2*pn
1310 else:
1311 if pn == 4: faces = [[0,2,3,1]]
1312 elif pn == 3: faces = [[0,2,1]]
1313 elif pn == 2:
1314 edges = [[0,1]]
1315 self.drawtype = 'Mesh'
1316 if self.normal!=Vector((0,0,1)):
1317 ma = getOCS(self.normal)
1318 if ma:
1319 points = [ma * v for v in points]
1320 return ((points, edges, faces, vn))
1323 # class CVertex(CEntity):
1324 # 10 : 'location.x', 20 : 'location.y', 30 : 'location.z',
1325 # 40 : 'start_width', 41 : 'end_width', 42 : 'bulge',
1326 # 50 : 'tangent',
1327 # 70 : 'flags',
1328 # 71 : 'index1', 72 : 'index2', 73 : 'index3', 74 : 'index4',
1331 class CVertex(CEntity):
1332 def __init__(self):
1333 CEntity.__init__(self, 'VERTEX', None)
1334 self.location = Vector()
1335 self.start_width = 0.0
1336 self.end_width = 0.0
1337 self.bulge = 0.0
1338 self.tangent = 0.0
1339 self.flags = 0
1341 def display(self):
1342 return
1344 def draw(self):
1345 return
1348 # class CViewPort(CEntity):
1349 # 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1350 # 12 : 'view_center.x', 22 : 'view_center.y', 32 : 'view_center.z',
1351 # 13 : 'snap_base.x', 23 : 'snap_base.y', 33 : 'snap_base.z',
1352 # 14 : 'snap_spacing.x', 24 : 'snap_spacing.y', 34 : 'snap_spacing.z',
1353 # 15 : 'grid_spacing.x', 25 : 'grid_spacing.y', 35 : 'grid_spacing.z',
1354 # 16 : 'view_direction.x', 26 : 'view_direction.y', 36 : 'view_direction.z',
1355 # 40 : 'width', 41 : 'height',
1356 # 68 : 'status', 69 : 'id',
1359 class CViewPort(CEntity):
1360 def __init__(self):
1361 CEntity.__init__(self, 'VIEWPORT', None)
1362 self.center = Vector()
1363 self.view_center = Vector()
1364 self.snap_base = Vector()
1365 self.snap_spacing = Vector()
1366 self.grid_spacing = Vector()
1367 self.view_direction = Vector()
1368 self.width = 1.0
1369 self.height = 1.0
1370 self.status = 0
1371 self.id = 0
1373 def draw(self):
1374 # Todo
1375 return
1378 # class CWipeOut(CEntity):
1379 # 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
1380 # 11 : 'direction.x', 21 : 'direction.y', 31 : 'direction.z',
1383 class CWipeOut(CEntity):
1384 def __init__(self):
1385 CEntity.__init__(self, 'WIPEOUT', None)
1386 self.point = Vector()
1387 self.direction = Vector()
1392 WORLDX = Vector((1.0,0.0,0.0))
1393 WORLDY = Vector((0.0,1.0,0.0))
1394 WORLDZ = Vector((0.0,0.0,1.0))
1397 def getOCS(az): #-----------------------------------------------------------------
1398 """An implimentation of the Arbitrary Axis Algorithm.
1400 #decide if we need to transform our coords
1401 #if az[0] == 0 and az[1] == 0:
1402 if abs(az.x) < 0.00001 and abs(az.y) < 0.00001:
1403 if az.z > 0.0:
1404 return False
1405 elif az.z < 0.0:
1406 return Matrix((-WORLDX, WORLDY*1, -WORLDZ)).transposed()
1408 cap = 0.015625 # square polar cap value (1/64.0)
1409 if abs(az.x) < cap and abs(az.y) < cap:
1410 ax = WORLDY.cross(az)
1411 else:
1412 ax = WORLDZ.cross(az)
1413 ax.normalize()
1414 ay = az.cross(ax)
1415 ay.normalize()
1416 # Matrices are now constructed from rows, transpose to make the rows into cols
1417 return Matrix((ax, ay, az)).transposed()
1421 def transform(normal, rotation, obj): #--------------------------------------------
1422 """Use the calculated ocs to determine the objects location/orientation in space.
1424 ma = Matrix()
1425 o = Vector(obj.location)
1426 ma_new = getOCS(normal)
1427 if ma_new:
1428 ma_new.resize_4x4()
1429 ma = ma_new
1430 o = ma * o
1432 if rotation != 0:
1433 rmat = Matrix.Rotation(radians(rotation), 4, 'Z')
1434 ma = ma * rmat
1436 obj.matrix_world = ma
1437 obj.location = o
1440 DxfEntityAttributes = {
1441 '3DFACE' : {
1442 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
1443 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
1444 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
1445 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
1446 70 : 'flags',
1449 '3DSOLID' : {
1450 1 : 'data', 3 : 'more', 70 : 'version',
1453 'ACAD_PROXY_ENTITY' : {
1454 70 : 'format',
1455 90 : 'id', 91 : 'class', 92 : 'graphics_size', 93 : 'entity_size', 95: 'format',
1456 310 : 'data', 330 : 'id1', 340 : 'id2', 350 : 'id3', 360 : 'id4',
1459 'ARC' : {
1460 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1461 40 : 'radius',
1462 50 : 'start_angle', 51 : 'end_angle',
1463 39 : 'thickness',
1464 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1467 'ARCALIGNEDTEXT' : {
1468 1 : 'text', 2 : 'font', 3 : 'bigfont', 7 : 'style',
1469 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1470 40 : 'radius', 41 : 'width', 42 : 'height', 43 : 'spacing',
1471 44 : 'offset', 45 : 'right_offset', 46 : 'left_offset',
1472 50 : 'start_angle', 51 : 'end_angle',
1473 70 : 'order', 71 : 'direction', 72 : 'alignment', 73 : 'side',
1474 74 : 'bold', 75 : 'italic', 76 : 'underline',
1475 77 : 'character_set', 78 : 'pitch', 79 : 'fonttype',
1476 90 : 'color',
1477 280 : 'wizard', 330 : 'id'
1480 'ATTDEF' : {
1481 1 : 'text', 2 : 'tag', 3 : 'prompt', 7 : 'style',
1482 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1483 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
1484 40 : 'height', 41 : 'x_scale',
1485 50 : 'rotation_angle', 51 : 'oblique_angle',
1486 70 : 'flags', 71 : 'text_generation_flags',
1487 72 : 'horizontal_justification', 74 : 'vertical_justification',
1491 'ATTRIB' : {
1492 1 : 'text', 2 : 'tag', 3 : 'prompt', 7 : 'style',
1493 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1494 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
1495 40 : 'height', 41 : 'x_scale',
1496 50 : 'rotation_angle', 51 : 'oblique_angle',
1497 70 : 'flags', 73 : 'length',
1498 71 : 'text_generation_flags', 72 : 'horizontal_justification', 74 : 'vertical_justification',
1501 'BLOCK' : {
1502 1 : 'xref', 2 : 'name', 3 : 'also_name',
1503 10 : 'base_point.x', 20 : 'base_point.y', 30 : 'base_point.z',
1504 40 : 'size', 41 : 'x_scale',
1505 50 : 'rotation_angle', 51 : 'oblique_angle',
1506 70 : 'flags',
1509 'CIRCLE' : {
1510 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1511 40 : 'radius',
1512 39 : 'thickness',
1513 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1516 'DIMENSION' : {
1517 1 : 'text', 2 : 'name', 3 : 'style',
1518 10 : 'def_point.x', 20 : 'def_point.y', 30 : 'def_point.z',
1519 11 : 'mid_point.x', 21 : 'mid_point.y', 31 : 'mid_point.z',
1520 12 : 'vector.x', 22 : 'vector.y', 32 : 'vector.z',
1521 13 : 'def_point2.x', 23 : 'def_point2.y', 33 : 'def_point2.z',
1522 14 : 'vector2.x', 24 : 'vector2.y', 34 : 'vector2.z',
1523 15 : 'vector3.x', 25 : 'vector3.y', 35 : 'vector3.z',
1524 16 : 'vector4.x', 26 : 'vector4.y', 36 : 'vector4.z',
1525 70 : 'dimtype',
1528 'ELLIPSE' : {
1529 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1530 11 : 'end_point.x', 21 : 'end_point.y', 31 : 'end_point.z',
1531 40 : 'ratio', 41 : 'start', 42 : 'end',
1532 39 : 'thickness',
1533 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1536 'HATCH' : {
1537 2 : 'pattern',
1538 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
1539 41 : 'scale', 47 : 'pixelsize', 52 : 'angle',
1540 70 : 'fill', 71 : 'associativity', 75: 'style', 77 : 'double',
1541 78 : 'numlines', 91 : 'numpaths', 98 : 'numseeds',
1542 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1545 'IMAGE' : {
1546 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1547 11 : 'u_vector.x', 21 : 'u_vector.y', 31 : 'u_vector.z',
1548 12 : 'v_vector.x', 22 : 'v_vector.y', 32 : 'v_vector.z',
1549 13 : 'size.x', 23 : 'size.y', 33 : 'size.z',
1550 14 : 'clip.x', 24 : 'clip.y', 34 : 'clip.z',
1551 70 : 'display', 71 : 'cliptype',
1552 90 : 'version',
1553 280 : 'clipstate', 281 : 'brightness', 282 : 'contrast', 283 : 'fade',
1554 340 : 'image', 360 : 'reactor',
1557 'INSERT' : {
1558 1 : 'attributes_follow', 2 : 'name',
1559 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1560 41 : 'x_scale', 42 : 'y_scale', 43 : 'z_scale',
1561 44 : 'column_spacing', 45 : 'row_spacing',
1562 50 : 'rotation_angle', 66 : 'attributes_follow',
1563 70 : 'column_count', 71 : 'row_count',
1564 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1567 'LEADER' : {
1568 3 : 'style',
1569 10 : ['new_vertex(data)'], 20 : 'vertex.y', 30 : 'vertex.z',
1570 40 : 'height', 41 : 'width',
1571 71 : 'arrowhead', 72 : 'pathtype', 73 : 'creation',
1572 74 : 'hookdir', 75 : 'hookline', 76 : 'numverts', 77 : 'color',
1573 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1574 211 : 'horizon.x', 221 : 'horizon.y', 231 : 'horizon.z',
1575 212 : 'offset_ins.x', 222 : 'offset_ins.y', 232 : 'offset_ins.z',
1576 213 : 'offset_ann.x', 223 : 'offset_ann.y', 233 : 'offset_ann.z',
1579 'LINE' : {
1580 10 : 'start_point.x', 20 : 'start_point.y', 30 : 'start_point.z',
1581 11 : 'end_point.x', 21 : 'end_point.y', 31 : 'end_point.z',
1582 39 : 'thickness',
1583 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1586 'LWPOLYLINE' : {
1587 10 : ['new_vertex(data)'], 20 : 'vertex.y', 30 : 'vertex.z',
1588 38 : 'elevation', 39 : 'thickness',
1589 40 : 'start_width', 41 : 'end_width', 42 : 'bulge', 43 : 'constant_width',
1590 70 : 'flags', 90 : 'numverts',
1591 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1594 'MLINE' : {
1595 10 : 'start_point.x', 20 : 'start_point.y', 30 : 'start_point.z',
1596 11 : ['new_vertex(data)'], 21 : 'vertex.y', 31 : 'vertex.z',
1597 12 : ['new_seg_dir(data)'], 22 : 'seg_dir.y', 32 : 'seg_dir.z',
1598 13 : ['new_miter_dir(data)'], 23 : 'miter_dir.y', 33 : 'miter_dir.z',
1599 39 : 'thickness',
1600 40 : 'scale', 41 : 'elem_param', 42 : 'fill_param',
1601 70 : 'justification', 71 : 'flags',
1602 72 : 'numverts', 73 : 'numelems', 74 : 'numparam', 75 : 'numfills',
1603 340 : 'id',
1604 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1607 'MTEXT' : {
1608 1 : 'text', 3: 'more_text', 7 : 'style',
1609 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1610 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
1611 40 : 'nominal_height', 41 : 'reference_width', 42: 'width', 43 : 'height', 44 : 'line_spacing',
1612 50 : 'rotation_angle',
1613 71 : 'attachment_point', 72 : 'drawing_direction', 73 : 'spacing_style',
1614 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1617 'POINT' : {
1618 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
1619 39 : 'thickness', 50 : 'orientation',
1622 'POLYLINE' : {
1623 1 : 'verts_follow', 2 : 'name',
1624 10 : 'elevation.x', 20 : 'elevation.y', 30 : 'elevation.z',
1625 39 : 'thickness',
1626 40 : 'start_width', 41 : 'end_width',
1627 66 : 'verts_follow_flag',
1628 70 : 'flags', 71 : 'row_count', 72 : 'column_count',
1629 73 : 'row_density', 74 : 'column_density', 75 : 'linetype',
1630 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1633 'RAY' : {
1634 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
1635 11 : 'direction.x', 21 : 'direction.y', 31 : 'direction.z',
1638 'RTEXT' : {
1639 1 : 'text', 7 : 'style',
1640 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1641 39 : 'thickness',
1642 40 : 'height',
1643 50 : 'rotation_angle',
1644 70 : 'flags',
1645 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1648 'SHAPE' : {
1649 2 : 'name',
1650 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1651 39 : 'thickness',
1652 40 : 'size', 41 : 'x_scale',
1653 50 : 'rotation_angle', 51 : 'oblique_angle',
1654 39 : 'thickness',
1657 'SOLID' : {
1658 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
1659 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
1660 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
1661 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
1662 39 : 'thickness',
1663 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1666 'SPLINE' : {
1667 10 : ['new_control_point(data)'], 20 : 'control_point.y', 30 : 'control_point.z',
1668 11 : ['new_fit_point(data)'], 21 : 'fit_point.y', 31 : 'fit_point.z',
1669 40 : ['new_knot_value(data)'],
1670 12 : 'start_tangent.x', 22 : 'start_tangent.y', 32 : 'start_tangent.z',
1671 13 : 'end_tangent.x', 23 : 'end_tangent.y', 33 : 'end_tangent.z',
1672 39 : 'thickness',
1673 41 : 'weight', 42 : 'knot_tol', 43 : 'control_point_tol', 44 : 'fit_tol',
1674 70 : 'flag', 71 : 'degree',
1675 72 : 'num_knots', 73 : 'num_control_points', 74 : 'num_fit_points',
1676 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1679 'TEXT' : {
1680 1 : 'text', 7 : 'style',
1681 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1682 11 : 'alignment_point.x', 21 : 'alignment_point.y', 31 : 'alignment_point.z',
1683 40 : 'height', 41 : 'x_scale',
1684 50 : 'rotation_angle', 51 : 'oblique_angle',
1685 71 : 'flags', 72 : 'horizontal_justification', 73 : 'vertical_justification',
1686 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1689 'TOLERANCE' : {
1690 3 : 'style',
1691 10 : 'insertion_point.x', 20 : 'insertion_point.y', 30 : 'insertion_point.z',
1692 11 : 'direction.x', 21 : 'direction.y', 31 : 'direction.z',
1695 'TRACE' : {
1696 10 : 'point0.x', 20 : 'point0.y', 30 : 'point0.z',
1697 11 : 'point1.x', 21 : 'point1.y', 31 : 'point1.z',
1698 12 : 'point2.x', 22 : 'point2.y', 32 : 'point2.z',
1699 13 : 'point3.x', 23 : 'point3.y', 33 : 'point3.z',
1700 39 : 'thickness',
1701 210 : 'normal.x', 220 : 'normal.y', 230 : 'normal.z',
1704 'VERTEX' : {
1705 10 : 'location.x', 20 : 'location.y', 30 : 'location.z',
1706 40 : 'start_width', 41 : 'end_width', 42 : 'bulge',
1707 50 : 'tangent',
1708 70 : 'flags',
1709 71 : 'index1', 72 : 'index2', 73 : 'index3', 74 : 'index4',
1712 'VIEWPORT' : {
1713 10 : 'center.x', 20 : 'center.y', 30 : 'center.z',
1714 12 : 'view_center.x', 22 : 'view_center.y', 32 : 'view_center.z',
1715 13 : 'snap_base.x', 23 : 'snap_base.y', 33 : 'snap_base.z',
1716 14 : 'snap_spacing.x', 24 : 'snap_spacing.y', 34 : 'snap_spacing.z',
1717 15 : 'grid_spacing.x', 25 : 'grid_spacing.y', 35 : 'grid_spacing.z',
1718 16 : 'view_direction.x', 26 : 'view_direction.y', 36 : 'view_direction.z',
1719 40 : 'width', 41 : 'height',
1720 68 : 'status', 69 : 'id',
1723 'WIPEOUT' : {
1724 10 : 'point.x', 20 : 'point.y', 30 : 'point.z',
1725 11 : 'direction.x', 21 : 'direction.y', 31 : 'direction.z',
1732 # Flags
1735 # Polyline flags
1736 PL_CLOSED = 0x01
1737 PL_CURVE_FIT_VERTS = 0x02
1738 PL_SPLINE_FIT_VERTS = 0x04
1739 PL_3D_POLYLINE = 0x08
1740 PL_3D_POLYGON_MESH = 0x10
1741 PL_CLOSED_IN_N_DIR = 0x20
1742 PL_POLYFACE_MESH = 0x40
1743 PL_CONTINUOUS = 0x80
1746 # Vertex flags
1747 VX_EXTRA_FLAG_CREATED = 0x01
1748 VX_CURVE_FIT_TANGENT_DEFINED = 0x02
1749 VX_SPLINE_VERTEX_CREATED = 0x08
1750 VX_SPLINE_FRAME_CONTROL_POINT = 0x10
1751 VX_3D_POLYLINE_VERTEX = 0x20
1752 VX_3D_POLYGON_MESH_VERTEX = 0x40
1753 VX_POLYFACE_MESH_VERTEX = 0x80
1755 # 3DFACE flags
1757 F3D_EDGE0_INVISIBLE = 0x01
1758 F3D_EDGE1_INVISIBLE = 0x02
1759 F3D_EDGE2_INVISIBLE = 0x04
1760 F3D_EDGE3_INVISIBLE = 0x08
1763 # readDxfFile(filePath):
1766 def readDxfFile(fileName):
1767 global toggle, theCodec
1769 print( "Opening DXF file "+ fileName )
1771 # fp= open(fileName, "rU")
1772 fp = codecs.open(fileName, "r", encoding=theCodec)
1773 first = True
1774 statements = []
1775 no = 0
1776 for line in fp:
1777 word = line.strip()
1778 no += 1
1779 if first:
1780 if word:
1781 code = int(word)
1782 first = False
1783 else:
1784 if toggle & T_Verbose:
1785 print("%4d: %4d %s" % (no, code, word))
1786 if code < 10:
1787 data = word
1788 elif code < 60:
1789 data = float(word)
1790 elif code < 100:
1791 data = int(word)
1792 elif code < 140:
1793 data = word
1794 elif code < 150:
1795 data = float(word)
1796 elif code < 200:
1797 data = int(word)
1798 elif code < 300:
1799 data = float(word)
1800 elif code < 370:
1801 data = word
1802 elif code < 390:
1803 data = int(word)
1804 elif code < 400:
1805 data = word
1806 elif code < 410:
1807 data = int(word)
1808 elif code < 1010:
1809 data = word
1810 elif code < 1060:
1811 data = float(word)
1812 elif code < 1080:
1813 data = int(word)
1815 statements.append((code,data))
1816 first = True
1817 fp.close()
1819 statements.reverse()
1820 sections = {}
1821 handles = {}
1822 while statements:
1823 (code,data) = statements.pop()
1824 if code == 0:
1825 if data == 'SECTION':
1826 section = CSection()
1827 elif code == 2:
1828 section.type = data
1829 if data == 'HEADER':
1830 parseHeader(section, statements, handles)
1831 known = False
1832 elif data == 'CLASSES':
1833 parseClasses(section, statements, handles)
1834 known = False
1835 elif data == 'TABLES':
1836 parseTables(section, statements, handles)
1837 known = False
1838 elif data == 'BLOCKS':
1839 parseBlocks(section, statements, handles)
1840 known = False
1841 elif data == 'ENTITIES':
1842 parseEntities(section, statements, handles)
1843 known = False
1844 elif data == 'OBJECTS':
1845 parseObjects(section, statements, handles)
1846 elif data == 'THUMBNAILIMAGE':
1847 parseThumbnail(section, statements, handles)
1848 sections[data] = section
1849 elif code == 999:
1850 pass
1851 else:
1852 raise NameError("Unexpected code in SECTION context: %d %s" % (code,data))
1854 if toggle & T_Verbose:
1855 for (typ,section) in sections.items():
1856 section.display()
1857 return sections
1862 # SECTION
1864 # HEADER
1867 # $<variable>
1868 # <group code>
1869 # <value>
1872 # ENDSEC
1875 def parseHeader(section, statements, handles):
1876 while statements:
1877 (code,data) = statements.pop()
1878 if code == 0:
1879 if data == 'ENDSEC':
1880 return
1882 return
1886 # SECTION
1888 # CLASSES
1891 # CLASS
1893 # <class dxf record>
1895 # <class name>
1897 # <app name>
1898 # 90
1899 # <flag>
1900 # 280
1901 # <flag>
1902 # 281
1903 # <flag>
1906 # ENDSEC
1908 def parseClasses(section, statements, handles):
1909 while statements:
1910 (code,data) = statements.pop()
1911 if code == 0:
1912 if data == 'ENDSEC':
1913 return
1915 return
1919 # SECTION
1921 # TABLES
1924 # TABLE
1926 # <table type>
1928 # <handle>
1929 # 100
1930 # AcDbSymbolTable
1931 # 70
1932 # <max. entries>
1935 # <table type>
1937 # <handle>
1938 # 100
1939 # AcDbSymbolTableRecord
1941 # . <data>
1945 # ENDTAB
1948 # ENDSEC
1951 # APPID (application identification table)
1953 # BLOCK_RECORD (block reference table)
1955 # DIMSTYLE (dimension style table)
1957 # LAYER (layer table)
1959 # LTYPE (linetype table)
1961 # STYLE (text style table)
1963 # UCS (User Coordinate System table)
1965 # VIEW (view table)
1967 # VPORT (viewport configuration table)
1970 def parseTables(section, statements, handles):
1971 tables = []
1972 section.data = tables
1973 while statements:
1974 (code,data) = statements.pop()
1975 if code == 0:
1976 if data == 'ENDSEC':
1977 return
1979 known = False
1980 elif data == 'TABLE':
1981 table = CTable()
1982 tables.append(table)
1983 known = False
1984 elif data == 'ENDTAB':
1985 pass
1986 known = False
1987 elif data == table.type:
1988 parseTableType
1989 table = CTable()
1990 tables.append(table)
1991 table.type = word
1992 elif code == 2:
1993 table.type = word
1994 elif code == 5:
1995 table.handle = word
1996 handles[word] = table
1997 elif code == 330:
1998 table.owner = word
1999 elif code == 100:
2000 table.subclass = word
2001 elif code == 70:
2002 table.nEntries = int(word)
2004 return
2007 # SECTION
2009 # BLOCKS
2012 # BLOCK
2014 # <handle>
2015 # 100
2016 # AcDbEntity
2018 # <layer>
2019 # 100
2020 # AcDbBlockBegin
2022 # <block name>
2023 # 70
2024 # <flag>
2025 # 10
2026 # <X value>
2027 # 20
2028 # <Y value>
2029 # 30
2030 # <Z value>
2032 # <block name>
2034 # <xref path>
2037 # <entity type>
2039 # . <data>
2043 # ENDBLK
2045 # <handle>
2046 # 100
2047 # AcDbBlockEnd
2050 # ENDSEC
2052 def parseBlocks(section, statements, handles):
2053 while statements:
2054 (code,data) = statements.pop()
2055 if code == 0:
2056 if data == 'ENDSEC':
2057 return
2059 return
2062 # SECTION
2064 # ENTITIES
2067 # <entity type>
2069 # <handle>
2070 # 330
2071 # <pointer to owner>
2072 # 100
2073 # AcDbEntity
2075 # <layer>
2076 # 100
2077 # AcDb<classname>
2079 # . <data>
2083 # ENDSEC
2085 Ignorables = ['DIMENSION', 'TEXT', 'VIEWPORT']
2087 ClassCreators = {
2088 '3DFACE': 'C3dFace()',
2089 '3DSOLID': 'C3dSolid()',
2090 'ACAD_PROXY_ENTITY': 'CAcadProxyEntity()',
2091 'ACAD_ZOMBIE_ENTITY': 0,
2092 'ARC': 'CArc()',
2093 'ARCALIGNEDTEXT': 'CArcAlignedText()',
2094 'ATTDEF': 'CAttdef()',
2095 'ATTRIB': 'CAttrib()',
2096 'BODY': 0,
2097 'CIRCLE': 'CCircle()',
2098 'DIMENSION': 'CDimension()',
2099 'ELLIPSE': 'CEllipse()',
2100 'HATCH': 'CHatch()',
2101 'IMAGE': 'CImage()',
2102 'INSERT': 'CInsert()',
2103 'LEADER': 'CLeader()',
2104 'LINE': 'CLine()',
2105 'LWPOLYLINE': 'CLWPolyLine()',
2106 'MLINE': 'CMLine()',
2107 'MTEXT': 'CMText()',
2108 'OLEFRAME': 0,
2109 'OLE2FRAME': 0,
2110 'POINT': 'CPoint()',
2111 'POLYLINE': 'CPolyLine()',
2112 'RAY': 'CRay()',
2113 'REGION': 0,
2114 'RTEXT': 'CRText',
2115 'SEQEND': 0,
2116 'SHAPE': 'CShape()',
2117 'SOLID': 'CSolid()',
2118 'SPLINE': 'CSpline()',
2119 'TEXT': 'CText()',
2120 'TOLERANCE': 'CTolerance()',
2121 'TRACE': 'CTrace()',
2122 'VERTEX': 'CVertex()',
2123 'VIEWPORT': 'CViewPort()',
2124 'WIPEOUT': 'CWipeOut()',
2125 'XLINE': 'CXLine()',
2128 def parseEntities(section, statements, handles):
2129 entities = []
2130 section.data = entities
2131 while statements:
2132 (code,data) = statements.pop()
2133 if toggle & T_Verbose:
2134 print("ent", code,data)
2135 if code == 0:
2136 known = True
2137 if data in Ignorables:
2138 ignore = True
2139 else:
2140 ignore = False
2142 try:
2143 creator = ClassCreators[data]
2144 except:
2145 creator = None
2147 if creator:
2148 entity = eval(creator)
2149 elif data == 'ENDSEC':
2150 return
2151 else:
2152 known = False
2154 if data == 'POLYLINE':
2155 verts = entity.verts
2156 elif data == 'VERTEX':
2157 verts.append(entity)
2159 if data == 'SEQEND':
2160 attributes = []
2161 known = False
2162 elif creator == 0:
2163 ignore = True
2164 elif known:
2165 entities.append(entity)
2166 attributes = DxfEntityAttributes[data]
2167 else:
2168 raise NameError("Unknown data %s" % data)
2170 elif not known:
2171 pass
2172 else:
2173 expr = getAttribute(attributes, code)
2174 if expr:
2175 exec(expr)
2176 else:
2177 expr = getAttribute(DxfCommonAttributes, code)
2178 if expr:
2179 exec(expr)
2180 elif code >= 1000 or ignore:
2181 pass
2182 elif toggle & T_Debug:
2183 raise NameError("Unknown code %d for %s" % (code, entity.type))
2185 return
2187 def getAttribute(attributes, code):
2188 try:
2189 ext = attributes[code]
2190 if type(ext) == str:
2191 expr = "entity.%s = data" % ext
2192 else:
2193 name = ext[0]
2194 expr = "entity.%s" % name
2195 except:
2196 expr = None
2197 return expr
2201 # SECTION
2203 # OBJECTS
2206 # DICTIONARY
2208 # <handle>
2209 # 100
2210 # AcDbDictionary
2213 # <dictionary name>
2214 # 350
2215 # <handle of child>
2218 # <object type>
2220 # . <data>
2224 # ENDSEC
2226 def parseObjects(data, statements, handles):
2227 while statements:
2228 (code,data) = statements.pop()
2229 if code == 0:
2230 if data == 'ENDSEC':
2231 return
2233 return
2236 # THUMBNAILIMAGE
2237 # 90
2238 # 45940
2239 # 310
2240 # 28000000B40000005500000001001800000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
2241 # 310
2242 # FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
2243 # 310
2244 # .......
2246 # ENDSEC
2248 def parseThumbnail(section, statements, handles):
2249 """ Just skip these """
2250 while statements:
2251 (code,data) = statements.pop()
2252 if code == 0:
2253 if data == 'ENDSEC':
2254 return
2256 return
2259 # buildGeometry(entities):
2260 # addMesh(name, verts, edges, faces):
2263 def buildGeometry(entities):
2264 try: bpy.ops.object.mode_set(mode='OBJECT')
2265 except: pass
2266 v_verts = []
2267 v_vn = 0
2268 e_verts = []
2269 e_edges = []
2270 e_vn = 0
2271 f_verts = []
2272 f_edges = []
2273 f_faces = []
2274 f_vn = 0
2275 for ent in entities:
2276 if ent.drawtype in {'Mesh', 'Curve'}:
2277 (verts, edges, faces, vn) = ent.build()
2278 if not toggle & T_DrawOne:
2279 drawGeometry(verts, edges, faces)
2280 else:
2281 if verts:
2282 if faces:
2283 for i,f in enumerate(faces):
2284 #print ('face=', f)
2285 faces[i] = tuple(it+f_vn for it in f)
2286 for i,e in enumerate(edges):
2287 edges[i] = tuple(it+f_vn for it in e)
2288 f_verts.extend(verts)
2289 f_edges.extend(edges)
2290 f_faces.extend(faces)
2291 f_vn += len(verts)
2292 elif edges:
2293 for i,e in enumerate(edges):
2294 edges[i] = tuple(it+e_vn for it in e)
2295 e_verts.extend(verts)
2296 e_edges.extend(edges)
2297 e_vn += len(verts)
2298 else:
2299 v_verts.extend(verts)
2300 v_vn += len(verts)
2301 else:
2302 ent.draw()
2304 if toggle & T_DrawOne:
2305 drawGeometry(f_verts, f_edges, f_faces)
2306 drawGeometry(e_verts, e_edges)
2307 drawGeometry(v_verts)
2311 def drawGeometry(verts, edges=[], faces=[]):
2312 if verts:
2313 if edges and (toggle & T_Curves):
2314 print ('draw Curve')
2315 cu = bpy.data.curves.new('DXFlines', 'CURVE')
2316 cu.dimensions = '3D'
2317 buildSplines(cu, verts, edges)
2318 ob = addObject('DXFlines', cu)
2319 else:
2320 #for v in verts: print(v)
2321 #print ('draw Mesh with %s vertices' %(len(verts)))
2322 #for e in edges: print(e)
2323 #print ('draw Mesh with %s edges' %(len(edges)))
2324 #for f in faces: print(f)
2325 #print ('draw Mesh with %s faces' %(len(faces)))
2326 me = bpy.data.meshes.new('DXFmesh')
2327 me.from_pydata(verts, edges, faces)
2328 ob = addObject('DXFmesh', me)
2329 removeDoubles(ob)
2330 return
2334 def buildSplines(cu, verts, edges):
2335 if edges:
2336 point_list = []
2337 (v0,v1) = edges.pop()
2338 v1_old = v1
2339 newPoints = [tuple(verts[v0]),tuple(verts[v1])]
2340 for (v0,v1) in edges:
2341 if v0==v1_old:
2342 newPoints.append(tuple(verts[v1]))
2343 else:
2344 #print ('newPoints=', newPoints)
2345 point_list.append(newPoints)
2346 newPoints = [tuple(verts[v0]),tuple(verts[v1])]
2347 v1_old = v1
2348 point_list.append(newPoints)
2349 for points in point_list:
2350 spline = cu.splines.new('POLY')
2351 #spline = cu.splines.new('BEZIER')
2352 #spline.use_endpoint_u = True
2353 #spline.order_u = 2
2354 #spline.resolution_u = 1
2355 #spline.bezier_points.add(2)
2357 spline.points.add(len(points)-1)
2358 #spline.points.foreach_set('co', points)
2359 for i,p in enumerate(points):
2360 spline.points[i].co = (p[0],p[1],p[2],0)
2362 #print ('spline.type=', spline.type)
2363 #print ('spline number=', len(cu.splines))
2366 def addObject(name, data):
2367 ob = bpy.data.objects.new(name, data)
2368 scn = bpy.context.scene
2369 scn.objects.link(ob)
2370 return ob
2373 def removeDoubles(ob):
2374 global theMergeLimit
2375 if toggle & T_Merge:
2376 scn = bpy.context.scene
2377 scn.objects.active = ob
2378 bpy.ops.object.mode_set(mode='EDIT')
2379 bpy.ops.mesh.remove_doubles(threshold=theMergeLimit)
2380 bpy.ops.object.mode_set(mode='OBJECT')
2385 # clearScene(context):
2388 def clearScene():
2389 global toggle
2390 scn = bpy.context.scene
2391 print("clearScene %s %s" % (toggle & T_NewScene, scn))
2392 if not toggle & T_NewScene:
2393 return scn
2395 for ob in scn.objects:
2396 if ob.type in ["MESH", "CURVE", "TEXT"]:
2397 scn.objects.active = ob
2398 bpy.ops.object.mode_set(mode='OBJECT')
2399 scn.objects.unlink(ob)
2400 del ob
2401 return scn
2404 # readAndBuildDxfFile(filepath):
2407 def readAndBuildDxfFile(filepath):
2408 fileName = os.path.expanduser(filepath)
2409 if fileName:
2410 (shortName, ext) = os.path.splitext(fileName)
2411 #print("filepath: ", filepath)
2412 #print("fileName: ", fileName)
2413 #print("shortName: ", shortName)
2414 if ext.lower() != ".dxf":
2415 print("Error: Not a dxf file: " + fileName)
2416 return
2417 if toggle & T_NewScene:
2418 clearScene()
2419 if 0: # how to switch to the new scene?? (migius)
2420 new_scn = bpy.data.scenes.new(shortName[-20:])
2421 #new_scn.layers = (1<<20) -1
2422 #new_scn_name = new_scn.name # UNUSED
2423 bpy.data.screens.scene = new_scn
2424 #print("newScene: %s" % (new_scn))
2425 sections = readDxfFile(fileName)
2426 print("Building geometry")
2427 buildGeometry(sections['ENTITIES'].data)
2428 print("Done")
2429 return
2430 print("Error: Not a dxf file: " + filepath)
2431 return
2434 # User interface
2437 DEBUG= False
2438 from bpy.props import *
2440 def tripleList(list1):
2441 list3 = []
2442 for elt in list1:
2443 list3.append((elt,elt,elt))
2444 return list3
2446 class IMPORT_OT_autocad_dxf(bpy.types.Operator):
2447 """Import from DXF file format (.dxf)"""
2448 bl_idname = "import_scene.autocad_dxf"
2449 bl_description = 'Import from DXF file format (.dxf)'
2450 bl_label = "Import DXF" +' v.'+ __version__
2451 bl_space_type = "PROPERTIES"
2452 bl_region_type = "WINDOW"
2453 bl_options = {'UNDO'}
2455 filepath = StringProperty(
2456 subtype='FILE_PATH',
2458 new_scene = BoolProperty(
2459 name="Replace scene",
2460 description="Replace scene",
2461 default=toggle & T_NewScene,
2463 #~ new_scene = BoolProperty(
2464 #~ name="New scene",
2465 #~ description="Create new scene",
2466 #~ default=toggle & T_NewScene,
2467 #~ )
2468 curves = BoolProperty(
2469 name="Draw curves",
2470 description="Draw entities as curves",
2471 default=toggle & T_Curves,
2473 thic_on = BoolProperty(
2474 name="Thick ON",
2475 description="Support THICKNESS",
2476 default=toggle & T_ThicON,
2478 merge = BoolProperty(
2479 name="Remove doubles",
2480 description="Merge coincident vertices",
2481 default=toggle & T_Merge,
2483 mergeLimit = FloatProperty(
2484 name="Limit",
2485 description="Merge limit * 0.0001",
2486 default=theMergeLimit * 1e4,
2487 min=1.0,
2488 soft_min=1.0,
2489 max=1000.0,
2490 soft_max=1000.0,
2492 draw_one = BoolProperty(
2493 name="Merge all",
2494 description="Draw all into one mesh object",
2495 default=toggle & T_DrawOne,
2497 circleResolution = IntProperty(
2498 name="Circle resolution",
2499 description="Circle/Arc are approximated with this factor",
2500 default=theCircleRes,
2501 min=4,
2502 soft_min=4,
2503 max=360,
2504 soft_max=360,
2506 codecs = tripleList(['iso-8859-15', 'utf-8', 'ascii'])
2507 codec = EnumProperty(name="Codec",
2508 description="Codec",
2509 items=codecs,
2510 default='ascii',
2512 debug = BoolProperty(
2513 name="Debug",
2514 description="Unknown DXF-codes generate errors",
2515 default=toggle & T_Debug,
2517 verbose = BoolProperty(
2518 name="Verbose",
2519 description="Print debug info",
2520 default=toggle & T_Verbose,
2523 ##### DRAW #####
2524 def draw(self, context):
2525 layout0 = self.layout
2526 #layout0.enabled = False
2528 #col = layout0.column_flow(2,align=True)
2529 layout = layout0.box()
2530 col = layout.column()
2531 #col.prop(self, 'KnotType') waits for more knottypes
2532 #col.label(text="import Parameters")
2533 #col.prop(self, 'replace')
2534 col.prop(self, 'new_scene')
2536 row = layout.row(align=True)
2537 row.prop(self, 'curves')
2538 row.prop(self, 'circleResolution')
2540 row = layout.row(align=True)
2541 row.prop(self, 'merge')
2542 if self.merge:
2543 row.prop(self, 'mergeLimit')
2545 row = layout.row(align=True)
2546 #row.label('na')
2547 row.prop(self, 'draw_one')
2548 row.prop(self, 'thic_on')
2550 col = layout.column()
2551 col.prop(self, 'codec')
2553 row = layout.row(align=True)
2554 row.prop(self, 'debug')
2555 if self.debug:
2556 row.prop(self, 'verbose')
2558 def execute(self, context):
2559 global toggle, theMergeLimit, theCodec, theCircleRes
2560 O_Merge = T_Merge if self.merge else 0
2561 #O_Replace = T_Replace if self.replace else 0
2562 O_NewScene = T_NewScene if self.new_scene else 0
2563 O_Curves = T_Curves if self.curves else 0
2564 O_ThicON = T_ThicON if self.thic_on else 0
2565 O_DrawOne = T_DrawOne if self.draw_one else 0
2566 O_Debug = T_Debug if self.debug else 0
2567 O_Verbose = T_Verbose if self.verbose else 0
2569 toggle = O_Merge | O_DrawOne | O_NewScene | O_Curves | O_ThicON | O_Debug | O_Verbose
2570 theMergeLimit = self.mergeLimit*1e-4
2571 theCircleRes = self.circleResolution
2572 theCodec = self.codec
2574 readAndBuildDxfFile(self.filepath)
2575 return {'FINISHED'}
2577 def invoke(self, context, event):
2578 wm = context.window_manager
2579 wm.fileselect_add(self)
2580 return {'RUNNING_MODAL'}
2583 def menu_func(self, context):
2584 self.layout.operator(IMPORT_OT_autocad_dxf.bl_idname, text="Autocad (.dxf)")
2587 def register():
2588 bpy.utils.register_module(__name__)
2590 bpy.types.INFO_MT_file_import.append(menu_func)
2593 def unregister():
2594 bpy.utils.unregister_module(__name__)
2596 bpy.types.INFO_MT_file_import.remove(menu_func)
2599 if __name__ == "__main__":
2600 register()