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