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