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