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