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