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