added encoding "# coding: utf-8" to the headers of scripts that python would not...
[blender.git] / release / scripts / import_dxf.py
1 #!BPY
2 # coding: utf-8
3 """
4 Name: 'Autodesk DXF (.dxf)'
5 Blender: 244
6 Group: 'Import'
7 Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).'
8 """
9 __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)'
10 __version__ = '1.0.12 - 2008.02.08 by migius'
11 __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319",
12          "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"]
13 __email__ = ["Kitsune_e(at)yahoo.com", "migius(at)4d-vectors.de"]
14 __bpydoc__ = """\
15 This script imports objects from DXF (2d/3d) into Blender.
16
17 This script imports 2d and 3d geometery from DXFr12 format files.
18 Enhanced features are:
19 - configurable object filtering and geometry manipulation,
20 - configurable material pre-processing,
21 - DXF-data analyze and raporting.
22
23 Supported DXF r12 objects:
24 LINE,
25 POINT,
26 SOLID,
27 TRACE,
28 TEXT,
29 INSERT (=block),
30 MINSERT (=array of blocks),
31 CIRCLE,
32 ARC,
33 3DFACE,
34 2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline),
35 3d-POLYLINE (=non-plane),
36 3d-POLYMESH,
37 3d-POLYFACE,
38 VIEW, VPORT
39 XREF (External Reference).
40
41 Supported DXF>r12 objects:
42 ELLIPSE,
43 (wip v1.0.12 partly supported) LWPOLYLINE (LightWeight),
44 (wip v1.0.12) MLINE,
45 (wip v1.0.12) MTEXT
46
47 Unsupported Objects:
48 DXF r12: DIMENSION.
49 DXF>r12: SPLINE, GROUP, RAY/XLINE, LEADER, 3DSOLID, BODY, REGION, dynamic BLOCK
50
51 Supported Geometry: 2d and 3d DXF-objects.
52 Curves imported as curves or meshes optionally.
53
54 Supported layout modes:
55 "model space" is default,
56 "paper space" as option (= "layout views")
57
58 Scene definitions produced with AVE_RENDER:
59 scene: selection of lights assigned to the camera,
60 lights: DIRECT, OVERHEAD, SH_SPOT,
61 (wip v1.0.13 import of AVE_RENDER material definitions)
62
63 Hierarchy:
64 Entire DXF BLOCK hierarchy is preserved after import into Blender
65 (BLOCKs as groups on layer19, INSERTs as dupliGroups on target layer).
66
67 Supported properties:
68 visibility status,
69 frozen status,
70 thickness,
71 width,
72 color,
73 layer,
74 (wip v1.0.12: XDATA, grouped status)
75 It is recommended to use DXF-object properties for assign Blender materials.
76
77 Notes:
78 - Recommend that you run 'RemoveDoubles' on each imported mesh after using this script
79 - Blocks are created on layer 19 then referenced at each insert point.
80 - Big DXF-files (over 1500 objects) decrease import performance.
81 The problem is not the inefficiency of python-scripting but Blenders performance
82 in creating new objects in his database - probably a database management problem.
83         
84 TODO:  
85 - the new style object visibility
86 - support for real 3d-solids (ACIS)
87 - (to see more, search for "--todo--" in script code)
88
89 """
90
91 """
92 History:
93  v1.0 - 2008.01. by migius
94  planned tasks:
95  -- command-line-mode/batch-mode
96  -- in-place-editing for dupliGroups
97  -- support for MLINE (is exported to r12 as BLOCK*Unnamed with LINEs)
98  -- support for MTEXT (is exported to r12 as TEXT???)
99  -- blender_object.properties['dxf_layer_name']
100  -- better support for long dxf-layer-names 
101  -- add configuration file.ini handles multiple material setups
102  -- added f_layerFilter
103  -- to-check: obj/mat/group/_mapping-idea from ideasman42:
104  -- curves: added "fill/non-fill" option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs
105  -- bug:? object = Object.Get(obname) -> = SCENE.getChildren(obname)
106  -- "normalize Z" option to correct non-planar figures
107  -- LINEs need "width" in 3d-space incl vGroups
108  -- support width_force for LINEs/ELLIPSEs = "solidify"
109  -- add better support for color_index BYLAYER=256, BYBLOCK=0 
110  -- bug: "oneMesh" produces sometimes errors
111  -- bug: Registry recall from hd_cache ?? only win32 bug??
112
113  v1.0.12: 2008.02.08 by migius
114  -- support DXF-definitions of scene, lights and cameras
115  -- support ortho mode for VIEWs and VPORTs as cameras 
116  a9 bugfix by non-existing tables views, vports, layers (Kai reported)
117  v1.0.12: 2008.01.17 by migius
118  a8 lately used INI-dir/filename persistently stored in Registry
119  a8 lately used DXF-dir/filename persistently stored in Registry
120  a7 fix missing layersmap{} for dxf-files without "section:layer"
121  a6 added support for XREF external referenced BLOCKs
122  a6 check for bug in AutoCAD2002:DXFr12export: ELLIPSE->POLYLINE_ARC fault angles
123  a6 support VIEWs and VPORTs as cameras: ortho and perspective mode
124  a6 save resources through ignoring unused BLOCKs (not-inserted or on frozen/blocked layers)
125  a6 added try_finally: f.close() for all IO-files
126  a6 added handling for TypeError raise
127  a5 bugfix f_getOCS for (0,0,z!=1.0) (ellipse in Kai's dxf)
128  a4 added to analyzeTool: report about VIEWs, VPORTs, unused/xref BLOCKs
129  a4 bugfix: individual support for 2D/3DPOLYLINE/POLYMESH
130  a4 added to UI: (*wip)BLOCK-(F): name filtering for BLOCKs
131  a4 added to UI: BLOCK-(n): filter anoname/hatch BLOCKs *X...
132  a2 g_scale_as is no more GUI_A-variable
133  a2 bugfix "material": negative sign color_index
134  a2 added support for BLOCKs defined with origin !=(0,0,0)
135  a1 added 'global.reLocation-vector' option
136
137  v1.0.11: 2007.11.24 by migius
138  c8 added 'curve_resolution_U' option 
139  c8 added context_sensitivity for some UI-buttons
140  c8 bugfix ELLIPSE rotation, added closed_variant and caps
141  c7 rebuild UI: new layout, grouping and meta-buttons
142  c6 rewritten support for ELLIPSE mesh & curve representation
143  c6 restore selector-buttons for DXF-drawTypes: LINE & Co
144  c6 change header of INI/INF-files: # at begin
145  c6 apply scale(1,1,1) after glob.Scale for all mesh objects, not for curve objects.
146  c5 fixing 'material_on' option
147  c4 added "analyze DXF-file" UI-option: print LAYER/BLOCK-dependences into a textfile
148  c3 human-formating of data in INI-Files
149  c2 added "caps" for closed Bezier-curves
150  c2 added "set elevation" UI-option
151  c1 rewrite POLYLINE2d-arc-segments Bezier-interpreter
152  b9 many bugs fixed
153  b9 rewrite POLYLINE2d-arc-segments trimming (clean-trim)
154  b8 added "import from frozen layers" UI-option
155  b8 added "import from paper space" UI-option
156  b8 support Bezier curves for LINEs incl.thickness(0.0-10.0)
157  b8 added meshSmooth_on for circle/arc/polyline 
158  b8 added vertexGroups for circle/arc 
159  b7 added width_force for ARCs/CIRCLEs = "thin_box" option
160  b3 cleanup code, rename f_drawArc/Bulg->f_calcArc/Bulg
161  b2 fixing material assignment by LAYER+COLOR
162  b1 fixing Bezier curves representation of POLYLINEs-arc-segments
163  b0 added global_scale_presets: "yard/feet/inch to meter"
164
165  v1.0.10: 2007.10.18 by migius
166  a6 bugfix CircleDrawCaps for OSX 
167  a5 added two "curve_res" UI-buttons for Bezier curves representation
168  a5 improved Bezier curves representation of circles/arcs: correct handlers
169  a4 try to fix malformed endpoints of Blender curves of ARC/POLYLINE-arc segments. 
170  a3 bugfix: open-POLYLINEs with end_point.loc==start_point.loc
171  a2 bugfix: f_transform for OCS=(0,0,-1) oriented objects
172  a1 added "fill_on=caps" option to draw top and bottom sides of CIRCLEs and ELLIPSEs
173  a1 rewrite f_CIRCLE.Draw: from Mesh.Primitive to Mesh
174  a1 bugfix "newScene"-mode: all Cylinders/Arcs were drawn at <0,0,0>location
175
176  v1.0.beta09: 2007.09.02 by migius
177  g5 redesign UI: grouping of buttons
178  g3 update multi-import-mode: <*.*> button
179  g- added multi-import-mode: (path/*) for importing many dxf-files at once
180  g- added import into newScene
181  g- redesign UI: user presets, into newScene-import  
182  f- cleanup code
183  f- bugfix: thickness for Bezier/Bsplines into Blender-curves
184  f- BlenderWiki documentation, on-line Manual
185  f- added import POLYLINE-Bsplines into Blender-NURBSCurves
186  f- added import POLYLINE-arc-segments into Blender-BezierCurves
187  f- added import POLYLINE-Bezier-curves into Blender-Curves
188  d5 rewrite: Optimization Levels, added 'directDrawing'
189  d4 added: f_set_thick(controlled by ini-parameters)
190  d4 bugfix: face-normals in objects with minus thickness
191  d4 added: placeholder'Empty'-size in f_Insert.draw
192  d3 rewrite f_Text.Draw: added support for all Text's parameters
193  d2 redesign: progressbar 
194  e- tuning by ideasman42: better use of the Py API.
195  c- tuning by ideasman42
196  b- rewrite f_Text.Draw rotation/transform
197  b- bugfix: POLYLINE-segment-intersection more reliable now
198  b- bugfix: circle:_thic, 'Empties':no material_assignment
199  b- added material assignment (from layer and/or color)
200  a- added empty, cylinder and UVsphere for POINTs
201  a- added support for 2d-POLYLINE: splines, fitted curves, fitted surfaces
202  a- redesign f_Drawer for block_definitions
203  a- rewrite import into Blender-Curve-Object
204
205  v1.0.beta08 - 2007.07.27 by migius: "full 3d"-release
206  l- bugfix: solid_vgroups, clean:scene.objects.new()
207  l- redesign UI to standard Draw.Register+FileSelector, advanced_config_option
208  k- bugfix UI:fileSelect() for MacOSX os.listdir()
209  k- added reset/save/load for config-data
210  k- redesign keywords/drawTypes/Draw.Create_Buttons
211  j- new UI using UIBlock() with own FileSelector, cause problem Window.FileSelector()
212  i- rewritten Class:Settings for better config-parameter management
213  h- bugfix: face-normals in objects with minus thickness
214  h- added Vertex-Groups in POLYLINE and SOLID meshes, for easy material assignment
215  h- beautify code, whitespace->tabs
216  h- added settings.thic_force switch for forcing thickness
217  h- added "one Mesh" option for all entities from the same Layer, sorted in<br>
218  Vertex-Groups(color_name)  (fewer objects = better import performance)
219  g- rewrote: insert-point-handle-object is a small tetrahedron
220  e- bugfix: closed-polymesh3d
221  - rewrote: UI, type_map.keys, f_drawer, all class_f_draw(added "settings" as attribut)
222  - added 2d/3d-support for Polyline_Width incl. angle intersection
223  beta07: 2007.06.19 by migius
224  - added 3d-support for LWPolylines
225  - added 2d/3d-support for Points
226  beta06: 2007.06.15 by migius
227  - cleanup code
228  - added 2d/3d-support for MINSERT=BlockArray in f_drawer, added f_rotXY_Vec
229  beta05: 2007.06.14 by migius
230  - added 2d/3d-support for 3d-PolyLine, PolyMesh and PolyFace
231  - added Global-Scale for size control of imported scenes
232  beta04: 2007.06.12 by migius
233  - rewrote the f_drawBulge for correct import the arc-segments of Polylines
234  beta03: 2007.06.10 by migius
235  - rewrote interface
236  beta02: 2007.06.09 by migius
237  - added 3d-support for Arcs and Circles
238  - added support for Object_Thickness(=height)
239  beta01: 2007.06.08 by migius
240  - added 3d-support for Blocks/Inserts within nested-structures
241  - rewrote f_transform for correct 3d-location/3d-rotation
242  - added 3d-support Lines, 3dFaces
243  - added 2d+3d-support for Solids and Traces
244
245  v0.9 - 2007.01 by kitsu: (for 2.43)
246  - first draft of true POLYLINE import
247  -
248
249  v0.8 - 2006.12 by kitsu:
250  - first draft of object space coordinates OCS import
251  -
252
253  v0.5b - 2006.10 by kitsu: (for 2.42a)
254  - dxfReader.py
255  - color_map.py
256
257 """
258
259 # --------------------------------------------------------------------------
260 # DXF Import v1.0 by Ed Blake (AKA kitsu) and Remigiusz Fiedler (AKA migius)
261 # --------------------------------------------------------------------------
262 # ***** BEGIN GPL LICENSE BLOCK *****
263 #
264 # This program is free software; you can redistribute it and/or
265 # modify it under the terms of the GNU General Public License
266 # as published by the Free Software Foundation; either version 2
267 # of the License, or (at your option) any later version.
268 #
269 # This program is distributed in the hope that it will be useful,
270 # but WITHOUT ANY WARRANTY; without even the implied warranty of
271 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
272 # GNU General Public License for more details.
273 #
274 # You should have received a copy of the GNU General Public License
275 # along with this program; if not, write to the Free Software Foundation,
276 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
277 #
278 # ***** END GPL LICENCE BLOCK *****
279 # --------------------------------------------------------------------------
280
281 import Blender
282 #import bpy
283 from Blender import *
284 #from Blender.Mathutils import Vector, Matrix
285 #import BPyMessages
286
287 from dxfReader import readDXF
288 #from dxfReader import get_name, get_layer
289 from dxfReader import Object as dxfObject
290 from dxfColorMap import color_map
291
292 from math import *
293
294 try:
295         import os
296         if os.name:# != 'mac':
297                 import psyco
298                 psyco.log(Blender.Get('tempdir')+"/blender.log-psyco")
299                 #psyco.log()
300                 psyco.full(memory=100)
301                 psyco.profile(0.05, memory=100)
302                 psyco.profile(0.2)
303                 #print 'psyco imported'
304 except ImportError:
305         #print 'psyco not imported'
306         pass
307
308 print '\n\n\n\n'
309 print 'DXF-Importer  *** start ***'   #---------------------
310
311 SCENE = None
312 WORLDX = Mathutils.Vector((1,0,0))
313 WORLDY = Mathutils.Vector((1,1,0))
314 WORLDZ = Mathutils.Vector((0,0,1))
315
316 G_SCALE = 1.0      #(0.0001-1000) global scaling factor for all dxf data
317 G_ORIGIN_X = 0.0   #global translation-vector (x,y,z) in DXF units
318 G_ORIGIN_Y = 0.0
319 G_ORIGIN_Z = 0.0
320 MIN_DIST = 0.001        #cut-off value for sort out short-distance polyline-"duoble_vertex"
321 ARC_RESOLUTION = 64   #(4-500) arc/circle resolution - number of segments
322 ARC_RADIUS = 1.0   #(0.01-100) arc/circle radius for number of segments algorithm
323 CURV_RESOLUTION = 12 #(1-128) Bezier curves U-resolution
324 CURVARC_RESOLUTION = 4 #(3-32) resolution of circle represented as Bezier curve 
325 THIN_RESOLUTION = 8   #(4-64) thin_cylinder arc_resolution - number of segments
326 MIN_THICK = MIN_DIST * 10.0  #minimal thickness by forced thickness
327 MIN_WIDTH = MIN_DIST * 10.0  #minimal width by forced width
328 TRIM_LIMIT = 3.0         #limit for triming of polylines-wide-segments (values:0.0 - 5.0)
329 ELEVATION = 0.0 #standard elevation = coordinate Z
330
331 TARGET_LAYER = 3        #target blender_layer
332 GROUP_BYLAYER = 0   #(0/1) all entities from same layer import into one blender-group
333
334 FILENAME_MAX = 180      #max length of path+file_name string  (FILE_MAXDIR + FILE_MAXFILE)
335 MAX_NAMELENGTH = 17   #max_effective_obnamelength in blender =21=17+(.001)
336 INIFILE_DEFAULT_NAME = 'importDXF'
337 INIFILE_EXTENSION = '.ini'
338 INIFILE_HEADER = '#ImportDXF.py ver.1.0 config data'
339 INFFILE_HEADER = '#ImportDXF.py ver.1.0 analyze of DXF-data'
340
341 AUTO = BezTriple.HandleTypes.AUTO
342 FREE = BezTriple.HandleTypes.FREE
343 VECT = BezTriple.HandleTypes.VECT
344 ALIGN = BezTriple.HandleTypes.ALIGN
345 cur_COUNTER = 0  #counter for progress_bar
346
347
348 """This module provides wrapper objects for dxf entities.
349
350         The wrappers expect a "dxf object" as input.  The dxf object is
351         an object with a type and a data attribute.  Type is a lowercase
352         string matching the 0 code of a dxf entity.  Data is a list containing
353         dxf objects or lists of [code, data] pairs.
354
355         This module is not general, and is only for dxf import.
356 """
357
358 # from Stani's dxf writer v1.1 (c)www.stani.be (GPL)
359 #---color values
360 BYBLOCK = 0
361 BYLAYER = 256
362
363 #---block-type flags (bit coded values, may be combined):
364 ANONYMOUS                  =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
365 NON_CONSTANT_ATTRIBUTES =2  # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
366 XREF                                    =4  # This block is an external reference (xref)
367 XREF_OVERLAY                    =8  # This block is an xref overlay
368 EXTERNAL                                =16 # This block is externally dependent
369 RESOLVED                                =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
370 REFERENCED        =64 # This definition is a referenced external reference (ignored on input)
371
372 #---polyline flags
373 CLOSED                    =1  # This is a closed polyline (or a polygon mesh closed in the M direction)
374 CURVE_FIT                          =2  # Curve-fit vertices have been added
375 SPLINE_FIT                =4  # Spline-fit vertices have been added
376 POLYLINE_3D      =8   # This is a 3D polyline
377 POLYGON_MESH                            =16  # This is a 3D polygon mesh
378 CLOSED_N                                        =32  # The polygon mesh is closed in the N direction
379 POLYFACE_MESH              =64   # The polyline is a polyface mesh
380 CONTINOUS_LINETYPE_PATTERN  =128        # The linetype pattern is generated continuously around the vertices of this polyline
381
382 #---text flags
383 #horizontal
384 LEFT            = 0
385 CENTER  = 1
386 RIGHT   = 2
387 ALIGNED  = 3 #if vertical alignment = 0
388 MIDDLE  = 4 #if vertical alignment = 0
389 FIT   = 5 #if vertical alignment = 0
390 #vertical
391 BASELINE        = 0
392 BOTTOM  = 1
393 MIDDLE  = 2
394 TOP   = 3
395
396 #---mtext flags
397 #attachment point
398 TOP_LEFT                = 1
399 TOP_CENTER  = 2
400 TOP_RIGHT   = 3
401 MIDDLE_LEFT  = 4
402 MIDDLE_CENTER   = 5
403 MIDDLE_RIGHT    = 6
404 BOTTOM_LEFT  = 7
405 BOTTOM_CENTER   = 8
406 BOTTOM_RIGHT    = 9
407 #drawing direction
408 LEFT_RIGHT  = 1
409 TOP_BOTTOM  = 3
410 BY_STYLE                = 5 #the flow direction is inherited from the associated text style
411 #line spacing style (optional):
412 AT_LEAST                = 1 #taller characters will override
413 EXACT      = 2 #taller characters will not override
414
415
416 class View:  #-----------------------------------------------------------------
417         """Class for objects representing dxf VIEWs.
418         """
419         def __init__(self, obj, active=None):
420                 """Expects an object of type VIEW as input.
421                 """
422                 if not obj.type == 'view':
423                         raise TypeError, "Wrong type %s for VIEW object!" %obj.type
424
425                 self.type = obj.type
426                 self.name = obj.get_type(2)[0]
427                 self.data = obj.data[:]
428
429
430                 self.centerX = getit(obj.data, 10, 0.0) #view center pointX (in DCS)
431                 self.centerY = getit(obj.data, 20, 0.0) #view center pointY (in DCS)
432                 self.height = obj.get_type(40)[0] #view height (in DCS)
433                 self.width = obj.get_type(41)[0] #view width (in DCS)
434
435                 self.dir = [0,0,0]
436                 self.dir[0] = getit(obj.data, 11, 0.0) #view directionX from target (in WCS)
437                 self.dir[1] = getit(obj.data, 21, 0.0) #
438                 self.dir[2] = getit(obj.data, 31, 0.0) #
439
440                 self.target = [0,0,0]
441                 self.target[0] = getit(obj.data, 12, 0.0) #target pointX(in WCS)
442                 self.target[1] = getit(obj.data, 22, 0.0) #
443                 self.target[2] = getit(obj.data, 32, 0.0) #
444
445                 self.length = obj.get_type(42)[0] #Lens length
446                 self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point)
447                 self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point)
448                 self.twist  = obj.get_type(50)[0] #view twist angle in degrees
449
450                 self.flags = getit(obj, 70, 0)
451                 self.paperspace = self.flags & 1 #
452
453                 self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable)
454
455         def __repr__(self):
456                 return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length)
457
458
459         def draw(self, settings):
460                 """for VIEW: generate Blender_camera.
461                 """
462                 obname = 'vw_%s' %self.name  # create camera object name
463                 #obname = 'ca_%s' %self.name  # create camera object name
464                 obname = obname[:MAX_NAMELENGTH]
465
466                 if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0:
467                         cam= Camera.New('ortho', obname)
468                         ob= SCENE.objects.new(cam)
469                         cam.type = 'ortho'
470                         cam.scale = 1.0  # for ortho cameras
471                 else:
472                         cam= Camera.New('persp', obname)
473                         ob= SCENE.objects.new(cam)
474                         cam.type = 'persp'
475                         cam.angle = 60.0  # for persp cameras
476                         if self.length:
477                                 #cam.angle = 2 * atan(17.5/self.length) * 180/pi
478                                 cam.lens = self.length #for persp cameras
479                         # hack to update Camera>Lens setting (inaccurate as a focal length) 
480                         #curLens = cam.lens; cam.lens = curLens
481                         # AutoCAD gets clip distance from target:
482                         dist = Mathutils.Vector(self.dir).length
483                         cam.clipEnd = dist - self.clip_back
484                         cam.clipStart = dist - self.clip_front
485         
486                 cam.drawLimits = 1 
487                 cam.drawSize = 10
488                 
489                 v = Mathutils.Vector(self.dir)
490 #               print 'deb:view cam:', cam #------------
491 #               print 'deb:view self.target:', self.target #------------
492 #               print 'deb:view self.dir:', self.dir #------------
493 #               print 'deb:view self.twist:', self.twist #------------
494 #               print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------
495                 transform(v.normalize(), -self.twist, ob)
496                 ob.loc =  Mathutils.Vector(self.target) + Mathutils.Vector(self.dir)
497                 return ob
498
499
500 class Vport:  #-----------------------------------------------------------------
501         """Class for objects representing dxf VPORTs.
502         """
503         def __init__(self, obj, active=None):
504                 """Expects an object of type VPORT as input.
505                 """
506                 if not obj.type == 'vport':
507                         raise TypeError, "Wrong type %s for VPORT object!" %obj.type
508
509                 self.type = obj.type
510                 self.name = obj.get_type(2)[0]
511                 self.data = obj.data[:]
512                 #print 'deb:vport name, data:', self.name #-------
513                 #print 'deb:vport data:', self.data #-------
514
515                 self.height = obj.get_type(40)[0] #vport height (in DCS)
516                 self.centerX = getit(obj.data, 12, 0.0) #vport center pointX (in DCS)
517                 self.centerY = getit(obj.data, 22, 0.0) #vport center pointY (in DCS)
518                 self.width = self.height * obj.get_type(41)[0] #vport aspect ratio - width (in DCS)
519
520                 self.dir = [0,0,0]
521                 self.dir[0] = getit(obj.data, 16, 0.0) #vport directionX from target (in WCS)
522                 self.dir[1] = getit(obj.data, 26, 0.0) #
523                 self.dir[2] = getit(obj.data, 36, 0.0) #
524
525                 self.target = [0,0,0]
526                 self.target[0] = getit(obj.data, 17, 0.0) #target pointX(in WCS)
527                 self.target[1] = getit(obj.data, 27, 0.0) #
528                 self.target[2] = getit(obj.data, 37, 0.0) #
529
530                 self.length = obj.get_type(42)[0] #Lens length
531                 self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point)
532                 self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point)
533                 self.twist  = obj.get_type(51)[0] #view twist angle
534
535                 self.flags = getit(obj, 70, 0)
536                 self.paperspace = self.flags & 1 #
537
538                 self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable)
539
540         def __repr__(self):
541                 return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length)
542
543         def draw(self, settings):
544                 """for VPORT: generate Blender_camera.
545                 """
546                 obname = 'vp_%s' %self.name  # create camera object name
547                 #obname = 'ca_%s' %self.name  # create camera object name
548                 obname = obname[:MAX_NAMELENGTH]
549
550                 if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0:
551                         cam= Camera.New('ortho', obname)
552                         ob= SCENE.objects.new(cam)
553                         cam.type = 'ortho'
554                         cam.scale = 1.0  # for ortho cameras
555                 else:
556                         cam= Camera.New('persp', obname)
557                         ob= SCENE.objects.new(cam)
558                         cam.type = 'persp'
559                         cam.angle = 60.0  # for persp cameras
560                         if self.length:
561                                 #cam.angle = 2 * atan(17.5/self.length) * 180/pi
562                                 cam.lens = self.length #for persp cameras
563                         # hack to update Camera>Lens setting (inaccurate as a focal length) 
564                         #curLens = cam.lens; cam.lens = curLens
565                         # AutoCAD gets clip distance from target:
566                         dist = Mathutils.Vector(self.dir).length
567                         cam.clipEnd = dist - self.clip_back
568                         cam.clipStart = dist - self.clip_front
569         
570                 cam.drawLimits = 1 
571                 cam.drawSize = 10
572                 
573                 v = Mathutils.Vector(self.dir)
574 #               print 'deb:view cam:', cam #------------
575 #               print 'deb:view self.target:', self.target #------------
576 #               print 'deb:view self.dir:', self.dir #------------
577 #               print 'deb:view self.twist:', self.twist #------------
578 #               print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------
579                 transform(v.normalize(), -self.twist, ob)
580                 ob.loc =  Mathutils.Vector(self.target) + Mathutils.Vector(self.dir)
581                 return ob
582
583
584
585 class Layer:  #-----------------------------------------------------------------
586         """Class for objects representing dxf LAYERs.
587         """
588         def __init__(self, obj, name=None, color=None, frozen=None):
589                 """Expects an object of type layer as input.
590                 """
591                 self.type = obj.type
592                 self.data = obj.data[:]
593
594                 if name:
595                         self.name = name
596                         #self.bfname = name  #--todo---see layernamesmap in f_getLayersmap ---
597                 else:
598                         self.name = obj.get_type(2)[0] #layer name of object
599
600                 if color:
601                         self.color = color
602                 else:
603                         self.color = obj.get_type(62)[0]  #color of object
604
605                 if frozen:
606                         self.frozen = frozen
607                 else:
608                         self.flags = obj.get_type(70)[0]
609                         self.frozen = self.flags & 1
610
611
612         def __repr__(self):
613                 return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color)
614
615
616
617 def getit(obj, typ, default=None):  #------------------------------------------
618         """Universal procedure for geting data from list/objects.
619         """
620         it = default
621         if type(obj) == list:  #if obj is a list, then searching in a list
622                 for item in obj:
623                         #print 'deb:getit item, type(item)', item, type(item)
624                         try:
625                                 if item[0] == typ:
626                                         it = item[1]
627                                         break  #as soon as the first found
628                         except:
629                                 # --todo-- I found one case where item was a text instance
630                                 # that failed with no __getitem__
631                                 pass
632         else:   #else searching in Object with get_type-Methode
633                 item = obj.get_type(typ)
634                 if item:
635                         it = item[0]
636         #print 'deb:getit:typ, it', typ, it #----------
637         return it
638
639
640
641 def get_extrusion(data):         #-------------------------------------------------
642         """Find the axis of extrusion.
643
644         Used to get from object_data the objects Object_Coordinate_System (ocs).
645         """
646         #print 'deb:get_extrusion: data: \n', data  #---------------
647         vec = [0,0,1]
648         vec[0] = getit(data, 210, 0) # 210 = x
649         vec[1] = getit(data, 220, 0) # 220 = y
650         vec[2] = getit(data, 230, 1) # 230 = z
651         #print 'deb:get_extrusion: vec: ', vec  #---------------
652         return vec
653
654
655
656 class Solid:  #-----------------------------------------------------------------
657         """Class for objects representing dxf SOLID or TRACE.
658         """
659         def __init__(self, obj):
660                 """Expects an entity object of type solid or trace as input.
661                 """
662                 if obj.type == 'trace':
663                         obj.type = 'solid'
664                 if not obj.type == 'solid':
665                         raise TypeError, "Wrong type \'%s\' for solid/trace object!" %obj.type
666
667                 self.type = obj.type
668                 self.data = obj.data[:]
669
670                 self.space = getit(obj, 67, 0)
671                 self.thic =  getit(obj, 39, 0)
672                 self.color_index = getit(obj, 62, BYLAYER)
673
674                 self.layer = getit(obj.data, 8, None)
675                 self.extrusion = get_extrusion(obj.data)
676                 self.points = self.get_points(obj.data)
677
678
679
680         def get_points(self, data):
681                 """Gets start and end points for a solid type object.
682
683                 Solids have 3 or 4 points and fixed codes for each value.
684                 """
685
686                 # start x, y, z and end x, y, z = 0
687                 a = [0, 0, 0]
688                 b = [0, 0, 0]
689                 c = [0, 0, 0]
690                 d = [0, 0, 0]
691                 a[0] = getit(data, 10, None) # 10 = x
692                 a[1] = getit(data, 20, None) # 20 = y
693                 a[2] = getit(data, 30,  0)   # 30 = z
694                 b[0] = getit(data, 11, None)
695                 b[1] = getit(data, 21, None)
696                 b[2] = getit(data, 31,  0)
697                 c[0] = getit(data, 12, None)
698                 c[1] = getit(data, 22, None)
699                 c[2] = getit(data, 32,  0)
700                 out = [a,b,c]
701
702                 d[0] =  getit(data, 13, None)
703                 if d[0] != None:
704                         d[1] = getit(data, 23, None)
705                         d[2] = getit(data, 33,  0)
706                         out.append(d)
707                 #print 'deb:solid.vertices:---------\n', out  #-----------------------
708                 return out
709
710
711         def __repr__(self):
712                 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
713
714
715         def draw(self, settings):
716                 """for SOLID: generate Blender_geometry.
717                 """
718                 points = self.points
719                 if not points: return
720                 edges, faces = [], []
721                 l = len(self.points)
722
723                 obname = 'so_%s' %self.layer  # create object name from layer name
724                 obname = obname[:MAX_NAMELENGTH]
725
726                 vg_left, vg_right, vg_top, vg_bottom, vg_start, vg_end = [], [], [], [], [], []
727                 thic = set_thick(self.thic, settings)
728                 if thic != 0:
729                         thic_points = [[v[0], v[1], v[2] + thic] for v in points[:]]
730                         if thic < 0.0:
731                                 thic_points.extend(points)
732                                 points = thic_points
733                         else:
734                                 points.extend(thic_points)
735
736                         if   l == 4:
737                                 faces = [[0,1,3,2], [4,6,7,5], [0,4,5,1],
738                                                  [1,5,7,3], [3,7,6,2], [2,6,4,0]]
739                                 vg_left = [2,6,4,0]
740                                 vg_right = [1,5,7,3]
741                                 vg_top = [4,6,7,5]
742                                 vg_bottom = [0,1,3,2]
743                                 vg_start = [0,4,5,1]
744                                 vg_end = [3,7,6,2]
745                         elif l == 3:
746                                 faces = [[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]]
747                                 vg_top = [3,4,5]
748                                 vg_bottom = [0,1,2]
749                                 vg_left = [2,5,3,0]
750                                 vg_right = [1,4,5,2]
751                                 vg_start = [0,3,4,1]
752                         elif l == 2: faces = [[0,1,3,2]]
753                 else:
754                         if   l == 4: faces = [[0,1,3,2]]
755                         elif l == 3: faces = [[0,1,2]]
756                         elif l == 2: edges = [[0,1]]
757
758
759
760                 me = Mesh.New(obname)             # create a new mesh
761                 me.verts.extend(points)         # add vertices to mesh
762                 if faces: me.faces.extend(faces)                   # add faces to the mesh
763                 if edges: me.edges.extend(edges)                   # add faces to the mesh
764
765                 ob = SCENE.objects.new(me) # create a new mesh_object
766                 if settings.var['vGroup_on']:
767                         # each MeshSide becomes vertexGroup for easier material assignment ---------------------
768                         replace = Blender.Mesh.AssignModes.ADD  #or .AssignModes.ADD/REPLACE
769                         if vg_left: me.addVertGroup('side.left')  ; me.assignVertsToGroup('side.left',  vg_left, 1.0, replace)
770                         if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
771                         if vg_top:  me.addVertGroup('side.top')   ; me.assignVertsToGroup('side.top',   vg_top, 1.0, replace)
772                         if vg_bottom:me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace)
773                         if vg_start:me.addVertGroup('side.start') ; me.assignVertsToGroup('side.start', vg_start, 1.0, replace)
774                         if vg_end:  me.addVertGroup('side.end')   ; me.assignVertsToGroup('side.end',   vg_end,   1.0, replace)
775
776                 transform(self.extrusion, 0, ob)
777
778                 return ob
779
780
781
782
783 class Line:  #-----------------------------------------------------------------
784         """Class for objects representing dxf LINEs.
785         """
786         def __init__(self, obj):
787                 """Expects an entity object of type line as input.
788                 """
789                 if not obj.type == 'line':
790                         raise TypeError, "Wrong type \'%s\' for line object!" %obj.type
791                 self.type = obj.type
792                 self.data = obj.data[:]
793
794                 self.space = getit(obj, 67, 0)
795                 self.thic =  getit(obj, 39, 0)
796                 #print 'deb:self.thic: ', self.thic #---------------------
797                 self.color_index = getit(obj, 62, BYLAYER)
798
799                 self.layer = getit(obj.data, 8, None)
800                 self.extrusion = get_extrusion(obj.data)
801                 self.points = self.get_points(obj.data)
802
803
804         def get_points(self, data):
805                 """Gets start and end points for a line type object.
806
807                 Lines have a fixed number of points (two) and fixed codes for each value.
808                 """
809                 # start x,y,z and end x,y,z = 0
810                 a = [0, 0, 0]
811                 b = [0, 0, 0]
812                 a[0] = getit(data, 10, None) # 10 = x
813                 a[1] = getit(data, 20, None) # 20 = y
814                 a[2] = getit(data, 30,  0) # 30 = z
815                 b[0] = getit(data, 11, None)
816                 b[1] = getit(data, 21, None)
817                 b[2] = getit(data, 31,  0)
818                 out = [a,b]
819                 return out
820
821
822         def __repr__(self):
823                 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
824
825
826         def draw(self, settings):
827                 """for LINE: generate Blender_geometry.
828                 """
829                 # Generate the geometery
830                 #settings.var['curves_on']=False
831
832                 points = self.points
833                 thic = set_thick(self.thic, settings)
834                 width = 0.0
835                 if settings.var['lines_as'] == 4: # as thin_box
836                         thic = settings.var['thick_min']
837                         width = settings.var['width_min']
838                 elif settings.var['lines_as'] == 3: # as thin cylinder
839                         cyl_rad = 0.5 * settings.var['width_min']
840
841                 if settings.var['lines_as'] == 5: # LINE curve representation-------------------------
842                         obname = 'li_%s' %self.layer  # create object name from layer name
843                         obname = obname[:MAX_NAMELENGTH]
844
845                         c = Curve.New(obname) # create new curve data
846                         curve = c.appendNurb(BezTriple.New(points[0]))
847                         curve.append(BezTriple.New(points[1]))
848                         for point in curve:
849                                 point.handleTypes = [VECT, VECT]
850                         curve.flagU = 0 # 0 sets the curve not cyclic=open
851                         c.setResolu(settings.var['curve_res'])
852                         c.update() #important for handles calculation
853
854                         ob = SCENE.objects.new(c) # create a new curve_object
855
856                         #if False:  # --todo-- better support for 210-group
857                         if thic != 0.0: #hack: Blender2.45 curve-extrusion
858                                 t = thic * 0.5
859                                 if abs(t) > 5.0: t = 5.0 * cmp(t,0) # Blender2.45 accepts only (0.0 - 5.0)
860                                 e = self.extrusion
861                                 c.setExt1(abs(t))  # curve-extrusion
862                                 ob.LocX += t * e[0]
863                                 ob.LocY += t * e[1]
864                                 ob.LocZ += t * e[2]
865                                 #c.setExt1(1.0)  # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0)
866                                 #ob.LocZ = t + self.loc[2]
867                                 #ob.SizeZ *= abs(t)
868                         return ob
869
870                 else:  # LINE mesh representation ------------------------------
871                         global activObjectLayer
872                         global activObjectName
873                         #print 'deb:draw:line.ob IN activObjectName: ', activObjectName #---------------------
874         
875                         if activObjectLayer == self.layer and settings.var['one_mesh_on']:
876                                 obname = activObjectName
877                                 #print 'deb:line.draw obname from activObjectName: ', obname #---------------------
878                                 ob = Object.Get(obname)  # open an existing mesh_object
879                                 #ob = SCENE.getChildren(obname)  # open an existing mesh_object
880                                 me = Mesh.Get(ob.name)   # open objects mesh data
881                         else:
882                                 obname = 'li_%s' %self.layer  # create object name from layer name
883                                 obname = obname[:MAX_NAMELENGTH]
884                                 me = Mesh.New(obname)             # create a new mesh
885                                 ob = SCENE.objects.new(me) # create a new mesh_object
886                                 activObjectName = ob.name
887                                 activObjectLayer = self.layer
888                                 #print ('deb:line.draw new line.ob+mesh:"%s" created!' %ob.name) #---------------------
889         
890                         faces, edges = [], []
891                         n = len(me.verts)
892
893                         #if settings.var['width_force']: #--todo-----------
894
895                         if thic != 0:
896                                 t, e = thic, self.extrusion
897                                 #print 'deb:thic, extr: ', t, e #---------------------
898                                 points.extend([[v[0]+t*e[0], v[1]+t*e[1], v[2]+t*e[2]] for v in points[:]])
899                                 faces = [[0+n, 1+n, 3+n, 2+n]]
900                         else:
901                                 edges = [[0+n, 1+n]]
902         
903                         me.verts.extend(points) # adds vertices to global mesh
904                         if faces: me.faces.extend(faces)           # add faces to the mesh
905                         if edges: me.edges.extend(edges)           # add faces to the mesh
906         
907                         if settings.var['vGroup_on']:
908                                 # entities with the same color build one vertexGroup for easier material assignment ----
909                                 ob.link(me) # link mesh to that object
910                                 vG_name = 'color_%s' %self.color_index
911                                 if edges: faces = edges
912                                 replace = Blender.Mesh.AssignModes.ADD  #or .AssignModes.REPLACE or ADD
913                                 try:
914                                         me.assignVertsToGroup(vG_name,  faces[0], 1.0, replace)
915                                         #print 'deb: existed vGroup:', vG_name #---------------------
916                                 except:
917                                         me.addVertGroup(vG_name)
918                                         me.assignVertsToGroup(vG_name,  faces[0], 1.0, replace)
919                                         #print 'deb: create new vGroup:', vG_name #---------------------
920         
921         
922                         #print 'deb:draw:line.ob OUT activObjectName: ', activObjectName #---------------------
923                         return ob
924         
925
926
927 class Point:  #-----------------------------------------------------------------
928         """Class for objects representing dxf POINTs.
929         """
930         def __init__(self, obj):
931                 """Expects an entity object of type point as input.
932                 """
933                 if not obj.type == 'point':
934                         raise TypeError, "Wrong type %s for point object!" %obj.type
935                 self.type = obj.type
936                 self.data = obj.data[:]
937
938                 self.space = getit(obj, 67, 0)
939                 self.thic =  getit(obj, 39, 0)
940                 #print 'deb:self.thic: ', self.thic #---------------------
941                 self.color_index = getit(obj, 62, BYLAYER)
942
943                 self.layer = getit(obj.data, 8, None)
944                 self.extrusion = get_extrusion(obj.data)
945                 self.points = self.get_points(obj.data)
946
947
948         def get_points(self, data):
949                 """Gets coordinates for a point type object.
950
951                 Points have fixed codes for each value.
952                 """
953                 a = [0, 0, 0]
954                 a[0] = getit(data, 10, None) # 10 = x
955                 a[1] = getit(data, 20, None) # 20 = y
956                 a[2] = getit(data, 30,  0) # 30 = z
957                 out = [a]
958                 return out
959
960
961         def __repr__(self):
962                 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
963
964
965         def draw(self, settings):
966                 """for POINT: generate Blender_geometry.
967                 """
968                 points = self.points
969                 obname = 'po_%s' %self.layer  # create object name from layer name
970                 obname = obname[:MAX_NAMELENGTH]
971                 points_as = settings.var['points_as']
972                 thic = settings.var['thick_min']
973                 if thic < settings.var['dist_min']: thic = settings.var['dist_min']
974
975                 if True: #--todo--  points_as in [1,3,4,5]:
976                         if True: # points_as in [1,5]: # as 'empty'
977                                 c = 'Empty'
978                         elif points_as == 3: # as 'thin sphere'
979                                 res = settings.var['thin_res']
980                                 c = Mesh.Primitives.UVsphere(res,res,thic)
981                         elif points_as == 4: # as 'thin box'
982                                 c = Mesh.Primitives.Cube(thic)
983                         ob = SCENE.objects.new(c, obname) # create a new object
984                         transform(self.extrusion, 0, ob)
985                         ob.loc = tuple(points[0])
986
987                 elif points_as == 2: # as 'vertex'
988                         global activObjectLayer
989                         global activObjectName
990                         #print 'deb:draw:point.ob IN activObjectName: ', activObjectName #---------------------
991                         if activObjectLayer == self.layer and settings.var['one_mesh_on']:
992                                 obname = activObjectName
993                                 #print 'deb:draw:point.ob obname from activObjectName: ', obname #---------------------
994                                 ob = Object.Get(obname)  # open an existing mesh_object
995                                 #ob = SCENE.getChildren(obname)  # open an existing mesh_object
996                                 me = Mesh.Get(ob.name)   # open objects mesh data
997                         else:
998                                 me = Mesh.New(obname)             # create a new mesh
999                                 ob = SCENE.objects.new(me) # create a new mesh_object
1000                                 activObjectName = ob.name
1001                                 activObjectLayer = self.layer
1002                                 #print ('deb:draw:point new point.ob+mesh:"%s" created!' %ob.name) #---------------------
1003                         me.verts.extend(points) # add vertices to mesh
1004
1005                 return ob
1006
1007
1008
1009 class LWpolyline:  #-----------------------------------------------------------------
1010         """Class for objects representing dxf LWPOLYLINEs.
1011         """
1012         def __init__(self, obj):
1013                 """Expects an entity object of type lwpolyline as input.
1014                 """
1015                 #print 'deb:LWpolyline.START:----------------' #------------------------
1016                 if not obj.type == 'lwpolyline':
1017                         raise TypeError, "Wrong type %s for polyline object!" %obj.type
1018                 self.type = obj.type
1019                 self.data = obj.data[:]
1020
1021                 # required data
1022                 self.num_points = obj.get_type(90)[0]
1023
1024                 # optional data (with defaults)
1025                 self.space = getit(obj, 67, 0)
1026
1027                 self.color_index = getit(obj, 62, BYLAYER)
1028
1029                 self.elevation =  getit(obj, 30, 0)
1030                 self.thic =  getit(obj, 39, 0)
1031                 self.flags = getit(obj, 70, 0)
1032
1033                 self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
1034
1035                 self.layer = getit(obj.data, 8, None)
1036                 self.points = self.get_points(obj.data)
1037                 self.extrusion = get_extrusion(obj.data)
1038
1039                 #print 'deb:LWpolyline.obj.data:\n', obj.data #------------------------
1040                 #print 'deb:LWpolyline.ENDinit:----------------' #------------------------
1041
1042
1043         def get_points(self, data):
1044                 """Gets points for a polyline type object.
1045
1046                 LW-Polylines have no fixed number of verts, and
1047                 each vert can have a number of properties.
1048                 Verts should be coded as
1049                 10:xvalue
1050                 20:yvalue
1051                 40:startwidth or 0
1052                 41:endwidth or 0
1053                 42:bulge or 0
1054                 for each vert
1055                 """
1056                 num = self.num_points
1057                 point = None
1058                 points = []
1059                 for item in data:
1060                         if item[0] == 10:   # 10 = x
1061                                 if point:
1062                                         points.append(point)
1063                                 point = Vertex()
1064                                 point.x = item[1]
1065                         elif item[0] == 20: # 20 = y
1066                                 point.y = item[1]
1067                         elif item[0] == 40: # 40 = start width
1068                                 point.swidth = item[1]
1069                         elif item[0] == 41: # 41 = end width
1070                                 point.ewidth = item[1]
1071                         elif item[0] == 42: # 42 = bulge
1072                                 point.bulge = item[1]
1073                 points.append(point)
1074                 return points
1075
1076
1077
1078         def __repr__(self):
1079                 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
1080
1081
1082         def draw(self, settings):
1083                 """for LWPOLYLINE: generate Blender_geometry.
1084                 """
1085                 #print 'deb:LWpolyline.draw.START:----------------' #------------------------
1086                 points = []
1087                 obname = 'lw_%s' %self.layer  # create object name from layer name
1088                 obname = obname[:MAX_NAMELENGTH]
1089                 #settings.var['curves_on'] == True
1090                 #print 'deb:index_len: ', len(self.points) #------------------
1091                 for i, point in enumerate(self.points):
1092                         #print 'deb:index: ', i #------------------
1093                         if not point.bulge:
1094                                 points.append(point.loc)
1095                         elif point.bulge and not self.closed and i == len(self.points)-1:
1096                                 points.append(point.loc)
1097                         elif point.bulge:        #
1098                                 if i == len(self.points)-1:
1099                                         point2 = self.points[0]
1100                                 else:
1101                                         point2 = self.points[i+1]
1102                                 arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad'])
1103                                 verts, center = calcBulge(point, point2, arc_res)
1104 #                          if i == len(self.points)-1:
1105 #                                  if self.closed:
1106 #                                          verts.pop() #remove last(=first) vertex
1107 #                          else:
1108 #                                  verts.pop() #remove last vertex, because this point will be writen as the next vertex
1109                                 points.extend(verts)
1110
1111                 thic = self.thic
1112                 if settings.var['thick_force'] and thic == 0: thic = settings.var['thick_min']
1113                 if settings.var['thick_on'] and thic != 0:
1114                         len1 = len(points)
1115                         points.extend([[point[0], point[1], point[2]+thic] for point in points])
1116                         faces = []
1117                         #print 'deb:len1:', len1  #-----------------------
1118                         faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)]
1119                         if self.closed:
1120                                 faces.append([len1-1, 0, len1, 2*len1-1])
1121                         #print 'deb:faces_list:\n', faces  #-----------------------
1122                         me = Mesh.New(obname)             # create a new mesh
1123                         ob = SCENE.objects.new(me) # create a new mesh_object
1124                         me.verts.extend(points) # add vertices to mesh
1125                         me.faces.extend(faces)   # add faces to the mesh
1126                 else:
1127                         edges = [[num, num+1] for num in xrange(len(points)-1)]
1128                         if self.closed:
1129                                 edges.append([len(points)-1, 0])
1130                         #print 'deb:edges_list:\n', edges  #-----------------------
1131                         me = Mesh.New(obname)             # create a new mesh
1132                         ob = SCENE.objects.new(me) # create a new mesh_object
1133                         me.verts.extend(points) # add vertices to mesh
1134                         me.edges.extend(edges)   # add edges to the mesh
1135
1136                 ob.LocZ = self.elevation
1137                 transform(self.extrusion, 0, ob)
1138
1139                 #print 'deb:LWpolyline.draw.END:----------------' #------------------------
1140                 return ob
1141
1142
1143
1144 class Polyline:  #-----------------------------------------------------------------
1145         """Class for objects representing dxf POLYLINEs.
1146         """
1147         def __init__(self, obj):
1148                 """Expects an entity object of type polyline as input.
1149                 """
1150                 #print 'deb:polyline.init.START:----------------' #------------------------
1151                 if not obj.type == 'polyline':
1152                         raise TypeError, "Wrong type %s for polyline object!" %obj.type
1153                 self.type = obj.type
1154                 self.data = obj.data[:]
1155                 #print 'deb:polyline.obj.data[:]:\n', obj.data[:] #------------------------
1156                 self.points = []
1157
1158                 # optional data (with defaults)
1159                 self.space = getit(obj, 67, 0)
1160                 self.elevation =  getit(obj, 30, 0)
1161                 #print 'deb:elevation: ', self.elevation #---------------
1162                 self.thic =  getit(obj, 39, 0)
1163                 self.color_index = getit(obj, 62, BYLAYER)
1164
1165                 self.flags = getit(obj, 70, 0)
1166                 self.closed = self.flags & 1   # closed in the M direction
1167                 self.curved = self.flags & 2   # Bezier-curve-fit vertices have been added
1168                 self.spline = self.flags & 4   # Bspline-fit vertices have been added
1169                 self.poly3d = self.flags & 8   # 3D-polyline
1170                 self.plmesh = self.flags & 16  # 3D-polygon mesh
1171                 self.closeN = self.flags & 32  # closed in the N direction
1172                 self.plface = self.flags & 64  # 3D-polyface mesh
1173                 self.contin = self.flags & 128 # the linetype pattern is generated continuously
1174
1175                 if self.poly3d or self.plface or self.plmesh:
1176                         self.poly2d = False  # its not a 2D-polyline
1177                 else:
1178                         self.poly2d = True   # it is a 2D-polyline
1179
1180                 self.swidth =  getit(obj, 40, 0) # default start width
1181                 self.ewidth =  getit(obj, 41, 0) # default end width
1182                 #self.bulge  =  getit(obj, 42, None) # bulge of the segment
1183                 self.vectorsM =  getit(obj, 71, None) # PolyMesh: expansion in M-direction / PolyFace: number of the vertices
1184                 self.vectorsN =  getit(obj, 72, None) # PolyMesh: expansion in M-direction / PolyFace: number of faces
1185                 #self.resolM =  getit(obj, 73, None) # resolution of surface in M direction
1186                 #self.resolN =  getit(obj, 74, None) # resolution of surface in N direction
1187                 self.curvetyp =  getit(obj, 75, 0) # type of curve/surface: 0=None/5=Quadric/6=Cubic/8=Bezier
1188                 self.curvNormal = False
1189                 self.curvQBspline = False
1190                 self.curvCBspline = False
1191                 self.curvBezier = False
1192                 if   self.curvetyp == 0: self.curvNormal = True
1193                 elif self.curvetyp == 5: self.curvQBspline = True
1194                 elif self.curvetyp == 6: self.curvCBspline = True
1195                 elif self.curvetyp == 8: self.curvBezier = True
1196
1197                 self.layer = getit(obj.data, 8, None)
1198                 self.extrusion = get_extrusion(obj.data)
1199
1200                 self.points = []  #list with vertices coordinats
1201                 self.faces  = []  #list with vertices assigment to faces
1202                 #print 'deb:polyline.init.ENDinit:----------------' #------------
1203
1204
1205
1206         def __repr__(self):
1207                 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
1208
1209
1210
1211         def draw(self, settings):   #-------------%%%% DRAW POLYLINE %%%---------------
1212                 """for POLYLINE: generate Blender_geometry.
1213                 """
1214                 ob = []
1215                 #---- 3dPolyFace - mesh with free topology
1216                 if self.plface and settings.drawTypes['plmesh']:
1217                         ob = self.drawPlFace(settings)
1218                 #---- 3dPolyMesh - mesh with ortogonal topology
1219                 elif self.plmesh and settings.drawTypes['plmesh']:
1220                         ob = self.drawPlMesh(settings)
1221                 #---- 2dPolyline - plane polyline with arc/wide/thic segments
1222                 elif (self.poly2d and settings.drawTypes['polyline']):
1223                         if settings.var['plines_as'] == 5: # and self.spline:
1224                                 ob = self.drawPolyCurve(settings)
1225                         else:
1226                                 ob = self.drawPoly2d(settings)
1227                 #---- 3dPolyline - non-plane polyline (thin segments = without arc/wide/thic)
1228                 elif (self.poly3d and settings.drawTypes['pline3']):
1229                         if settings.var['plines3_as'] == 5: # and self.spline:
1230                                 ob = self.drawPolyCurve(settings)
1231                         else:
1232                                 ob = self.drawPoly2d(settings)
1233                 return ob
1234
1235
1236
1237         def drawPlFace(self, settings):  #---- 3dPolyFace - mesh with free topology
1238                 """Generate the geometery of polyface.
1239                 """
1240                 #print 'deb:drawPlFace.START:----------------' #------------------------
1241                 points = []
1242                 faces = []
1243                 #print 'deb:len of pointsList ====== ', len(self.points) #------------------------
1244                 for point in self.points:
1245                         if point.face:
1246                                 faces.append(point.face)
1247                         else:
1248                                 points.append(point.loc)
1249
1250
1251                 #print 'deb:drawPlFace: len of points_list:\n', len(points)  #-----------------------
1252                 #print 'deb:drawPlFace: len of faces_list:\n', len(faces)  #-----------------------
1253                 #print 'deb:drawPlFace: points_list:\n', points  #-----------------------
1254                 #print 'deb:drawPlFace: faces_list:\n', faces  #-----------------------
1255                 obname = 'pf_%s' %self.layer  # create object name from layer name
1256                 obname = obname[:MAX_NAMELENGTH]
1257                 me = Mesh.New(obname)             # create a new mesh
1258                 ob = SCENE.objects.new(me) # create a new mesh_object
1259                 me.verts.extend(points) # add vertices to mesh
1260                 me.faces.extend(faces)   # add faces to the mesh
1261                 #print 'deb:drawPlFace: len of me.faces:\n', len(me.faces)  #-----------------------
1262
1263                 if settings.var['meshSmooth_on']:  # ----------------------
1264                         for i in xrange(len(me.faces)):
1265                                 me.faces[i].smooth = True
1266                         #me.Mode(AUTOSMOOTH)
1267                 transform(self.extrusion, 0, ob)
1268                 #print 'deb:drawPlFace.END:----------------' #------------------------
1269                 return ob
1270
1271
1272
1273         def drawPlMesh(self, settings):  #---- 3dPolyMesh - mesh with orthogonal topology
1274                 """Generate the geometery of polymesh.
1275                 """
1276                 #print 'deb:polymesh.draw.START:----------------' #------------------------
1277                 #points = []
1278                 #print 'deb:len of pointsList ====== ', len(self.points) #------------------------
1279                 faces = []
1280                 m = self.vectorsM
1281                 n = self.vectorsN
1282                 for j in xrange(m - 1):
1283                         for i in xrange(n - 1):
1284                                 nn = j * n
1285                                 faces.append([nn+i, nn+i+1, nn+n+i+1, nn+n+i])
1286
1287                 if self.closed:   #mesh closed in N-direction
1288                         nn = (m-1)*n
1289                         for i in xrange(n - 1):
1290                                 faces.append([nn+i, nn+i+1, i+1, i])
1291
1292                 if self.closeN:   #mesh closed in M-direction
1293                         for j in xrange(m-1):
1294                                 nn = j * n
1295                                 faces.append([nn+n-1, nn, nn+n, nn+n-1+n])
1296
1297                 if self.closed and self.closeN:   #mesh closed in M/N-direction
1298                                 faces.append([ (n*m)-1, (m-1)*n, 0, n-1])
1299
1300                 #print 'deb:len of points_list:\n', len(points)  #-----------------------
1301                 #print 'deb:faces_list:\n', faces  #-----------------------
1302                 obname = 'pm_%s' %self.layer  # create object name from layer name
1303                 obname = obname[:MAX_NAMELENGTH]
1304                 me = Mesh.New(obname)             # create a new mesh
1305                 ob = SCENE.objects.new(me) # create a new mesh_object
1306                 me.verts.extend([point.loc for point in self.points]) # add vertices to mesh
1307                 me.faces.extend(faces)   # add faces to the mesh
1308
1309                 if settings.var['meshSmooth_on']:  # ----------------------
1310                         for i in xrange(len(faces)):
1311                                 me.faces[i].smooth = True
1312                         #me.Mode(AUTOSMOOTH)
1313
1314                 transform(self.extrusion, 0, ob)
1315                 #print 'deb:polymesh.draw.END:----------------' #------------------------
1316                 return ob
1317
1318
1319         def drawPolyCurve(self, settings):  #---- Polyline - draw as Blender-curve
1320                 """Generate the geometery of polyline as Blender-curve.
1321                 """
1322                 #print 'deb:polyline2dCurve.draw.START:----------------' #---
1323                 if len(self.points) < 2:
1324                         #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #---------
1325                         return
1326
1327                 if self.spline: pline_typ = 'ps'        # Polyline-nurbSpline
1328                 elif self.curved: pline_typ = 'pc'  # Polyline-bezierCurve
1329                 else: pline_typ = 'pl'                    # Polyline
1330                 obname = '%s_%s' %(pline_typ, self.layer)  # create object_name from layer name
1331                 obname = obname[:MAX_NAMELENGTH]
1332                 d_points = []
1333
1334                 if settings.var['Z_force_on']:
1335                         self.elevation = settings.var['Z_elev']
1336                         for point in self.points:
1337                                 point.loc[2] = self.elevation
1338                                 d_points.append(point)
1339                 else: #for DXFr10-format: update all points[].loc[2] == None -> 0.0 
1340                         for point in self.points:
1341                                 if point.loc[2] == None:
1342                                         point.loc[2] = self.elevation
1343                                 d_points.append(point)
1344
1345                 thic = set_thick(self.thic, settings)
1346                 if thic != 0.0:   #hack: Blender<2.45 curve-extrusion
1347                         LocZ = d_points[0].loc[2]
1348                         temp_points = []
1349                         for point in d_points:
1350                                 point.loc[2] = 0.0
1351                                 temp_points.append(point)
1352                         d_points = temp_points
1353                 
1354                 #print 'deb:polyline2dCurve.draw d_points=', d_points  #---------------
1355                 pline = Curve.New(obname)   # create new curve data
1356                 #pline.setResolu(24) #--todo-----                                               
1357
1358                 if False: #self.spline:  # NURBSplines-----FAKE(with Bezier)-----
1359                         #print 'deb:polyline2dCurve.draw self.spline!' #---------------
1360                         curve = pline.appendNurb(BezTriple.New(d_points[0]))
1361                         for p in d_points[1:]:
1362                                 curve.append(BezTriple.New(p))
1363                         for point in curve:
1364                                 point.handleTypes = [AUTO, AUTO]
1365                         if self.closed:
1366                                 curve.flagU = 1 # Set curve cyclic=close
1367                         else:
1368                                 curve.flagU = 0 # Set curve not cyclic=open
1369                                 curve[0].handleTypes = [FREE, ALIGN]   #remi--todo-----
1370                                 curve[-1].handleTypes = [ALIGN, FREE]   #remi--todo-----
1371
1372                 elif self.spline:  # NURBSplines-----OK-----
1373                         #print 'deb:polyline2dCurve.draw self.spline!' #---------------
1374                         weight1 = 0.5
1375                         weight2 = 1.0
1376                         # generate middlepoints except start/end-segments ---
1377                         if self.curvQBspline:
1378                                 temp_points = []
1379                                 point = d_points[0].loc
1380                                 point.append(weight1)
1381                                 temp_points.append(point)
1382                                 for i in xrange(1,len(d_points)-2):
1383                                         point1 = d_points[i].loc
1384                                         point2 = d_points[i+1].loc
1385                                         mpoint = list((Mathutils.Vector(point1) + Mathutils.Vector(point2)) * 0.5)
1386                                         mpoint.append(weight2)
1387                                         point1.append(weight1)
1388                                         temp_points.append(point1)
1389                                         temp_points.append(mpoint)
1390                                 point2.append(weight1)
1391                                 temp_points.append(point2)
1392                                 point = d_points[-1].loc
1393                                 point.append(weight1)
1394                                 temp_points.append(point)
1395                                 d_points = temp_points
1396                         else:
1397                                 temp_points = []
1398                                 for d in d_points:
1399                                         d = d.loc
1400                                         d.append(weight1)
1401                                         temp_points.append(d)
1402                                 d_points = temp_points
1403
1404                         if not self.closed:
1405                                 # generate extended startpoint and endpoint------
1406                                 point1 = Mathutils.Vector(d_points[0][:3])
1407                                 point2 = Mathutils.Vector(d_points[1][:3])
1408                                 startpoint = list(point1 - point2 + point1)
1409                                 startpoint.append(weight1)
1410                                 point1 = Mathutils.Vector(d_points[-1][:3])
1411                                 point2 = Mathutils.Vector(d_points[-2][:3])
1412                                 endpoint = list(point1 - point2 + point1)
1413                                 endpoint.append(weight1)
1414                                 temp_points = []
1415                                 temp_points.append(startpoint)
1416                                 temp_points.extend(d_points)
1417                                 d_points = temp_points
1418                                 d_points.append(endpoint)
1419
1420                         point = d_points[0]
1421                         curve = pline.appendNurb(point)
1422                         curve.setType(4) #NURBS curve
1423                         for point in d_points[1:]:
1424                                 curve.append(point)
1425                         if self.closed:
1426                                 curve.flagU = 1 # Set curve cyclic=close
1427                         else:
1428                                 curve.flagU = 0 # Set curve not cyclic=open
1429
1430                 elif  self.curved:  #--Bezier-curves---OK-------
1431                         #print 'deb:polyline2dCurve.draw self.curved!' #---------------
1432                         curve = pline.appendNurb(BezTriple.New(d_points[0]))
1433                         for p in d_points[1:]:
1434                                 curve.append(BezTriple.New(p))
1435                         for point in curve:
1436                                 point.handleTypes = [AUTO, AUTO]
1437                         if self.closed:
1438                                 curve.flagU = 1 # Set curve cyclic=close
1439                         else:
1440                                 curve.flagU = 0 # Set curve not cyclic=open
1441                                 curve[0].handleTypes = [FREE, ALIGN]   #remi--todo-----
1442                                 curve[-1].handleTypes = [ALIGN, FREE]   #remi--todo-----
1443
1444                 else:   #--straight line- and arc-segments----OK------
1445                         #print 'deb:polyline2dCurve.draw curve:', curve #-----
1446                         points = []
1447                         arc_res = settings.var['curve_arc']
1448                         prevHandleType = VECT
1449                         #d_points.append(d_points[0])  #------ first vertex added at the end of list --------
1450                         #curve.setType(0) #polygon_type of Blender_curve
1451                         for i in xrange(len(d_points)):
1452                                 point1 = d_points[i]
1453                                 #point2 = d_points[i+1]
1454                                 if False: #-----outdated!- standard calculation ----------------------------------
1455                                         if point1.bulge and (i < len(d_points)-2 or self.closed):
1456                                                 verts, center = calcBulge(point1, point2, arc_res, triples=False)
1457                                                 if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0]))
1458                                                 else: curve.append(BezTriple.New(verts[0]))
1459                                                 curve[-1].handleTypes = [VECT, VECT]  #--todo--calculation of bezier-tangents
1460                                                 for p in verts[1:]:
1461                                                         curve.append(BezTriple.New(p))
1462                                                         curve[-1].handleTypes = [AUTO, AUTO]
1463                                         else:
1464                                                 if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc))
1465                                                 else: curve.append(BezTriple.New(point1.loc))
1466                                                 curve[-1].handleTypes = [VECT, VECT]   #--todo--calculation of bezier-tangents
1467
1468                                 elif True:   #----- optimised Bezier-Handles calculation --------------------------------
1469                                         #print 'deb:drawPlineCurve: i:', i #---------
1470                                         if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed):
1471                                                 if i == len(d_points)-1: point2 = d_points[0]
1472                                                 else: point2 = d_points[i+1]
1473
1474
1475                                                 # calculate additional points for bulge
1476                                                 VectorTriples = calcBulge(point1, point2, arc_res, triples=True)
1477
1478                                                 if prevHandleType == FREE:
1479                                                         #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
1480                                                         VectorTriples[0][:3] = prevHandleVect
1481                                                         #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
1482
1483                                                 if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0]))
1484                                                 else: curve.append(BezTriple.New(VectorTriples[0]))
1485                                                 curve[-1].handleTypes = [prevHandleType, FREE]
1486
1487                                                 for p in VectorTriples[1:-1]:
1488                                                         curve.append(BezTriple.New(p))
1489                                                         curve[-1].handleTypes = [FREE, FREE]
1490
1491                                                 prevHandleVect = VectorTriples[-1][:3]
1492                                                 prevHandleType = FREE
1493                                                 #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #---------
1494                                         else:
1495                                                 #print 'deb:drawPlineCurve: else' #----------
1496                                                 if prevHandleType == FREE:
1497                                                         VectorTriples = prevHandleVect + list(point1) + list(point1)
1498                                                         #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #---------
1499                                                         curve.append(BezTriple.New(VectorTriples))
1500                                                         curve[-1].handleTypes = [FREE, VECT]
1501                                                         prevHandleType = VECT
1502                                                 else:
1503                                                         if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc))
1504                                                         else: curve.append(BezTriple.New(point1.loc))
1505                                                         curve[-1].handleTypes = [VECT, VECT]
1506                                                         
1507
1508
1509                                         #print 'deb:drawPlineCurve: curve[-1].vec[0]', curve[-1].vec[0] #----------
1510
1511                         if self.closed:
1512                                 curve.flagU = 1 # Set curve cyclic=close
1513                                 if prevHandleType == FREE:
1514                                         #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #----------
1515                                         #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #----------
1516                                         prevHandleType2 = curve[0].handleTypes[1]
1517                                         p0h1,p0,p0h2 = curve[0].vec 
1518                                         #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #----------
1519                                         p0h1 = prevHandleVect
1520                                         #p0h1 = [0,0,0]
1521                                         #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #----------
1522                                         #curve[0].vec = [p0h1,p0,p0h2]
1523                                         curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2))
1524
1525                                         curve[0].handleTypes = [FREE,prevHandleType2]
1526                                         #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #----------
1527                                         #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #----------
1528                                 else: 
1529                                         curve[0].handleTypes[0] = VECT
1530                         else: 
1531                                 curve.flagU = 0 # Set curve not cyclic=open
1532
1533                 if settings.var['fill_on']:
1534                         pline.setFlag(6) # 2+4 set top and button caps
1535                 else:
1536                         pline.setFlag(pline.getFlag() & ~6) # dont set top and button caps
1537
1538                 pline.setResolu(settings.var['curve_res'])
1539                 pline.update()
1540                 ob = SCENE.objects.new(pline) # create a new curve_object
1541
1542                 if thic != 0.0: #hack: Blender<2.45 curve-extrusion
1543                         thic = thic * 0.5
1544                         pline.setExt1(1.0)  # curve-extrusion accepts only (0.0 - 2.0)
1545                         ob.LocZ = thic + LocZ
1546
1547                 transform(self.extrusion, 0, ob)
1548                 if thic != 0.0:
1549                         ob.SizeZ *= abs(thic)
1550
1551                 #print 'deb:polyline2dCurve.draw.END:----------------' #-----
1552                 return ob
1553
1554
1555         def drawPoly2d(self, settings):  #---- 2dPolyline - plane lines/arcs with wide/thic
1556                 """Generate the geometery of regular polyline.
1557                 """
1558                 #print 'deb:polyline2d.draw.START:----------------' #------------------------
1559                 points = []
1560                 d_points = []
1561                 swidths = []
1562                 ewidths = []
1563                 swidth_default = self.swidth #default start width of POLYLINEs segments
1564                 ewidth_default = self.ewidth #default end width of POLYLINEs segments
1565                 thic = set_thick(self.thic, settings)
1566                 if self.spline: pline_typ = 'ps'
1567                 elif self.curved: pline_typ = 'pc'
1568                 else: pline_typ = 'pl'
1569                 obname = '%s_%s' %(pline_typ, self.layer)  # create object_name from layer name
1570                 obname = obname[:MAX_NAMELENGTH]
1571
1572                 if len(self.points) < 2:
1573                         #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #---------
1574                         return
1575                 
1576                 if settings.var['Z_force_on']:
1577                         self.elevation = settings.var['Z_elev']
1578                         for point in self.points:
1579                                 point.loc[2] = self.elevation
1580                                 d_points.append(point)
1581                 else: #for DXFr10-format: update all non-existing LocZ points[].loc[2] == None -> 0.0 elevation
1582                         for point in self.points:
1583                                 if point.loc[2] == None:
1584                                         point.loc[2] = self.elevation
1585                                 d_points.append(point)
1586                 #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------
1587                 #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------
1588
1589
1590                 #if closed polyline, add duplic of the first vertex at the end of pointslist
1591                 if self.closed:  #new_b8
1592                         if d_points[-1].loc != d_points[0].loc: # if not equal, then set the first at the end of pointslist
1593                                 d_points.append(d_points[0])
1594                 else:
1595                         if d_points[-1].loc == d_points[0].loc: # if equal, then set to closed, and modify the last point
1596                                 d_points[-1] = d_points[0]
1597                                 self.closed = True
1598                 #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------
1599                 #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------
1600
1601
1602                 # routine to sort out of "double.vertices" ------------------------------------
1603                 minimal_dist =  settings.var['dist_min'] * 0.1
1604                 temp_points = []
1605                 for i in xrange(len(d_points)-1):
1606                         point = d_points[i]
1607                         point2 = d_points[i+1]
1608                         #print 'deb:double.vertex p1,p2', point, point2 #------------------------
1609                         delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc)
1610                         if delta.length > minimal_dist:
1611                                  temp_points.append(point)
1612                         #else: print 'deb:drawPoly2d double.vertex sort out!' #------------------------
1613                 temp_points.append(d_points[-1])  #------ incl. last vertex -------------
1614                 #if self.closed: temp_points.append(d_points[1])  #------ loop start vertex -------------
1615                 d_points = temp_points   #-----vertex.list without "double.vertices"
1616                 #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------
1617
1618                 #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------
1619                 if len(d_points) < 2:  #if too few vertex, then return
1620                         #print 'deb:drawPoly2d corrupted Vertices' #---------
1621                         return
1622
1623                 # analyze of straight- and bulge-segments
1624                 # generation of additional points for bulge segments
1625                 arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad'])
1626                 wide_segment_exist = False
1627                 bulg_points = []  # for each point set None (or center for arc-subPoints)
1628                 for i in xrange(len(d_points)-1):
1629                         point1 = d_points[i]
1630                         point2 = d_points[i+1]
1631                         #print 'deb:drawPoly2d_bulg tocalc.point1:', point1 #------------------------
1632                         #print 'deb:drawPoly2d_bulg tocalc.point2:', point2 #------------------------
1633
1634                         swidth = point1.swidth
1635                         ewidth = point1.ewidth
1636                         if swidth == None: swidth = swidth_default
1637                         if ewidth == None: ewidth = ewidth_default
1638                         if swidth != 0.0 or ewidth != 0.0: wide_segment_exist = True
1639
1640                         if settings.var['width_force']:  # force minimal width for thin segments
1641                                 width_min = settings.var['width_min']
1642                                 if swidth < width_min: swidth = width_min
1643                                 if ewidth < width_min: ewidth = width_min
1644                                 if not settings.var['width_on']:  # then force minimal width for all segments
1645                                         swidth = width_min
1646                                         ewidth = width_min
1647
1648                         #if point1.bulge and (i < (len(d_points)-1) or self.closed):
1649                         if point1.bulge and i < (len(d_points)-1): #10_b8
1650                                 verts, center = calcBulge(point1, point2, arc_res) #calculate additional points for bulge
1651                                 points.extend(verts)
1652                                 delta_width = (ewidth - swidth) / len(verts)
1653                                 width_list = [swidth + (delta_width * ii) for ii in xrange(len(verts)+1)]
1654                                 swidths.extend(width_list[:-1])
1655                                 ewidths.extend(width_list[1:])
1656                                 bulg_list = [center for ii in xrange(len(verts))]
1657                                 #the last point in bulge has index False for better indexing of bulg_end!
1658                                 bulg_list[-1] = None
1659                                 bulg_points.extend(bulg_list)
1660
1661                         else:
1662                                 points.append(point1.loc)
1663                                 swidths.append(swidth)
1664                                 ewidths.append(ewidth)
1665                                 bulg_points.append(None)
1666                 points.append(d_points[-1].loc)
1667
1668
1669                 #--calculate width_vectors: left-side- and right-side-points ----------------
1670                 # 1.level:IF width  ---------------------------------------
1671                 if (settings.var['width_on'] and wide_segment_exist) or settings.var['width_force']:
1672                         #new_b8 points.append(d_points[0].loc)  #temporarly add first vertex at the end (for better loop)
1673                         dist_min05 = 0.5 * settings.var['dist_min'] #minimal width for zero_witdh
1674                         
1675                         pointsLs = []   # list of left-start-points
1676                         pointsLe = []   # list of left-end-points
1677                         pointsRs = []   # list of right-start-points
1678                         pointsRe = []   # list of right-end-points
1679                         pointsW  = []   # list of all border-points
1680                         #rotMatr90 = Mathutils.Matrix(rotate 90 degree around Z-axis) = normalvectorXY
1681                         rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1])
1682                         bulg_in = False
1683                         last_bulg_point = False
1684                         for i in xrange(len(points)-1):
1685                                 point1 = points[i]
1686                                 point2 = points[i+1]
1687                                 point1vec = Mathutils.Vector(point1)
1688                                 point2vec = Mathutils.Vector(point2)
1689                                 swidth05 = swidths[i] * 0.5
1690                                 ewidth05 = ewidths[i] * 0.5
1691                                 if swidth05 == 0: swidth05 = dist_min05
1692                                 if ewidth05 == 0: ewidth05 = dist_min05
1693                                 normal_vector = rotMatr90 * (point2vec-point1vec).normalize()
1694                                 if last_bulg_point:
1695                                         last_bulg_point = False
1696                                         bulg_in = True
1697                                 elif bulg_points[i] != None:
1698                                         centerVec = Mathutils.Vector(bulg_points[i])
1699                                         if bulg_points[i+1] == None: last_bulg_point = True
1700                                         bulg_in = True
1701                                 else: bulg_in = False
1702
1703                                 if bulg_in:
1704                                         #makes clean intersections for arc-segments
1705                                         radius1vec = point1vec - centerVec
1706                                         radius2vec = point2vec - centerVec
1707                                         angle = Mathutils.AngleBetweenVecs(normal_vector, radius1vec)
1708                                         if angle < 90.0:
1709                                                 normal_vector1 = radius1vec.normalize()
1710                                                 normal_vector2 = radius2vec.normalize()
1711                                         else:   
1712                                                 normal_vector1 = - radius1vec.normalize()
1713                                                 normal_vector2 = - radius2vec.normalize()
1714
1715                                         swidth05vec = swidth05 * normal_vector1
1716                                         ewidth05vec = ewidth05 * normal_vector2
1717                                         pointsLs.append(point1vec + swidth05vec) #vertex left start
1718                                         pointsRs.append(point1vec - swidth05vec) #vertex right start
1719                                         pointsLe.append(point2vec + ewidth05vec) #vertex left end
1720                                         pointsRe.append(point2vec - ewidth05vec) #vertex right end
1721
1722                                 else:
1723                                         swidth05vec = swidth05 * normal_vector
1724                                         ewidth05vec = ewidth05 * normal_vector
1725                                         pointsLs.append(point1vec + swidth05vec) #vertex left start
1726                                         pointsRs.append(point1vec - swidth05vec) #vertex right start
1727                                         pointsLe.append(point2vec + ewidth05vec) #vertex left end
1728                                         pointsRe.append(point2vec - ewidth05vec) #vertex right end
1729         
1730                         # additional last point is also calculated
1731                         #pointsLs.append(pointsLs[0])
1732                         #pointsRs.append(pointsRs[0])
1733                         #pointsLe.append(pointsLe[0])
1734                         #pointsRe.append(pointsRe[0])
1735
1736                         pointsLc, pointsRc = [], [] # lists Left/Right corners = intersection points
1737
1738                         # 2.level:IF width and corner-trim
1739                         if settings.var['pl_trim_on']:  #optional clean corner-intersections
1740                                 # loop preset
1741                                 # set STARTpoints of the first point points[0]
1742                                 if not self.closed:
1743                                         pointsLc.append(pointsLs[0])
1744                                         pointsRc.append(pointsRs[0])
1745                                 else:
1746                                         pointsLs.append(pointsLs[0])
1747                                         pointsRs.append(pointsRs[0])
1748                                         pointsLe.append(pointsLe[0])
1749                                         pointsRe.append(pointsRe[0])
1750                                         points.append(points[0])
1751                                 vecL3, vecL4 = pointsLs[0], pointsLe[0]
1752                                 vecR3, vecR4 = pointsRs[0], pointsRe[0]
1753                                 lenL = len(pointsLs)-1
1754                                 #print 'deb:drawPoly2d pointsLs():\n',  pointsLs  #----------------
1755                                 #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs)  #----------------
1756                                 bulg_in = False
1757                                 last_bulg_point = False
1758
1759                                 # LOOP: makes (ENDpoints[i],STARTpoints[i+1])
1760                                 for i in xrange(lenL):
1761                                         if bulg_points[i] != None:
1762                                                 if bulg_points[i+1] == None: #makes clean intersections for arc-segments
1763                                                         last_bulg_point = True
1764                                                 if not bulg_in:
1765                                                         bulg_in = True
1766                                                         #pointsLc.extend((points[i], pointsLs[i]))
1767                                                         #pointsRc.extend((points[i], pointsRs[i]))
1768                                         vecL1, vecL2 = vecL3, vecL4
1769                                         vecR1, vecR2 = vecR3, vecR4
1770                                         vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1]
1771                                         vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1]
1772                                         #compute left- and right-cornerpoints
1773                                         #cornerpointL = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4)
1774                                         cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4)
1775                                         cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4)
1776                                         #print 'deb:drawPoly2d cornerpointL: ', cornerpointL  #-------------
1777                                         #print 'deb:drawPoly2d cornerpointR: ', cornerpointR  #-------------
1778
1779                                         # IF not cornerpoint THEN check if identic start-endpoints (=collinear segments)
1780                                         if cornerpointL == None or cornerpointR == None:
1781                                                 if vecL2 == vecL3 and vecR2 == vecR3:
1782                                                         #print 'deb:drawPoly2d pointVec: ####### identic ##########' #----------------
1783                                                         pointsLc.append(pointsLe[i])
1784                                                         pointsRc.append(pointsRe[i])
1785                                                 else:
1786                                                         pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1]))
1787                                                         pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1]))
1788                                         else:
1789                                                 cornerpointL = cornerpointL[0] # because Mathutils.LineIntersect() -> (pkt1,pkt2)
1790                                                 cornerpointR = cornerpointR[0]
1791                                                 #print 'deb:drawPoly2d cornerpointL: ', cornerpointL  #-------------
1792                                                 #print 'deb:drawPoly2d cornerpointR: ', cornerpointR  #-------------
1793                                                 pointVec0 = Mathutils.Vector(points[i])
1794                                                 pointVec = Mathutils.Vector(points[i+1])
1795                                                 pointVec2 = Mathutils.Vector(points[i+2])
1796                                                 #print 'deb:drawPoly2d pointVec0: ', pointVec0  #-------------
1797                                                 #print 'deb:drawPoly2d pointVec: ', pointVec  #-------------
1798                                                 #print 'deb:drawPoly2d pointVec2: ', pointVec2  #-------------
1799                                                 # if diststance(cornerL-center-cornerR) < limiter * (seg1_endWidth + seg2_startWidth)
1800                                                 max_cornerDist = (vecL2 - vecR2).length + (vecL3 - vecR3).length
1801                                                 is_cornerDist = (cornerpointL - pointVec).length + (cornerpointR - pointVec).length
1802                                                 #corner_angle = Mathutils.AngleBetweenVecs((pointVec0 - pointVec),(pointVec - pointVec2))
1803                                                 #print 'deb:drawPoly2d corner_angle: ', corner_angle  #-------------
1804                                                 #print 'deb:drawPoly2d max_cornerDist, is_cornerDist: ', max_cornerDist, is_cornerDist  #-------------
1805                                                 #if abs(corner_angle) < 90.0:
1806                                                 # intersection --------- limited by TRIM_LIMIT (1.0 - 5.0)
1807                                                 if is_cornerDist < max_cornerDist * settings.var['pl_trim_max']:
1808                                                         # clean corner intersection
1809                                                         pointsLc.append(cornerpointL)
1810                                                         pointsRc.append(cornerpointR)
1811                                                 elif False: # the standard no-intersection
1812                                                         # --todo-- not optimal, because produces X-face
1813                                                         pointsLc.extend((pointsLe[i],pointsLs[i+1]))
1814                                                         pointsRc.extend((pointsRe[i],pointsRs[i+1]))
1815                                                 elif False: # --todo-- the optimised non-intersection
1816                                                         if (cornerpointL - vecL1).length < (cornerpointR - vecR1).length:
1817                                                                 left_angle = True
1818                                                         else:
1819                                                                 left_angle = False
1820                                                         limit_dist = settings.var['dist_min']
1821                                                         if left_angle:  # if left turning angle
1822                                                                 print 'deb:drawPoly2d it is left turning angle' #-------------
1823                                                                 # to avoid triangelface/doubleVertex
1824                                                                 delta1 = (cornerpointL - vecL1).normalize() * limit_dist
1825                                                                 delta4 = (cornerpointL - vecL4).normalize() * limit_dist
1826                                                                 pointsLc.extend((cornerpointL - delta1, cornerpointL - delta4))
1827                                                                 pointsRc.extend((pointsRe[i],pointsRs[i+1]))
1828                                                         else:  # if right turning angle
1829                                                                 print 'deb:drawPoly2d right turning angle' #-------------
1830                                                                 delta1 = (cornerpointR - vecR1).normalize() * limit_dist
1831                                                                 delta4 = (cornerpointR - vecR4).normalize() * limit_dist
1832                                                                 pointsRc.extend((cornerpointR - delta1, cornerpointR - delta4))
1833                                                                 pointsLc.extend((pointsLe[i],pointsLs[i+1]))
1834                                                 else:
1835                                                         pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1]))
1836                                                         pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1]))
1837                                 if not self.closed:
1838                                         pointsLc.append(pointsLe[-1])
1839                                         pointsRc.append(pointsRe[-1])
1840
1841                         # 2.level:IF width but no-trim
1842                         else:
1843                                 # loop preset
1844                                 # set STARTpoints of the first point points[0]
1845                                 if not self.closed:
1846                                         pointsLc.append(pointsLs[0])
1847                                         pointsRc.append(pointsRs[0])
1848                                 else:
1849                                         pointsLs.append(pointsLs[0])
1850                                         pointsRs.append(pointsRs[0])
1851                                         pointsLe.append(pointsLe[0])
1852                                         pointsRe.append(pointsRe[0])
1853                                         points.append(points[0])
1854                                 vecL3, vecL4 = pointsLs[0], pointsLe[0]
1855                                 vecR3, vecR4 = pointsRs[0], pointsRe[0]
1856                                 lenL = len(pointsLs)-1
1857                                 #print 'deb:drawPoly2d pointsLs():\n',  pointsLs  #----------------
1858                                 #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs)  #----------------
1859                                 bulg_in = False
1860                                 last_bulg_point = False
1861
1862                                 # LOOP: makes (ENDpoints[i],STARTpoints[i+1])
1863                                 for i in xrange(lenL):
1864                                         vecL1, vecL2 = vecL3, vecL4
1865                                         vecR1, vecR2 = vecR3, vecR4
1866                                         vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1]
1867                                         vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1]
1868                                         if bulg_points[i] != None:
1869                                                 #compute left- and right-cornerpoints
1870                                                 if True:
1871                                                         cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4)
1872                                                         cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4)
1873                                                         pointsLc.append(cornerpointL[0])
1874                                                         pointsRc.append(cornerpointR[0])
1875                                                 else:
1876                                                         pointVec = Mathutils.Vector(point[i])
1877
1878                                         else: # IF non-bulg
1879                                                 pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1]))
1880                                                 pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1]))
1881                                 if not self.closed:
1882                                         pointsLc.append(pointsLe[-1])
1883                                         pointsRc.append(pointsRe[-1])
1884
1885                         len1 = len(pointsLc)
1886                         #print 'deb:drawPoly2d len1:', len1  #-----------------------
1887                         #print 'deb:drawPoly2d len1 len(pointsLc),len(pointsRc):', len(pointsLc),len(pointsRc)  #-----------------------
1888                         pointsW = pointsLc + pointsRc  # all_points_List = left_side + right_side
1889                         #print 'deb:drawPoly2d pointsW():\n',  pointsW  #----------------
1890
1891                         # 2.level:IF width and thickness  ---------------------
1892                         if thic != 0:
1893                                 thic_pointsW = []
1894                                 thic_pointsW.extend([[point[0], point[1], point[2]+thic] for point in pointsW])
1895                                 if thic < 0.0:
1896                                         thic_pointsW.extend(pointsW)
1897                                         pointsW = thic_pointsW
1898                                 else:
1899                                         pointsW.extend(thic_pointsW)
1900                                 faces = []
1901                                 f_start, f_end = [], []
1902                                 f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)]
1903                                 f_top   = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)]
1904                                 f_left   = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)]
1905                                 f_right  = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)]
1906
1907                                 if self.closed:
1908                                         f_bottom.append([len1-1, 0, len1, len1+len1-1])  #bottom face
1909                                         f_top.append(   [len1+len1+len1-1, len1+len1+len1+len1-1, len1+len1+len1, len1+len1+0])  #top face
1910                                         f_left.append(  [0, len1-1, len1+len1+len1-1, len1+len1])  #left face
1911                                         f_right.append( [len1, len1+len1+len1, len1+len1+len1+len1-1, len1+len1-1])  #right face
1912                                 else:
1913                                         f_start = [[0, len1, len1+len1+len1, len1+len1]]
1914                                         f_end   = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]]
1915
1916                                 faces = f_left + f_right + f_bottom + f_top + f_start + f_end
1917                                 #faces = f_bottom + f_top
1918                                 #faces = f_left + f_right + f_start + f_end
1919                                 #print 'deb:faces_list:\n', faces  #-----------------------
1920                                 me = Mesh.New(obname)             # create a new mesh
1921                                 ob = SCENE.objects.new(me) # create a new mesh_object
1922                                 me.verts.extend(pointsW)                # add vertices to mesh
1923                                 me.faces.extend(faces)  # add faces to the mesh
1924
1925                                 # each MeshSide becomes vertexGroup for easier material assignment ---------------------
1926                                 # The mesh must first be linked to an object so the method knows which object to update.
1927                                 # This is because vertex groups in Blender are stored in the object -- not in the mesh,
1928                                 # which may be linked to more than one object.
1929                                 if settings.var['vGroup_on']:
1930                                         # each MeshSide becomes vertexGroup for easier material assignment ---------------------
1931                                         replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
1932                                         vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
1933                                         for v in f_left: vg_left.extend(v)
1934                                         for v in f_right: vg_right.extend(v)
1935                                         for v in f_top: vg_top.extend(v)
1936                                         for v in f_bottom: vg_bottom.extend(v)
1937                                         me.addVertGroup('side.left')  ; me.assignVertsToGroup('side.left',  list(set(vg_left)), 1.0, replace)
1938                                         me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace)
1939                                         me.addVertGroup('side.top')   ; me.assignVertsToGroup('side.top',   list(set(vg_top)), 1.0, replace)
1940                                         me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
1941                                         if not self.closed:
1942                                                 me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace)
1943                                                 me.addVertGroup('side.end')  ; me.assignVertsToGroup('side.end',   f_end[0],   1.0, replace)
1944
1945                                 if settings.var['meshSmooth_on']:  # left and right side become smooth ----------------------
1946                                         #if self.spline or self.curved:
1947                                         if True:
1948                                                 smooth_len = len(f_left) + len(f_right)
1949                                                 for i in xrange(smooth_len):
1950                                                         me.faces[i].smooth = True
1951                                                 #me.Modes(AUTOSMOOTH)
1952
1953                         # 2.level:IF width, but no-thickness  ---------------------
1954                         else:
1955                                 faces = []
1956                                 faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)]
1957                                 if self.closed:
1958                                         faces.append([len1, 0, len1-1, len1+len1-1])
1959                                 me = Mesh.New(obname)             # create a new mesh
1960                                 ob = SCENE.objects.new(me) # create a new mesh_object
1961                                 me.verts.extend(pointsW)                # add vertices to mesh
1962                                 me.faces.extend(faces)  # add faces to the mesh
1963
1964
1965                 # 1.level:IF no-width, but thickness ---------------------
1966                 elif thic != 0:
1967                         len1 = len(points)
1968                         thic_points = []
1969                         thic_points.extend([[point[0], point[1], point[2]+thic] for point in points])
1970                         if thic < 0.0:
1971                                 thic_points.extend(points)
1972                                 points = thic_points
1973                         else:
1974                                 points.extend(thic_points)
1975                         faces = []
1976                         faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)]
1977                         if self.closed:
1978                                 faces.append([len1-1, 0, len1, 2*len1-1])
1979                         me = Mesh.New(obname)             # create a new mesh
1980                         ob = SCENE.objects.new(me) # create a new mesh_object
1981                         me.verts.extend(points)   # add vertices to mesh
1982                         me.faces.extend(faces)  # add faces to the mesh
1983
1984                         if settings.var['meshSmooth_on']:  # left and right side become smooth ----------------------
1985                                 #if self.spline or self.curved:
1986                                 if True:
1987                                         for i in xrange(len(faces)):
1988                                                 me.faces[i].smooth = True
1989                                         #me.Modes(AUTOSMOOTH)
1990
1991                 # 1.level:IF no-width and no-thickness  ---------------------
1992                 else:
1993                         edges = [[num, num+1] for num in xrange(len(points)-1)]
1994                         if self.closed:
1995                                 edges.append([len(points)-1, 0])
1996                         me = Mesh.New(obname)             # create a new mesh
1997                         ob = SCENE.objects.new(me) # create a new mesh_object
1998                         me.verts.extend(points)   # add vertices to mesh
1999                         me.edges.extend(edges)  # add edges to the mesh
2000
2001                 transform(self.extrusion, 0, ob)
2002                 #print 'deb:polyline.draw.END:----------------' #-----------------------
2003                 return ob
2004
2005
2006
2007
2008 class Vertex(object):  #-----------------------------------------------------------------
2009         """Generic vertex object used by POLYLINEs (and maybe others).
2010         """
2011
2012         def __init__(self, obj=None):
2013                 """Initializes vertex data.
2014
2015                 The optional obj arg is an entity object of type vertex.
2016                 """
2017                 #print 'deb:Vertex.init.START:----------------' #-----------------------
2018                 self.loc = [0,0,0]
2019                 self.face = []
2020                 self.swidth = 0
2021                 self.ewidth = 0
2022                 self.bulge = 0
2023                 if obj is not None:
2024                         if not obj.type == 'vertex':
2025                                 raise TypeError, "Wrong type %s for vertex object!" %obj.type
2026                         self.type = obj.type
2027                         self.data = obj.data[:]
2028                         self.get_props(obj.data)
2029                 #print 'deb:Vertex.init.END:----------------' #------------------------
2030
2031
2032         def get_props(self, data):
2033                 """Gets coords for a VERTEX type object.
2034
2035                 Each vert can have a number of properties.
2036                 Verts should be coded as
2037                 10:xvalue
2038                 20:yvalue
2039                 40:startwidth or 0
2040                 41:endwidth or 0
2041                 42:bulge or 0
2042                 """
2043                 self.x = getit(data, 10, None)
2044                 self.y = getit(data, 20, None)
2045                 self.z = getit(data, 30, None)
2046
2047                 self.flags  = getit(data, 70, 0) # flags
2048                 self.curved = self.flags&1   # Bezier-curve-fit:additional-vertex
2049                 self.curv_t = self.flags&2   # Bezier-curve-fit:tangent exists
2050                 self.spline = self.flags&8   # Bspline-fit:additional-vertex
2051                 self.splin2 = self.flags&16  # Bspline-fit:control-vertex
2052                 self.poly3d = self.flags&32  # polyline3d:control-vertex
2053                 self.plmesh = self.flags&64  # polymesh3d:control-vertex
2054                 self.plface = self.flags&128 # polyface
2055
2056                 # if PolyFace.Vertex with Face_definition
2057                 if self.curv_t:
2058                         self.curv_tangent =  getit(data, 50, None) # curve_tangent
2059
2060                 if self.plface and not self.plmesh:
2061                                 v1 = getit(data, 71, 0) # polyface:Face.vertex 1.
2062                                 v2 = getit(data, 72, 0) # polyface:Face.vertex 2.
2063                                 v3 = getit(data, 73, 0) # polyface:Face.vertex 3.
2064                                 v4 = getit(data, 74, None) # polyface:Face.vertex 4.
2065                                 self.face = [abs(v1)-1,abs(v2)-1,abs(v3)-1]
2066                                 if v4 != None:
2067                                         if abs(v4) != abs(v1):
2068                                                 self.face.append(abs(v4)-1)
2069                 else:   #--parameter for polyline2d
2070                         self.swidth = getit(data, 40, None) # start width
2071                         self.ewidth = getit(data, 41, None) # end width
2072                         self.bulge  = getit(data, 42, 0) # bulge of segment
2073
2074
2075         def __len__(self):
2076                 return 3
2077
2078
2079         def __getitem__(self, key):
2080                 return self.loc[key]
2081
2082
2083         def __setitem__(self, key, value):
2084                 if key in [0,1,2]:
2085                         self.loc[key]
2086
2087
2088         def __iter__(self):
2089                 return self.loc.__iter__()
2090
2091
2092         def __str__(self):
2093                 return str(self.loc)
2094
2095
2096         def __repr__(self):
2097                 return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s, face=%s" %(self.loc, self.swidth, self.ewidth, self.bulge, self.face)
2098
2099
2100         def getx(self):
2101                 return self.loc[0]
2102         def setx(self, value):
2103                 self.loc[0] = value
2104         x = property(getx, setx)
2105
2106
2107         def gety(self):
2108                 return self.loc[1]
2109         def sety(self, value):
2110                 self.loc[1] = value
2111         y = property(gety, sety)
2112
2113
2114         def getz(self):
2115                 return self.loc[2]
2116         def setz(self, value):
2117                 self.loc[2] = value
2118         z = property(getz, setz)
2119
2120
2121
2122 class Text:  #-----------------------------------------------------------------
2123         """Class for objects representing dxf TEXT.
2124         """
2125         def __init__(self, obj):
2126                 """Expects an entity object of type text as input.
2127                 """
2128                 if not obj.type == 'text':
2129                         raise TypeError, "Wrong type %s for text object!" %obj.type
2130                 self.type = obj.type
2131                 self.data = obj.data[:]
2132
2133                 # required data
2134                 self.height = 1.7 * obj.get_type(40)[0]  #text.height
2135                 self.value = obj.get_type(1)[0]   #The text string value
2136
2137                 # optional data (with defaults)
2138                 self.space = getit(obj, 67, 0)
2139                 self.color_index = getit(obj, 62, BYLAYER)
2140                 self.thic =  getit(obj, 39, 0)
2141
2142                 self.rotation = getit(obj, 50, 0)  # radians
2143                 self.width_factor = getit(obj, 41, 1) # Scaling factor along local x axis
2144                 self.oblique = getit(obj, 51, 0) # oblique angle: skew in degrees -90 <= oblique <= 90
2145
2146                 #self.style = getit(obj, 7, 'STANDARD') # --todo---- Text style name (optional, default = STANDARD)
2147
2148                 #Text generation flags (optional, default = 0):
2149                 #2 = backward (mirrored in X),
2150                 #4 = upside down (mirrored in Y)
2151                 self.flags = getit(obj, 71, 0)
2152                 self.mirrorX, self.mirrorY = 1.0, 1.0
2153                 if self.flags&2: self.mirrorX = - 1.0
2154                 if self.flags&4: self.mirrorY = - 1.0
2155
2156                 # vertical.alignment: 0=baseline, 1=bottom, 2=middle, 3=top
2157                 self.valignment = getit(obj, 73, 0)
2158                 #Horizontal text justification type (optional, default = 0) integer codes (not bit-coded)
2159                 #0=left, 1=center, 2=right
2160                 #3=aligned, 4=middle, 5=fit
2161                 self.halignment = getit(obj, 72, 0)
2162
2163                 self.layer = getit(obj.data, 8, None)
2164                 self.loc1, self.loc2 = self.get_loc(obj.data)
2165                 if self.loc2[0] != None and self.halignment != 5: 
2166                         self.loc = self.loc2
2167                 else:
2168                         self.loc = self.loc1
2169                 self.extrusion = get_extrusion(obj.data)
2170
2171
2172
2173         def get_loc(self, data):
2174                 """Gets adjusted location for text type objects.
2175
2176                 If group 72 and/or 73 values are nonzero then the first alignment point values
2177                 are ignored and AutoCAD calculates new values based on the second alignment
2178                 point and the length and height of the text string itself (after applying the
2179                 text style). If the 72 and 73 values are zero or missing, then the second
2180                 alignment point is meaningless.
2181                 I don't know how to calc text size...
2182                 """
2183                 # bottom left x, y, z and justification x, y, z = 0
2184                 #x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0
2185                 x  = getit(data, 10, None) #First alignment point (in OCS). 
2186                 y  = getit(data, 20, None)
2187                 z  = getit(data, 30, 0.0)
2188                 jx = getit(data, 11, None) #Second alignment point (in OCS). 
2189                 jy = getit(data, 21, None)
2190                 jz = getit(data, 31, 0.0)
2191                 return [x, y, z],[jx, jy, jz]
2192
2193
2194         def __repr__(self):
2195                 return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
2196
2197
2198         def draw(self, settings):
2199                 """for TEXTs: generate Blender_geometry.
2200                 """
2201                 obname = 'tx_%s' %self.layer  # create object name from layer name
2202                 obname = obname[:MAX_NAMELENGTH]
2203                 txt = Text3d.New(obname)
2204                 ob = SCENE.objects.new(txt) # create a new text_object
2205
2206                 txt.setText(self.value)
2207                 txt.setSize(1.0) #Blender<2.45 accepts only (0.0 - 5.0)
2208                 #txt.setSize(self.height)
2209                 #txt.setWidth(self.bold)
2210                 #setLineSeparation(sep)
2211                 txt.setShear(self.oblique/90)
2212
2213                 thic = set_thick(self.thic, settings)
2214                 if thic != 0.0:
2215                         thic = self.thic * 0.5
2216                         self.loc[2] += thic
2217                         txt.setExtrudeDepth(1.0)  #Blender<2.45 accepts only (0.1 - 10.0)
2218                 if self.halignment == 0:
2219                         align = Text3d.LEFT
2220                 elif self.halignment == 1:
2221                         align = Text3d.MIDDLE
2222                 elif self.halignment == 2:
2223                         align = Text3d.RIGHT
2224                 else:
2225                         align = Text3d.LEFT
2226                 txt.setAlignment(align)
2227
2228                 if self.valignment == 1:
2229                         txt.setYoffset(0.0)
2230                 elif self.valignment == 2:
2231                         txt.setYoffset(- self.height * 0.5)
2232                 elif self.valignment == 3:
2233                         txt.setYoffset(- self.height)
2234
2235                 # move the object center to the text location
2236                 ob.loc = tuple(self.loc)
2237                 transform(self.extrusion, self.rotation, ob)
2238
2239                 # flip it and scale it to the text width
2240                 ob.SizeX *= self.height * self.width_factor * self.mirrorX
2241                 ob.SizeY *= self.height * self.mirrorY
2242                 if thic != 0.0: ob.SizeZ *= abs(thic)
2243                 return ob
2244
2245
2246         
2247 def set_thick(thickness, settings):
2248         """Set thickness relative to settings variables.
2249         
2250         Set thickness relative to settings variables:
2251         'thick_on','thick_force','thick_min'.
2252         Accepted also minus values of thickness
2253         python trick: sign(x)=cmp(x,0)
2254         """
2255         if settings.var['thick_force']:
2256                 if settings.var['thick_on']:
2257                         if abs(thickness) <  settings.var['thick_min']:
2258                                 thic = settings.var['thick_min'] * cmp(thickness,0)
2259                         else: thic = thickness
2260                 else: thic = settings.var['thick_min']
2261         else: 
2262                 if settings.var['thick_on']: thic = thickness
2263                 else: thic = 0.0
2264         return thic
2265
2266
2267
2268
2269 class Mtext:  #-----------------------------------------------------------------
2270         """Class for objects representing dxf MTEXT.
2271         """
2272
2273         def __init__(self, obj):
2274                 """Expects an entity object of type mtext as input.
2275                 """
2276                 if not obj.type == 'mtext':
2277                         raise TypeError, "Wrong type %s for mtext object!" %obj.type
2278                 self.type = obj.type
2279                 self.data = obj.data[:]
2280
2281                 # required data
2282                 self.height = obj.get_type(40)[0]
2283                 self.width = obj.get_type(41)[0]
2284                 self.alignment = obj.get_type(71)[0] # alignment 1=TL, 2=TC, 3=TR, 4=ML, 5=MC, 6=MR, 7=BL, 8=BC, 9=BR
2285                 self.value = self.get_text(obj.data) # The text string value
2286
2287                 # optional data (with defaults)
2288                 self.space = getit(obj, 67, 0)
2289                 self.color_index = getit(obj, 62, BYLAYER)
2290                 self.rotation = getit(obj, 50, 0)  # radians
2291
2292                 self.width_factor = getit(obj, 42, 1) # Scaling factor along local x axis
2293                 self.line_space = getit(obj, 44, 1) # percentage of default
2294
2295                 self.layer = getit(obj.data, 8, None)
2296                 self.loc = self.get_loc(obj.data)
2297                 self.extrusion = get_extrusion(obj.data)
2298
2299
2300         def get_text(self, data):
2301                 """Reconstructs mtext data from dxf codes.
2302                 """
2303                 primary = ''
2304                 secondary = []
2305                 for item in data:
2306                         if item[0] == 1: # There should be only one primary...
2307                                 primary = item[1]
2308                         elif item[0] == 3: # There may be any number of extra strings (in order)
2309                                 secondary.append(item[1])
2310                 if not primary:
2311                         #raise ValueError, "Empty Mtext Object!"
2312                         string = "Empty Mtext Object!"
2313                 if not secondary:
2314                         string = primary.replace(r'\P', '\n')
2315                 else:
2316                         string = ''.join(secondary)+primary
2317                         string = string.replace(r'\P', '\n')
2318                 return string
2319
2320
2321         def get_loc(self, data):
2322                 """Gets location for a mtext type objects.
2323
2324                 Mtext objects have only one point indicating 
2325                 """      
2326                 loc = [0, 0, 0]
2327                 loc[0] = getit(data, 10, None)
2328                 loc[1] = getit(data, 20, None)
2329                 loc[2] = getit(data, 30, 0.0)
2330                 return loc
2331
2332
2333         def __repr__(self):
2334                 return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
2335
2336
2337         def draw(self, settings):
2338                 """for MTEXTs: generate Blender_geometry.
2339                 """
2340                 # Now Create an object
2341                 obname = 'tm_%s' %self.layer  # create object name from layer name
2342                 obname = obname[:MAX_NAMELENGTH]
2343                 txt = Text3d.New(obname)
2344                 ob = SCENE.objects.new(txt) # create a new text_object
2345
2346                 txt.setSize(1)
2347                 # Blender doesn't give access to its text object width currently
2348                 # only to the text3d's curve width...
2349                 #txt.setWidth(text.width/10)
2350                 txt.setLineSeparation(self.line_space)
2351                 txt.setExtrudeDepth(0.5)
2352                 txt.setText(self.value)
2353
2354                 # scale it to the text size
2355                 ob.SizeX = self.height * self.width_factor
2356                 ob.SizeY = self.height
2357                 ob.SizeZ = self.height
2358
2359                 # move the object center to the text location
2360                 ob.loc = tuple(self.loc)
2361                 transform(self.extrusion, self.rotation, ob)
2362
2363                 return ob
2364
2365
2366
2367
2368 class Circle:  #-----------------------------------------------------------------
2369         """Class for objects representing dxf CIRCLEs.
2370         """
2371
2372         def __init__(self, obj):
2373                 """Expects an entity object of type circle as input.
2374                 """
2375                 if not obj.type == 'circle':
2376                         raise TypeError, "Wrong type %s for circle object!" %obj.type
2377                 self.type = obj.type
2378                 self.data = obj.data[:]
2379
2380                 # required data
2381                 self.radius = obj.get_type(40)[0]
2382
2383                 # optional data (with defaults)
2384                 self.space = getit(obj, 67, 0)
2385                 self.thic =  getit(obj, 39, 0)
2386                 self.color_index = getit(obj, 62, BYLAYER)
2387
2388                 self.layer = getit(obj.data, 8, None)
2389                 self.loc = self.get_loc(obj.data)
2390                 self.extrusion = get_extrusion(obj.data)
2391
2392
2393
2394         def get_loc(self, data):
2395                 """Gets the center location for circle type objects.
2396
2397                 Circles have a single coord location.
2398                 """
2399                 loc = [0, 0, 0]
2400                 loc[0] = getit(data, 10, None)
2401                 loc[1] = getit(data, 20, None)
2402                 loc[2] = getit(data, 30, 0.0)
2403                 return loc
2404
2405
2406
2407         def __repr__(self):
2408                 return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
2409
2410
2411         def draw(self, settings):
2412                 """for CIRCLE: generate Blender_geometry.
2413                 """
2414                 obname = 'ci_%s' %self.layer  # create object name from layer name
2415                 obname = obname[:MAX_NAMELENGTH]
2416                 radius = self.radius
2417
2418                 thic = set_thick(self.thic, settings)
2419                 width = 0.0
2420                 if settings.var['lines_as'] == 4: # as thin_box
2421                         thic = settings.var['thick_min']
2422                         width = settings.var['width_min']
2423                 if settings.var['lines_as'] == 3: # as thin cylinder
2424                         cyl_rad = 0.5 * settings.var['width_min']
2425
2426                 if settings.var['lines_as'] == 5:  # draw CIRCLE as curve -------------
2427                         if True:  # universal version
2428                                 arc_res = settings.var['curve_arc']
2429                                 #arc_res = 3
2430                                 start, end = 0.0, 360.0
2431                                 VectorTriples = calcArc(None, radius, start, end, arc_res, True)
2432                                 c = Curve.New(obname) # create new curve data
2433                                 curve = c.appendNurb(BezTriple.New(VectorTriples[0]))
2434                                 for p in VectorTriples[1:-1]:
2435                                         curve.append(BezTriple.New(p))
2436                                 for point in curve:
2437                                         point.handleTypes = [FREE, FREE]
2438                         else:   # standard version
2439                                 c = Curve.New(obname)   # create new curve data
2440                                 p1 = (0, -radius, 0)
2441                                 p2 = (radius, 0, 0)
2442                                 p3 = (0, radius, 0)
2443                                 p4 = (-radius, 0, 0)
2444         
2445                                 p1 = BezTriple.New(p1)
2446                                 p2 = BezTriple.New(p2)
2447                                 p3 = BezTriple.New(p3)
2448                                 p4 = BezTriple.New(p4)
2449         
2450                                 curve = c.appendNurb(p1)
2451                                 curve.append(p2)
2452                                 curve.append(p3)
2453                                 curve.append(p4)
2454                                 for point in curve:
2455                                         point.handleTypes = [AUTO, AUTO]
2456
2457                         curve.flagU = 1  # 1 sets the curve cyclic=closed
2458                         if settings.var['fill_on']:
2459                                 c.setFlag(6) # 2+4 set top and button caps
2460                         else:
2461                                 c.setFlag(c.getFlag() & ~6) # dont set top and button caps
2462
2463                         c.setResolu(settings.var['curve_res'])
2464                         c.update()
2465
2466                         #--todo-----to check---------------------------
2467                         ob = SCENE.objects.new(c) # create a new curve_object
2468                         ob.loc = tuple(self.loc)
2469                         if thic != 0.0: #hack: Blender<2.45 curve-extrusion
2470                                 thic = thic * 0.5
2471                                 c.setExt1(1.0)  # curve-extrusion accepts only (0.0 - 2.0)
2472                                 ob.LocZ = thic + self.loc[2]
2473                         transform(self.extrusion, 0, ob)
2474                         if thic != 0.0:
2475                                 ob.SizeZ *= abs(thic)
2476                         return ob
2477
2478                 elif False: # create a new mesh_object with buildin_circle_primitive
2479                         verts_num = settings.var['arc_res'] * sqrt(radius / settings.var['arc_rad'])
2480                         if verts_num > 100: verts_num = 100 # Blender accepts only values [3:500]
2481                         if verts_num < 4: verts_num = 4 # Blender accepts only values [3:500]
2482                         if thic != 0:
2483                                 loc2 = thic * 0.5   #-----blenderAPI draw Cylinder with 2*thickness
2484                                 self.loc[2] += loc2  #---new location for the basis of cylinder
2485                                 #print 'deb:circleDraw:self.loc2:', self.loc  #-----------------------
2486                                 c = Mesh.Primitives.Cylinder(int(verts_num), radius*2, abs(thic))
2487                         else:
2488                                 c = Mesh.Primitives.Circle(int(verts_num), radius*2)
2489
2490                         #c.update()
2491                         ob = SCENE.objects.new(c, obname) # create a new circle_mesh_object
2492                         ob.loc = tuple(self.loc)
2493                         transform(self.extrusion, 0, ob)
2494                         return ob
2495
2496                 else:  # draw CIRCLE as mesh -----------------------------------------------
2497                         cir = Mesh.New(obname)           # create a new mesh
2498                         ob = SCENE.objects.new(cir) # create a new circle_object
2499                         # set a number of segments in entire circle
2500                         arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad'])
2501                         start, end = 0.0 , 360.0
2502                         verts = calcArc(None, radius, start, end, arc_res, False)
2503                         verts = verts[:-1] #list without last point/edge (cause by circle it is equal to the first point)
2504                         #print 'deb:circleDraw: verts:', verts  #--------------- 
2505
2506                         if thic != 0:
2507                                 len1 = len(verts)
2508                                 thic_verts = []
2509                                 thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts])
2510                                 if thic < 0.0:
2511                                         thic_verts.extend(verts)
2512                                         verts = thic_verts
2513                                 else:
2514                                         verts.extend(thic_verts)
2515                                 faces = []
2516                                 f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)]
2517                                 #f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1)]
2518                                 f_band.append([len1 - 1, 0, len1, len1 + len1 -1])
2519                                 faces = f_band
2520                                 smooth_len = len(f_band)
2521                                 if settings.var['fill_on']:
2522                                         if thic < 0.0:
2523                                                 verts.append([0,0,thic])  #center of top side
2524                                                 verts.append([0,0,0])  #center of bottom side
2525                                         else:
2526                                                 verts.append([0,0,0])  #center of bottom side
2527                                                 verts.append([0,0,thic])  #center of top side
2528                                         center1 = len(verts)-2
2529                                         center2 = len(verts)-1
2530                                         f_bottom = [[num+1, num, center1] for num in xrange(len1 - 1)]
2531                                         f_bottom.append([0, len1 - 1, center1])
2532                                         f_top = [[num+len1, num+1+len1, center2] for num in xrange(len1 - 1)]
2533                                         f_top.append([len1-1+len1, 0+len1, center2])
2534                                         #print 'deb:circleDraw:verts:', verts  #---------------
2535                                         faces = f_band + f_bottom + f_top
2536                                         #print 'deb:circleDraw:faces:', faces  #---------------
2537                                 cir.verts.extend(verts) # add vertices to mesh
2538                                 cir.faces.extend(faces)  # add faces to the mesh
2539
2540                                 if settings.var['meshSmooth_on']:  # left and right side become smooth ----------------------
2541                                         for i in xrange(smooth_len):
2542                                                 cir.faces[i].smooth = True
2543                                 # each MeshSide becomes vertexGroup for easier material assignment ---------------------
2544                                 if settings.var['vGroup_on']:
2545                                         # each MeshSide becomes vertexGroup for easier material assignment ---------------------
2546                                         replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
2547                                         vg_band, vg_top, vg_bottom = [], [], []
2548                                         for v in f_band: vg_band.extend(v)
2549                                         cir.addVertGroup('side.band')  ; cir.assignVertsToGroup('side.band',  list(set(vg_band)), 1.0, replace)
2550                                         if settings.var['fill_on']:
2551                                                 for v in f_top: vg_top.extend(v)
2552                                                 for v in f_bottom: vg_bottom.extend(v)
2553                                                 cir.addVertGroup('side.top')   ; cir.assignVertsToGroup('side.top',   list(set(vg_top)), 1.0, replace)
2554                                                 cir.addVertGroup('side.bottom'); cir.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
2555
2556                         else: # if thic == 0
2557                                 if settings.var['fill_on']:
2558                                         len1 = len(verts)
2559                                         verts.append([0,0,0])  #center of circle
2560                                         center1 = len1
2561                                         faces = []
2562                                         faces.extend([[num, num+1, center1] for num in xrange(len1)])
2563                                         faces.append([len1-1, 0, center1])
2564                                         #print 'deb:circleDraw:verts:', verts  #---------------
2565                                         #print 'deb:circleDraw:faces:', faces  #---------------
2566                                         cir.verts.extend(verts) # add vertices to mesh
2567                                         cir.faces.extend(faces)  # add faces to the mesh
2568                                 else:
2569                                         cir.verts.extend(verts) # add vertices to mesh
2570                                         edges = [[num, num+1] for num in xrange(len(verts))]
2571                                         edges[-1][1] = 0   # it points the "new" last edge to the first vertex
2572                                         cir.edges.extend(edges)  # add edges to the mesh
2573
2574                         ob.loc = tuple(self.loc)
2575                         transform(self.extrusion, 0, ob)
2576                         return ob
2577                         
2578                         
2579
2580
2581 class Arc:  #-----------------------------------------------------------------
2582         """Class for objects representing dxf ARCs.
2583         """
2584
2585         def __init__(self, obj):
2586                 """Expects an entity object of type arc as input.
2587                 """
2588                 if not obj.type == 'arc':
2589                         raise TypeError, "Wrong type %s for arc object!" %obj.type
2590                 self.type = obj.type
2591                 self.data = obj.data[:]
2592
2593                 # required data
2594                 self.radius = obj.get_type(40)[0]
2595                 self.start_angle = obj.get_type(50)[0]
2596                 self.end_angle = obj.get_type(51)[0]
2597
2598                 # optional data (with defaults)
2599                 self.space = getit(obj, 67, 0)
2600                 self.thic =  getit(obj, 39, 0)
2601                 self.color_index = getit(obj, 62, BYLAYER)
2602
2603                 self.layer = getit(obj.data, 8, None)
2604                 self.loc = self.get_loc(obj.data)
2605                 self.extrusion = get_extrusion(obj.data)
2606                 #print 'deb:Arc__init__: center, radius, start, end:\n', self.loc, self.radius, self.start_angle, self.end_angle  #---------
2607
2608
2609
2610         def get_loc(self, data):
2611                 """Gets the center location for arc type objects.
2612
2613                 Arcs have a single coord location.
2614                 """
2615                 loc = [0, 0, 0]
2616                 loc[0] = getit(data, 10, None)
2617                 loc[1] = getit(data, 20, None)
2618                 loc[2] = getit(data, 30, 0.0)
2619                 return loc
2620
2621
2622
2623         def __repr__(self):
2624                 return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
2625
2626
2627         def draw(self, settings):
2628                 """for ARC: generate Blender_geometry.
2629                 """
2630                 obname = 'ar_%s' %self.layer  # create object name from layer name
2631                 obname = obname[:MAX_NAMELENGTH]
2632
2633                 center = self.loc
2634                 radius = self.radius
2635                 start = self.start_angle
2636                 end = self.end_angle
2637                 #print 'deb:calcArcPoints:\n center, radius, start, end:\n', center, radius, start, end  #---------
2638                 thic = set_thick(self.thic, settings)
2639                 width = 0.0
2640                 if settings.var['lines_as'] == 4: # as thin_box
2641                         thic = settings.var['thick_min']
2642                         width = settings.var['width_min']
2643                 if settings.var['lines_as'] == 3: # as thin cylinder
2644                         cyl_rad = 0.5 * settings.var['width_min']
2645
2646                 if settings.var['lines_as'] == 5:  # draw ARC as curve -------------
2647                         arc_res = settings.var['curve_arc']
2648                         triples = True
2649                         VectorTriples = calcArc(None, radius, start, end, arc_res, triples)
2650                         arc = Curve.New(obname) # create new curve data
2651                         curve = arc.appendNurb(BezTriple.New(VectorTriples[0]))
2652                         for p in VectorTriples[1:]:
2653                                 curve.append(BezTriple.New(p))
2654                         for point in curve:
2655                                 point.handleTypes = [FREE, FREE]
2656                         curve.flagU = 0 # 0 sets the curve not cyclic=open
2657                         arc.setResolu(settings.var['curve_res'])
2658
2659                         arc.update() #important for handles calculation
2660
2661                         ob = SCENE.objects.new(arc) # create a new curve_object
2662                         ob.loc = tuple(self.loc)
2663                         if thic != 0.0: #hack: Blender<2.45 curve-extrusion
2664                                 thic = thic * 0.5
2665                                 arc.setExt1(1.0)  # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0)
2666                                 ob.LocZ = thic + self.loc[2]
2667                         transform(self.extrusion, 0, ob)
2668                         if thic != 0.0:
2669                                 ob.SizeZ *= abs(thic)
2670                         return ob
2671
2672                 else:  # draw ARC as mesh --------------------
2673                         me = Mesh.New(obname)  # create a new mesh
2674                         ob = SCENE.objects.new(me) # create a new mesh_object
2675                         # set a number of segments in entire circle
2676                         arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad'])
2677
2678                         verts = calcArc(None, radius, start, end, arc_res, False)
2679                         #verts = [list(point) for point in verts]
2680                         len1 = len(verts)
2681                         #print 'deb:len1:', len1  #-----------------------
2682                         if width != 0:
2683                                 radius_out = radius + (0.5 * width)
2684                                 radius_in  = radius - (0.5 * width)
2685                                 if radius_in <= 0.0:
2686                                         radius_in = settings.var['dist_min']
2687                                         #radius_in = 0.0
2688                                 verts_in = []
2689                                 verts_out = []
2690                                 for point in verts:
2691                                         pointVec = Mathutils.Vector(point)
2692                                         pointVec = pointVec.normalize()
2693                                         verts_in.append(list(radius_in * pointVec))   #vertex inside
2694                                         verts_out.append(list(radius_out * pointVec)) #vertex outside
2695                                 verts = verts_in + verts_out
2696
2697                                 #print 'deb:verts:', verts  #---------------------
2698                                 if thic != 0:
2699                                         thic_verts = []
2700                                         thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts])
2701                                         if thic < 0.0:
2702                                                 thic_verts.extend(verts)
2703                                                 verts = thic_verts
2704                                         else:
2705                                                 verts.extend(thic_verts)
2706                                         f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)]
2707                                         f_top   = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)]
2708                                         f_left   = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)]
2709                                         f_right  = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)]
2710                                         f_start = [[0, len1, len1+len1+len1, len1+len1]]
2711                                         f_end   = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]]
2712                                         faces = f_left + f_right + f_bottom + f_top + f_start + f_end
2713         
2714                                         me.verts.extend(verts) # add vertices to mesh
2715                                         me.faces.extend(faces)  # add faces to the mesh
2716
2717                                         if settings.var['meshSmooth_on']:  # left and right side become smooth ----------------------
2718                                                 smooth_len = len(f_left) + len(f_right)
2719                                                 for i in xrange(smooth_len):
2720                                                         me.faces[i].smooth = True
2721                                         # each MeshSide becomes vertexGroup for easier material assignment ---------------------
2722                                         if settings.var['vGroup_on']:
2723                                                 # each MeshSide becomes vertexGroup for easier material assignment ---------------------
2724                                                 replace = Blender.Mesh.AssignModes.REPLACE  #or .AssignModes.ADD
2725                                                 vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
2726                                                 for v in f_left: vg_left.extend(v)
2727                                                 for v in f_right: vg_right.extend(v)
2728                                                 for v in f_top: vg_top.extend(v)
2729                                                 for v in f_bottom: vg_bottom.extend(v)
2730                                                 me.addVertGroup('side.left')  ; me.assignVertsToGroup('side.left',  list(set(vg_left)), 1.0, replace)
2731                                                 me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace)
2732                                                 me.addVertGroup('side.top')   ; me.assignVertsToGroup('side.top',   list(set(vg_top)), 1.0, replace)
2733                                                 me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
2734                                                 me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace)
2735                                                 me.addVertGroup('side.end')  ; me.assignVertsToGroup('side.end',   f_end[0],   1.0, replace)
2736                                         
2737
2738                                 else:  # if thick=0 - draw only flat ring
2739                                         faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)]
2740                                         me.verts.extend(verts) # add vertices to mesh
2741                                         me.faces.extend(faces)  # add faces to the mesh
2742         
2743                         elif thic != 0:
2744                                 thic_verts = []
2745                                 thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts])
2746                                 if thic < 0.0:
2747                                         thic_verts.extend(verts)
2748                                         verts = thic_verts
2749                                 else:
2750                                         verts.extend(thic_verts)
2751                                 faces = []
2752                                 #print 'deb:len1:', len1  #-----------------------
2753                                 #print 'deb:verts:', verts  #---------------------
2754                                 faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)]
2755
2756                                 me.verts.extend(verts) # add vertices to mesh
2757                                 me.faces.extend(faces)  # add faces to the mesh
2758                                 if settings.var['meshSmooth_on']:  # left and right side become smooth ----------------------
2759                                         for i in xrange(len(faces)):
2760                                                 me.faces[i].smooth = True
2761
2762                         else:
2763                                 edges = [[num, num+1] for num in xrange(len(verts)-1)]
2764                                 me.verts.extend(verts) # add vertices to mesh
2765                                 me.edges.extend(edges)  # add edges to the mesh
2766
2767                         #me.update()
2768                         #ob = SCENE.objects.new(me) # create a new arc_object
2769                         #ob.link(me)
2770                         ob.loc = tuple(center)
2771                         #ob.loc = Mathutils.Vector(ob.loc)
2772                         transform(self.extrusion, 0, ob)
2773                         #ob.size = (1,1,1)
2774                         return ob
2775
2776
2777 class BlockRecord:  #-----------------------------------------------------------------
2778         """Class for objects representing dxf block_records.
2779         """
2780
2781         def __init__(self, obj):
2782                 """Expects an entity object of type block_record as input.
2783                 """
2784                 if not obj.type == 'block_record':
2785                         raise TypeError, "Wrong type %s for block_record object!" %obj.type
2786                 self.type = obj.type
2787                 self.data = obj.data[:]
2788
2789                 # required data
2790                 self.name =  getit(obj, 2, None)
2791
2792                 # optional data (with defaults)
2793                 self.insertion_units =  getit(obj, 70, None)
2794                 self.insert_units = getit(obj, 1070, None)
2795                 """code 1070 Einf├╝geeinheiten:
2796                 0 = Keine Einheiten; 1 = Zoll; 2 = Fu├č; 3 = Meilen; 4 = Millimeter;
2797                 5 = Zentimeter; 6 = Meter; 7 = Kilometer; 8 = Mikrozoll;
2798                 9 = Mils; 10 = Yard; 11 = Angstrom; 12 = Nanometer;
2799                 13 = Mikrons; 14 = Dezimeter; 15 = Dekameter;
2800                 16 = Hektometer; 17 = Gigameter; 18 = Astronomische Einheiten;
2801                 19 = Lichtjahre; 20 = Parsecs
2802                 """
2803
2804
2805         def __repr__(self):
2806                 return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units)
2807
2808
2809
2810
2811 class Block:  #-----------------------------------------------------------------
2812         """Class for objects representing dxf BLOCKs.
2813         """
2814
2815         def __init__(self, obj):
2816                 """Expects an entity object of type block as input.
2817                 """
2818                 if not obj.type == 'block':
2819                         raise TypeError, "Wrong type %s for block object!" %obj.type
2820
2821                 self.type = obj.type
2822                 self.name = obj.name
2823                 self.data = obj.data[:]
2824
2825                 # required data
2826                 self.flags = getit(obj, 70, 0)
2827                 self.anonim = self.flags & 1 #anonymous block generated by hatching, associative dimensioning, other
2828                 self.atrib  = self.flags & 2 # has attribute definitions
2829                 self.xref = self.flags & 4 # is an external reference (xref)
2830                 self.xref_lay = self.flags & 8 # is an xref overlay 
2831                 self.dep_ext = self.flags & 16 #  is externally dependent
2832                 self.dep_res = self.flags & 32 # resolved external reference
2833                 self.xref_ext = self.flags & 64 # is a referenced external reference xref
2834                 #--todo--- if self.flag > 4: self.xref = True
2835