diff options
author | Campbell Barton <ideasman42@gmail.com> | 2007-08-18 10:46:10 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2007-08-18 10:46:10 +0400 |
commit | c8471fe9339bb91c165fc8a45d7837455df3cce7 (patch) | |
tree | afffed2fec31538d78ee4b1f8b8eeaf1141eb68d | |
parent | 5f0b91e1dbd7bf1120ccde801d18d835787305bf (diff) |
Big update to kitsu's dxf importer from migius version beta09_f, too many changes an improvements to mention
The scripts thread is here http://blenderartists.org/forum/showthread.php?t=84319&page=8
-rw-r--r-- | release/scripts/import_dxf.py | 6062 |
1 files changed, 3860 insertions, 2202 deletions
diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index a4e4e69b366..f8d2da95187 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -1,54 +1,156 @@ #!BPY -# """ -# Name: 'Drawing eXchange Format (.dxf)' -# Blender: 243 -# Group: 'Import' -# Tooltip: 'Import DXF file.' -# """ -__author__ = 'Kitsu (Ed Blake)' -__version__ = '0.9 1/2007' -__url__ = ["elysiun.com", "BlenderArtists.org"] -__email__ = ["Kitsune_e@yahoo.com"] +""" +Name: 'DXF (.dxf)' +Blender: 244 +Group: 'Import' +Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' +""" +__author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' +__version__ = '1.0.beta09 by migius 17.08.2007' +__url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", + "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] +__email__ = ["Kitsune_e(at)yahoo.com", "remi_(at)gmx.de"] __bpydoc__ = """\ -This is a Blender import script for dxf files. - -This script imports the dxf Geometery from dxf versions 2007 and earlier. - -Supported:<br> - At this time only mesh based imports are supported.<br> - Future support for all curve import is planned.<br> - <br> -Currently Supported DXF Ojects:<br> - Lines<br> - LightWeight polylines<br> - True polylines<br> - Text<br> - Mtext<br> - Circles<br> - Arcs<br> - Ellipses<br> - Blocks<br> - 3Dfaces<br> - -Known issues:<br> - Does not convert perfectly between Object Coordinate System (OCS) - and World Coordinate System (WCS). Only rudimentary support for - true polylines have been implimented - splines/fitted curves/ - 3d plines/polymeshes are not supported. - No support for most 3d entities. Doesn't support the new style object - visability. There are problems importing some curves/arcs/circles. - -Notes:<br> - This is primarally a 2d drawing release. Currently only support for - 3d faces has been added. - Blocks are created on layer 19 then referenced at each insert point. The - insert point is designated with a small 3d crosshair. This handle does not render. +This script imports DXF objects (2d/3d) into Blender. + +This script imports 2d and 3d Geometery from DXFr12 format files. +This version is focused on import of 3d-objects. + +Supported DXF Objects: + LINE + POINT + SOLID + TRACE + INSERT (=block) + MINSERT (=array) + CIRCLE + ARC + 3DFACE + 2d-POLYLINE (incl.:arc-segments, variable-width-segments) + 2d-POLYLINE (curved, spline) + 3d-POLYLINE (curved, spline) + 3d-POLYMESH + 3d-POLYFACE + TEXT + +Supported DXF Objects: (*)-under construction + *LWPOLYLINE (DXF>r12 LightWeight POLYLINE) + *MTEXT (DXF>r12) + *ELLIPSE (DXF>r12) + +Not supported DXF Objects: + DIMENSION + XREF (External Reference) + SPLINE (DXF>r12) + GROUP (DXF>r12) + RAY/XLINE (DXF>r12) + LEADER (DXF>r12) + 3DSOLID, BODY, REGION (DXF>r12) + dynamic BLOCK (DXF 2006) + +Notes: +- Recommend that you run 'RemoveDoubles' on each imported mesh after using this script +- Blocks are created on layer 19 then referenced at each insert point. + +TODO: +- filtering of unused/not-inserted Blocks +- the new style object visibility +- support for Spline-curves, Besier-curves +- support for real 3d-solids (ACIS) +- (to see more, search for "-todo-" in script) + + +History: + v1.0 by migius 08.2007: "full 3d"-release + TODO: + -- command-line-mode/batch-mode + -- human-formating of data in INI-File + -- suport for MLine + -- suport for Ellipse + -- suport for Mtext + -- blender_object.ID.properties[dxf_layer_name] + -- added f_layerFilter + -- to-check: new_scene-idea from ideasman42: each import create a new scene + -- to-check: obj/mat/group/_mapping-idea from ideasman42: + -- better support for long dxf-layer-names + -- support width_force for LINEs/ARCs/CIRCLEs/ELLIPSEs = "solidify" + + beta09: 17.08.2007 by migius + f- cleanup code + f- bugfix: thickness for Bezier/Bsplines into Blender-curves + f- added import POLYLINE-Bsplines into Blender-NURBSCurves + f- added import POLYLINE-arc-segments into Blender-BezierCurves + f- added import POLYLINE-Bezier-curves into Blender-Curves + d5 rewrite: Optimisations Levels, added 'directDrawing' + d4 added: f_set_thick(cntrolled by ini-parameters) + d4 bugfix: face-normals in objects with minus thickness + d4 added: placeholder'Empty'-size in f_Insert.draw + d3 rewrite f_Text.Draw: added suport for all Text's parameters + d2 redesign: progressbar + e- tuning by ideasman42 + c- tuning by ideasman42 + b- rewrite f_Text.Draw rotation/transform + b- bugfix: POLYLINE-segment-intersection more reliable now + b- bugfix: circle:_thic, 'Empties':no material_assignement + b- added material assignment (from layer and/or color) + a- added empty, cylinder and UVsphere for POINTs + a- added support for 2d-POLYLINE: splines, fitted curves, fitted surfaces + a- redesign f_Drawer for block_definitions + a- rewrite import into Blender-Curve-Object + beta08: 27.07.2007 by migius + l- bugfix: solid_vgroups, clean:scene.objects.new() + l- redesign UI to standard Draw.Register+FileSelector, advanced_config_option + k- bugfix UI:fileSelect() for MacOSX os.listdir() + k- added reset/save/load for config-data + k- redesign keywords/drawTypes/Draw.Create_Buttons + j- new interface using UIBlock() with own FileSelector, cause Window.FileSelector() too buggy + i- rewritten Class:Settings for better config-parameter management + h- bugfix: face-normals in objects with minus thickness + h- added Vertex-Groups in polylines and solids generated Meshes, for easier material assignment + h- beautify code, whitespace->tabs + h- added settings.thic_force switch for forcing thickness + h- added one Object/Mesh for all simple-entities from the same Layer, + sorted in Vertex-Groups(color_name) (fewer objects = better import performance) + g- rewrote: insert-point-handle-object is a small tetrahedron + e- bugfix: closed-polymesh3d + - rewrote: startUI, type_map.keys, f_drawer, for all class_f_draw(added "settings" as attribut) + - added 2d/3d-support for Polyline_Width incl. angleintersection + beta07: 19.06.2007 by migius + - added 3d-support for LWPolylines + - added 2d/3d-support for Points + beta06: 15.06.2007 by migius + - cleanup code + - added 2d/3d-support for MINSERT=BlockArray in f_drawer, added f_rotXY_Vec + beta05: 14.06.2007 by migius + - added 2d/3d-support for 3d-PolyLine, PolyMesh and PolyFace + - added Global-Scale for size control of imported scenes + beta04: 12.06.2007 by migius + - rewrote the f_drawBulge for correct import the arc-segments of Polylines + beta03: 10.06.2007 by migius + - rewrote interface + beta02: 09.06.2007 by migius + - added 3d-support for Arcs and Circles + - added support for Object_Thickness(=height) + beta01: 08.06.2007 by migius + - added 3d-support for Blocks/Inserts within nested-structures + - rewrote f_transform for correct 3d-location/3d-rotation + - added 3d-support Lines, 3dFaces + - added 2d+3d-support for Solids and Traces + + v0.9 by kitsu 01.2007: (for 2.43) + - + + v0.8 by kitsu 12.2007: + - + + v0.5b by kitsu 10.2006 (for 2.42a) + - """ # -------------------------------------------------------------------------- -# DXF Import v0.9 by Ed Blake (AKA Kitsu) +# DXF Import v1.0 by Ed Blake (AKA kitsu) and Remigiusz Fiedler (AKA migius) # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -70,37 +172,67 @@ Notes:<br> # -------------------------------------------------------------------------- import Blender +import bpy from Blender import * -Sys = sys +#from Blender.Mathutils import Vector, Matrix +#import BPyMessages -from dxfReader import readDXF, get_name, get_layer + +from dxfReader import readDXF # get_name, get_layer from dxfReader import Object as dxfObject from dxfColorMap import color_map from math import * try: - import os - if os.name:# != 'mac': - import psyco - psyco.log() - psyco.full(memory=100) - psyco.profile(0.05, memory=100) - psyco.profile(0.2) + import os + if os.name:# != 'mac': + import psyco + psyco.log() + psyco.full(memory=100) + psyco.profile(0.05, memory=100) + psyco.profile(0.2) except ImportError: - pass + pass + +print '\n\n\n\n' +print 'Import DXF to Blender *** START ***' #--------------------- -SCENE = Scene.GetCurrent() +SCENE = None WORLDX = Mathutils.Vector((1,0,0)) +WORLDY = Mathutils.Vector((1,1,0)) +WORLDZ = Mathutils.Vector((0,0,1)) + +G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data +MIN_DIST = 0.001 #cut-off value for sort out short-distance polyline-"duoble_vertex" +ARC_RESOLUTION = 64 #(4-500) arc/circle resolution - number of segments +THIN_RESOLUTION = 8 #(4-500) thin_cylinder arc_resolution - number of segments +MIN_THICK = MIN_DIST * 10.0 #minimal thickness by forced thickness +MIN_WIDTH = MIN_DIST * 10.0 #minimal width by forced width +ANGLECUT_LIMIT = 3.0 #limit for anglecut of polylines-wide-segments (values:1.0 - 5.0) +TARGET_LAYER = 3 #target blender_layer +GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-group + +FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE) +MAX_NAMELENGTH = 17 #max_effective_obnamelength in blender =21=17+(.001) +INIFILE_DEFAULT_NAME = 'importDXF.ini' +INIFILE_EXTENSION = '.ini' +INIFILE_HEADER = 'ImportDXF.py ver.1.0 config data' + AUTO = BezTriple.HandleTypes.AUTO -BYLAYER=256 +FREE = BezTriple.HandleTypes.FREE +VECT = BezTriple.HandleTypes.VECT +ALIGN = BezTriple.HandleTypes.ALIGN +cur_COUNTER = 0 #counter for progress_bar + + """This module provides wrapper objects for dxf entities. - - The wrappers expect a "dxf object" as input. The dxf object is - an object with a type and a data attribute. Type is a lowercase - string matching the 0 code of a dxf entity. Data is a list containing - dxf objects or lists of [code, data] pairs. - - This module is not general, and is only for dxf import. + + The wrappers expect a "dxf object" as input. The dxf object is + an object with a type and a data attribute. Type is a lowercase + string matching the 0 code of a dxf entity. Data is a list containing + dxf objects or lists of [code, data] pairs. + + This module is not general, and is only for dxf import. """ # from Stani's dxf writer v1.1 (c)www.stani.be (GPL) @@ -108,2157 +240,3683 @@ BYLAYER=256 BYBLOCK=0 BYLAYER=256 -#---block-type flags (bit coded values, may be combined): -ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application +#---block-type flags (bit coded values, may be combined): +ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all) -XREF =4 # This block is an external reference (xref) -XREF_OVERLAY =8 # This block is an xref overlay -EXTERNAL =16 # This block is externally dependent -RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) -REFERENCED =64 # This definition is a referenced external reference (ignored on input) +XREF =4 # This block is an external reference (xref) +XREF_OVERLAY =8 # This block is an xref overlay +EXTERNAL =16 # This block is externally dependent +RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) +REFERENCED =64 # This definition is a referenced external reference (ignored on input) + +#---polyline flags +CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) +CURVE_FIT =2 # Curve-fit vertices have been added +SPLINE_FIT =4 # Spline-fit vertices have been added +POLYLINE_3D =8 # This is a 3D polyline +POLYGON_MESH =16 # This is a 3D polygon mesh +CLOSED_N =32 # The polygon mesh is closed in the N direction +POLYFACE_MESH =64 # The polyline is a polyface mesh +CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline + +#---text flags +#horizontal +LEFT = 0 +CENTER = 1 +RIGHT = 2 +ALIGNED = 3 #if vertical alignment = 0 +MIDDLE = 4 #if vertical alignment = 0 +FIT = 5 #if vertical alignment = 0 +#vertical +BASELINE = 0 +BOTTOM = 1 +MIDDLE = 2 +TOP = 3 #---mtext flags #attachment point -TOP_LEFT = 1 -TOP_CENTER = 2 -TOP_RIGHT = 3 -MIDDLE_LEFT = 4 +TOP_LEFT = 1 +TOP_CENTER = 2 +TOP_RIGHT = 3 +MIDDLE_LEFT = 4 MIDDLE_CENTER = 5 -MIDDLE_RIGHT = 6 -BOTTOM_LEFT = 7 +MIDDLE_RIGHT = 6 +BOTTOM_LEFT = 7 BOTTOM_CENTER = 8 -BOTTOM_RIGHT = 9 +BOTTOM_RIGHT = 9 #drawing direction -LEFT_RIGHT = 1 -TOP_BOTTOM = 3 -BY_STYLE = 5 #the flow direction is inherited from the associated text style -#line spacing style (optional): -AT_LEAST = 1 #taller characters will override -EXACT = 2 #taller characters will not override +LEFT_RIGHT = 1 +TOP_BOTTOM = 3 +BY_STYLE = 5 #the flow direction is inherited from the associated text style +#line spacing style (optional): +AT_LEAST = 1 #taller characters will override +EXACT = 2 #taller characters will not override -#---polyline flags -CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) -CURVE_FIT =2 # Curve-fit vertices have been added -SPLINE_FIT =4 # Spline-fit vertices have been added -POLYLINE_3D =8 # This is a 3D polyline -POLYGON_MESH =16 # This is a 3D polygon mesh -CLOSED_N =32 # The polygon mesh is closed in the N direction -POLYFACE_MESH =64 # The polyline is a polyface mesh -CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline -#---text flags -#horizontal -LEFT = 0 -CENTER = 1 -RIGHT = 2 -ALIGNED = 3 #if vertical alignment = 0 -MIDDLE = 4 #if vertical alignment = 0 -FIT = 5 #if vertical alignment = 0 -#vertical -BASELINE = 0 -BOTTOM = 1 -MIDDLE = 2 -TOP = 3 -class Layer: - """Class for objects representing dxf layers.""" - - def __init__(self, obj, name=None, color=None, frozen=None): - """Expects an entity object of type line as input.""" - self.type = obj.type - self.data = obj.data[:] - - if name: - self.name = name - else: - self.name = obj.get_type(2)[0] - if color: - self.color = color - else: - self.color = obj.get_type(62)[0] - if frozen: - self.frozen = frozen - else: - self.flags = obj.get_type(70)[0] - self.frozen = self.flags&1 - - def __repr__(self): - return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color) - - - -class Line: - """Class for objects representing dxf lines.""" - - def __init__(self, obj): - """Expects an entity object of type line as input.""" - if not obj.type == 'line': - raise TypeError, "Wrong type %s for line object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.points = self.get_points(obj.data) - - - - - def get_points(self, data): - """Gets start and end points for a line type object. - - Lines have a fixed number of points (two) and fixed codes for each value. - """ - - # start x, y, z and end x, y, z = 0 - sx, sy, sz, ex, ey, ez = 0, 0, 0, 0, 0, 0 - for item in data: - if item[0] == 10: # 10 = x - sx = item[1] - elif item[0] == 20: # 20 = y - sy = item[1] - elif item[0] == 30: # 30 = z - sz = item[1] - elif item[0] == 11: # 11 = x - ex = item[1] - elif item[0] == 21: # 21 = y - ey = item[1] - elif item[0] == 31: # 31 = z - ez = item[1] - return [[sx, sy, sz], [ex, ey, ez]] - - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, curves=False): - """Do all the specific things needed to import lines into Blender.""" - # Generate the geometery - points = self.points - edges = [[0, 1]] - - me = Mesh.New('line') # create a new mesh - - me.verts.extend(points) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - # Now Create an object - ob = Object.New('Mesh', 'line') # link mesh to an object - ob.link(me) - - return ob - - - - -class LWpolyline: - """Class for objects representing dxf LWpolylines.""" - - def __init__(self, obj): - """Expects an entity object of type lwpolyline as input.""" - if not obj.type == 'lwpolyline': - raise TypeError, "Wrong type %s for polyline object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.num_points = obj.get_type(90)[0] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - self.elevation = obj.get_type(38) - if self.elevation: - self.elevation = self.elevation[0] - else: - self.elevation = 0 - - self.flags = obj.get_type(70) - if self.flags: - self.flags = self.flags[0] - else: - self.flags = 0 - - self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.points = self.get_points(obj.data) - self.extrusion = self.get_extrusion(obj.data) - - - - - - - def get_points(self, data): - """Gets points for a polyline type object. - - Polylines have no fixed number of verts, and - each vert can have a number of properties. - Verts should be coded as - 10:xvalue - 20:yvalue - 40:startwidth or 0 - 41:endwidth or 0 - 42:bulge or 0 - for each vert - """ - num = self.num_points - point = None - points = [] - for item in data: - if item[0] == 10: # 10 = x - if point: - points.append(point) - point = Vertex() - point.x = item[1] - elif item[0] == 20: # 20 = y - point.y = item[1] - elif item[0] == 40: # 40 = start width - point.swidth = item[1] - elif item[0] == 41: # 41 = end width - point.ewidth = item[1] - elif item[0] == 42: # 42 = bulge - point.bulge = item[1] - points.append(point) - return points - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, curves=False): - """Do all the specific things needed to import plines into Blender.""" - # Generate the geometery - points = [] - for i in range(len(self.points)): - point = self.points[i] - if not point.bulge: - points.append(point.loc) - elif point.bulge and i < len(self.points)-1:# > 0: - center, radius, start, end = solveBulge(point, self.points[i+1]) - #print center, radius, start, end - verts, nosense = drawArc(center, radius, start, end) - verts.pop(0) # remove first - verts.pop() #remove last - if point.bulge >= 0: - verts.reverse() - points.extend(verts) - edges = [[num, num+1] for num in range(len(points)-1)] - if self.closed: - edges.append([len(self.points)-1, 0]) - - me = Mesh.New('lwpline') # create a new mesh - - me.verts.extend(points) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - # Now Create an object - ob = Object.New('Mesh', 'lwpline') # link mesh to an object - ob.link(me) - transform(self.extrusion, ob) - ob.LocZ = self.elevation - - return ob - - - -class Polyline: - """Class for objects representing dxf LWpolylines.""" - - def __init__(self, obj): - """Expects an entity object of type polyline as input.""" - if not obj.type == 'polyline': - raise TypeError, "Wrong type %s for polyline object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - self.points = [] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - self.elevation = obj.get_type(30) - if self.elevation: - self.elevation = self.elevation[0] - else: - self.elevation = 0 - - self.flags = obj.get_type(70) - if self.flags: - self.flags = self.flags[0] - else: - self.flags = 0 - - self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.extrusion = self.get_extrusion(obj.data) - - - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, curves=False): - """Do all the specific things needed to import plines into Blender.""" - # Generate the geometery - points = [] - for i in range(len(self.points)): - point = self.points[i] - if not point.bulge: - points.append(point.loc) - elif point.bulge and i < len(self.points)-1:# > 0: - center, radius, start, end = solveBulge(point, self.points[i+1]) - #print center, radius, start, end - verts, nosense = drawArc(center, radius, start, end) - verts.pop(0) # remove first - verts.pop() #remove last - if point.bulge >= 0: - verts.reverse() - points.extend(verts) - edges = [[num, num+1] for num in range(len(points)-1)] - if self.closed: - edges.append([len(self.points)-1, 0]) - - me = Mesh.New('pline') # create a new mesh - - me.verts.extend(points) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - # Now Create an object - ob = Object.New('Mesh', 'pline') # link mesh to an object - ob.link(me) - transform(self.extrusion, ob) - ob.LocZ = self.elevation - - return ob - - - - -class Vertex(object): - """Generic vertex object used by polylines (and maybe others).""" - - def __init__(self, obj=None): - """Initializes vertex data. - - The optional obj arg is an entity object of type vertex. - """ - self.loc = [0,0,0] - self.bulge = 0 - self.swidth = 0 - self.ewidth = 0 - self.flags = 0 - - if obj is not None: - if not obj.type == 'vertex': - raise TypeError, "Wrong type %s for vertex object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - self.get_props(obj.data) - - - def get_props(self, data): - """Gets coords for a vertex type object. - - Each vert can have a number of properties. - Verts should be coded as - 10:xvalue - 20:yvalue - 40:startwidth or 0 - 41:endwidth or 0 - 42:bulge or 0 - """ - for item in data: - if item[0] == 10: # 10 = x - self.x = item[1] - elif item[0] == 20: # 20 = y - self.y = item[1] - elif item[0] == 30: # 30 = z - self.z = item[1] - elif item[0] == 40: # 40 = start width - self.swidth = item[1] - elif item[0] == 41: # 41 = end width - self.ewidth = item[1] - elif item[0] == 42: # 42 = bulge - self.bulge = item[1] - elif item[0] == 70: # 70 = vert flags - self.flags = item[1] - - - def __len__(self): - return 3 - - - def __getitem__(self, key): - return self.loc[key] - - - def __setitem__(self, key, value): - if key in [0,1,2]: - self.loc[key] - - - def __iter__(self): - return self.loc.__iter__() - - - def __str__(self): - return str(self.loc) - - - def __repr__(self): - return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s" %(self.loc, self.swidth, self.ewidth, self.bulge) - - - def getx(self): - return self.loc[0] - - def setx(self, value): - self.loc[0] = value - - x = property(getx, setx) - - - def gety(self): - return self.loc[1] - - def sety(self, value): - self.loc[1] = value - - y = property(gety, sety) - - - def getz(self): - return self.loc[2] - - def setz(self, value): - self.loc[2] = value - - z = property(getz, setz) - - - -class Text: - """Class for objects representing dxf Text.""" - - def __init__(self, obj): - """Expects an entity object of type text as input.""" - if not obj.type == 'text': - raise TypeError, "Wrong type %s for text object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.height = obj.get_type(40)[0] - self.value = obj.get_type(1)[0] # The text string value - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - self.rotation = obj.get_type(50) # radians? - if not self.rotation: - self.rotation = 0 - else: - self.rotation = self.rotation[0] - - self.width_factor = obj.get_type(41) # Scaling factor along local x axis - if not self.width_factor: - self.width_factor = 1 - else: - self.width_factor = self.width_factor[0] - - self.oblique = obj.get_type(51) # skew in degrees -90 <= oblique <= 90 - if not self.oblique: - self.oblique = 0 - else: - self.oblique = self.oblique[0] - - self.halignment = obj.get_type(72) # horiz. alignment - if not self.halignment: # 0=left, 1=center, 2=right, 3=aligned, 4=middle, 5=fit - self.halignment = 0 - else: - self.halignment = self.halignment[0] - - self.valignment = obj.get_type(73) # vert. alignment - if not self.valignment: # 0=baseline, 1=bottom, 2=middle, 3=top - self.valignment = 0 - else: - self.valignment = self.valignment[0] - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data, self.halignment, self.valignment) - self.extrusion = self.get_extrusion(obj.data) - - - - - def get_loc(self, data, halign, valign): - """Gets adjusted location for text type objects. - - If group 72 and/or 73 values are nonzero then the first alignment point values - are ignored and AutoCAD calculates new values based on the second alignment - point and the length and height of the text string itself (after applying the - text style). If the 72 and 73 values are zero or missing, then the second - alignment point is meaningless. - - I don't know how to calc text size... - """ - # bottom left x, y, z and justification x, y, z = 0 - x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0 - for item in data: - if item[0] == 10: # 10 = x - x = item[1] - elif item[0] == 20: # 20 = y - y = item[1] - elif item[0] == 30: # 30 = z - z = item[1] - elif item[0] == 11: # 11 = x - jx = item[1] - elif item[0] == 21: # 21 = y - jy = item[1] - elif item[0] == 31: # 31 = z - jz = item[1] - - if halign or valign: - x, y, z = jx, jy, jz - return [x, y, z] - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) - - - def draw(self, curves=False): - """Do all the specific things needed to import texts into Blender.""" - # Generate the geometery - txt = Text3d.New("text") - txt.setSize(1) - txt.setShear(self.oblique/90) - txt.setExtrudeDepth(0.5) - if self.halignment == 0: - align = Text3d.LEFT - elif self.halignment == 1: - align = Text3d.MIDDLE - elif self.halignment == 2: - align = Text3d.RIGHT - elif self.halignment == 3: - align = Text3d.FLUSH - else: - align = Text3d.MIDDLE - txt.setAlignment(align) - txt.setText(self.value) - - # Now Create an object - ob = Object.New('Text', 'text') # link mesh to an object - ob.link(txt) - - transform(self.extrusion, ob) - - # move the object center to the text location - ob.loc = tuple(self.loc) - # scale it to the text size - ob.SizeX = self.height*self.width_factor - ob.SizeY = self.height - ob.SizeZ = self.height - # and rotate it around z - ob.RotZ = radians(self.rotation) - - return ob - - - - -class Mtext: - """Class for objects representing dxf Mtext.""" - - def __init__(self, obj): - """Expects an entity object of type mtext as input.""" - if not obj.type == 'mtext': - raise TypeError, "Wrong type %s for mtext object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.height = obj.get_type(40)[0] - self.width = obj.get_type(41)[0] - 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 - self.value = self.get_text(obj.data) # The text string value - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - self.rotation = obj.get_type(50) # radians - if not self.rotation: - self.rotation = 0 - else: - self.rotation = self.rotation[0] - - self.width_factor = obj.get_type(42) # Scaling factor along local x axis - if not self.width_factor: - self.width_factor = 1 - else: - self.width_factor = self.width_factor[0] - - self.line_space = obj.get_type(44) # percentage of default - if not self.line_space: - self.line_space = 1 - else: - self.line_space = self.line_space[0] - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - self.extrusion = self.get_extrusion(obj.data) - - - - - - def get_text(self, data): - """Reconstructs mtext data from dxf codes.""" - primary = '' - secondary = [] - for item in data: - if item[0] == 1: # There should be only one primary... - primary = item[1] - elif item[0] == 3: # There may be any number of extra strings (in order) - secondary.append(item[1]) - if not primary: - #raise ValueError, "Empty Mtext Object!" - string = "Empty Mtext Object!" - if not secondary: - string = primary.replace(r'\P', '\n') - else: - string = ''.join(secondary)+primary - string = string.replace(r'\P', '\n') - return string - def get_loc(self, data): - """Gets location for a mtext type objects. - - Mtext objects have only one point indicating location. - """ - loc = [0,0,0] - for item in data: - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) - - - def draw(self, curves=False): - """Do all the specific things needed to import mtexts into Blender.""" - # Generate the geometery - txt = Text3d.New("mtext") - txt.setSize(1) - # Blender doesn't give access to its text object width currently - # only to the text3d's curve width... - #txt.setWidth(text.width/10) - txt.setLineSeparation(self.line_space) - txt.setExtrudeDepth(0.5) - txt.setText(self.value) - - # Now Create an object - ob = Object.New('Text', 'mtext') # link mesh to an object - ob.link(txt) - - transform(self.extrusion, ob) - - # move the object center to the text location - ob.loc = tuple(self.loc) - # scale it to the text size - ob.SizeX = self.height*self.width_factor - ob.SizeY = self.height - ob.SizeZ = self.height - # and rotate it around z - ob.RotZ = radians(self.rotation) - - return ob - - - - - - -class Circle: - """Class for objects representing dxf Circles.""" - - def __init__(self, obj): - """Expects an entity object of type circle as input.""" - if not obj.type == 'circle': - raise TypeError, "Wrong type %s for circle object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.radius = obj.get_type(40)[0] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - self.extrusion = self.get_extrusion(obj.data) - - - - - - def get_loc(self, data): - """Gets the center location for circle type objects. - - Circles have a single coord location. - """ - loc = [0, 0, 0] - for item in data: - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, curves=False): - """Do all the specific things needed to import circles into Blender.""" - # Generate the geometery - # Now Create an object - if curves: - ob = drawCurveCircle(self) - else: - center = self.loc - radius = self.radius - - circ = 2 * pi * radius - if circ < 65: # if circumfrance is too small - verts = 32 # set a fixed number of 32 verts - else: - verts = circ/.5 # figure out how many verts we need - if verts > 100: # Blender only accepts values - verts = 100 # [3:100] - - c = Mesh.Primitives.Circle(int(verts), radius*2) - - ob = Object.New('Mesh', 'circle') - ob.link(c) # link curve data with this object - - ob.loc = tuple(center) - transform(self.extrusion, ob) - - return ob - - - - -class Arc: - """Class for objects representing dxf arcs.""" - - def __init__(self, obj): - """Expects an entity object of type arc as input.""" - if not obj.type == 'arc': - raise TypeError, "Wrong type %s for arc object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.radius = obj.get_type(40)[0] - self.start_angle = obj.get_type(50)[0] - self.end_angle = obj.get_type(51)[0] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - self.extrusion = self.get_extrusion(obj.data) - - - - - - def get_loc(self, data): - """Gets the center location for arc type objects. - - Arcs have a single coord location. - """ - loc = [0, 0, 0] - for item in data: - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, curves=False): - """Do all the specific things needed to import arcs into Blender.""" - # Generate the geometery - # Now Create an object - if curves: - ob = drawCurveArc(self) - else: - center = self.loc - radius = self.radius - start = self.start_angle - end = self.end_angle - verts, edges = drawArc(None, radius, start, end) - - a = Mesh.New('arc') - - a.verts.extend(verts) # add vertices to mesh - a.edges.extend(edges) # add edges to the mesh - - ob = Object.New('Mesh', 'arc') - ob.link(a) # link curve data with this object - ob.loc = tuple(center) - ob.RotX = radians(180) - - transform(self.extrusion, ob) - ob.size = (1,1,1) - - return ob - - -class BlockRecord: - """Class for objects representing dxf block_records.""" - - def __init__(self, obj): - """Expects an entity object of type block_record as input.""" - if not obj.type == 'block_record': - raise TypeError, "Wrong type %s for block_record object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.name = obj.get_type(2)[0] - - # optional data (with defaults) - self.insertion_units = obj.get_type(70) - if not self.insertion_units: - self.insertion_units = None - else: - self.insertion_units = self.insertion_units[0] - - self.insert_units = obj.get_type(1070) - if not self.insert_units: - self.insert_units = None - else: - self.insert_units = self.insert_units[0] - - - - - - - def __repr__(self): - return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units) - - - - -class Block: - """Class for objects representing dxf blocks.""" - - def __init__(self, obj): - """Expects an entity object of type block as input.""" - if not obj.type == 'block': - raise TypeError, "Wrong type %s for block object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - self.name = obj.name - - # required data - self.flags = obj.get_type(70)[0] - self.entities = dxfObject('block_contents') - self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) - - # optional data (with defaults) - self.path = obj.get_type(1) - if self.path: - self.path = self.path[0] - else: - self.path = '' - - self.discription = obj.get_type(4) - if self.discription: - self.discription = self.discription[0] - else: - self.discription = '' - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - - - - - def get_loc(self, data): - """Gets the insert point of the block.""" - loc = [0, 0, 0] - for item in data: - if type(item) != list: - continue - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - def __repr__(self): - return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path) - - - - -class Insert: - """Class for objects representing dxf inserts.""" - - def __init__(self, obj): - """Expects an entity object of type insert as input.""" - if not obj.type == 'insert': - raise TypeError, "Wrong type %s for insert object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.block = obj.get_type(2)[0] - - # optional data (with defaults) - self.rotation = obj.get_type(50) - if self.rotation: - self.rotation = self.rotation[0] - else: - self.rotation = 0 - - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - self.scale = self.get_scale(obj.data) - self.rows, self.columns = self.get_array(obj.data) - self.extrusion = self.get_extrusion(obj.data) - - - - - - def get_loc(self, data): - """Gets the center location for circle type objects. - - Circles have a single coord location. - """ - loc = [0, 0, 0] - for item in data: - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - def get_scale(self, data): - """Gets the x/y/z scale factor for the block. - """ - scale = [1, 1, 1] - for item in data: - if item[0] == 41: # 41 = x scale - scale[0] = item[1] - elif item[0] == 42: # 42 = y scale - scale[1] = item[1] - elif item[0] == 43: # 43 = z scale - scale[2] = item[1] - return scale - - - - def get_array(self, data): - """Returns the pair (row number, row spacing), (column number, column spacing).""" - columns = 1 - rows = 1 - cspace = 0 - rspace = 0 - for item in data: - if item[0] == 70: # 70 = columns - columns = item[1] - elif item[0] == 71: # 71 = rows - rows = item[1] - if item[0] == 44: # 44 = columns - cspace = item[1] - elif item[0] == 45: # 45 = rows - rspace = item[1] - return (rows, rspace), (columns, cspace) - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, block - %s" %(self.__class__.__name__, self.layer, self.block) - - - def draw(self, handle, settings): - """Do all the specific things needed to import blocks into Blender. - - Blocks are made of three objects: - the block_record in the tables section - the block in the blocks section - the insert object in the entities section - - block_records give the insert units, blocks provide the objects drawn in the - block, and the insert object gives the location/scale/rotation of the block - instances. To draw a block you must first get a group with all the - blocks entities drawn in it, then scale the entities to match the world - units, then dupligroup that data to an object matching each insert object.""" - - # Create an object - ob = Object.New('Mesh', self.block) - ob.link(handle) # Give the object a handle - - if settings.drawTypes['blocks']: - # get our block group - block = settings.blocks(self.block) - - ob.DupGroup = block - ob.enableDupGroup = True - - ob.loc = tuple(self.loc) - transform(self.extrusion, ob) - ob.RotZ += radians(self.rotation) - ob.size = tuple(self.scale) - - return ob - - - - -class Ellipse: - """Class for objects representing dxf ellipses.""" - - def __init__(self, obj): - """Expects an entity object of type ellipse as input.""" - if not obj.type == 'ellipse': - raise TypeError, "Wrong type %s for ellipse object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # required data - self.ratio = obj.get_type(40)[0] - self.start_angle = obj.get_type(41)[0] - self.end_angle = obj.get_type(42)[0] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.loc = self.get_loc(obj.data) - self.major = self.get_major(obj.data) - self.extrusion = self.get_extrusion(obj.data) - self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2) - - - - - def get_loc(self, data): - """Gets the center location for arc type objects. - - Arcs have a single coord location. - """ - loc = [0, 0, 0] - for item in data: - if item[0] == 10: # 10 = x - loc[0] = item[1] - elif item[0] == 20: # 20 = y - loc[1] = item[1] - elif item[0] == 30: # 30 = z - loc[2] = item[1] - return loc - - - - def get_major(self, data): - """Gets the major axis for ellipse type objects. - - The ellipse major axis defines the rotation of the ellipse and its radius. - """ - loc = [0, 0, 0] - for item in data: - if item[0] == 11: # 11 = x - loc[0] = item[1] - elif item[0] == 21: # 21 = y - loc[1] = item[1] - elif item[0] == 31: # 31 = z - loc[2] = item[1] - return loc - - - - def get_extrusion(self, data): - """Find the axis of extrusion. - - Used to get the objects Object Coordinate System (ocs). - """ - vec = [0,0,1] - for item in data: - if item[0] == 210: # 210 = x - vec[0] = item[1] - elif item[0] == 220: # 220 = y - vec[1] = item[1] - elif item[0] == 230: # 230 = z - vec[2] = item[1] - return vec - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, curves=False): - """Do all the specific things needed to import ellipses into Blender.""" - # Generate the geometery - # Now Create an object - if curves: - ob = drawCurveArc(self) - else: - major = Mathutils.Vector(self.major) - delta = Mathutils.AngleBetweenVecs(major, WORLDX) - center = self.loc - radius = major.length - start = degrees(self.start_angle) - end = degrees(self.end_angle) - verts, edges = drawArc(None, radius, start, end) - - e = Mesh.New('ellipse') - - e.verts.extend(verts) # add vertices to mesh - e.edges.extend(edges) # add edges to the mesh - - - ob = Object.New('Mesh', 'arc') - ob.link(e) # link curve data with this object - ob.loc = tuple(center) - ob.SizeY = self.ratio - #ob.RotZ = radians(delta) - ob.RotX = radians(180) - - - transform(self.extrusion, ob) - ob.RotZ = radians(delta) - - return ob - - - -class Face: - """Class for objects representing dxf 3d faces.""" - - def __init__(self, obj): - """Expects an entity object of type 3dfaceplot as input.""" - if not obj.type == '3dface': - raise TypeError, "Wrong type %s for 3dface object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - - # optional data (with defaults) - self.space = obj.get_type(67) - if self.space: - self.space = self.space[0] - else: - self.space = 0 - - self.color_index = obj.get_type(62) - if self.color_index: - self.color_index = self.color_index[0] - else: - self.color_index = BYLAYER - - discard, self.layer = get_layer(obj.data) - obj.data.remove(discard) - self.points = self.get_points(obj.data) - - - - - def get_points(self, data): - """Gets 3-4 points for a 3d face type object. - - Faces have three or optionally four verts. - """ - - a = [0, 0, 0] - b = [0, 0, 0] - c = [0, 0, 0] - d = False - for item in data: - # ----------- a ------------- - if item[0] == 10: # 10 = x - a[0] = item[1] - elif item[0] == 20: # 20 = y - a[1] = item[1] - elif item[0] == 30: # 30 = z - a[2] = item[1] - # ----------- b ------------- - elif item[0] == 11: # 11 = x - b[0] = item[1] - elif item[0] == 21: # 21 = y - b[1] = item[1] - elif item[0] == 31: # 31 = z - b[2] = item[1] - # ----------- c ------------- - elif item[0] == 12: # 12 = x - c[0] = item[1] - elif item[0] == 22: # 22 = y - c[1] = item[1] - elif item[0] == 32: # 32 = z - c[2] = item[1] - # ----------- d ------------- - elif item[0] == 13: # 13 = x - d = [0, 0, 0] - d[0] = item[1] - elif item[0] == 23: # 23 = y - d[1] = item[1] - elif item[0] == 33: # 33 = z - d[2] = item[1] - out = [a,b,c] - if d: - out.append(d) - return out - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, curves=False): - """Do all the specific things needed to import 3d faces into Blender.""" - # Generate the geometery - points = self.points - if len(self.points) > 3: - faces = [[0, 1, 2, 3]] - else: - faces = [[0, 1, 2]] - - me = Mesh.New('3dface') # create a new mesh - - me.verts.extend(points) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - # Now Create an object - ob = Object.New('Mesh', '3dface') # link mesh to an object - ob.link(me) - - return ob - - - -# type to object map + +class Layer: #----------------------------------------------------------------- + """Class for objects representing dxf layers. + """ + def __init__(self, obj, name=None, color=None, frozen=None): + """Expects an object of type layer as input. + """ + self.type = obj.type + self.data = obj.data[:] + + if name: + self.name = name + #self.bfname = name #remi--todo----------- + else: + self.name = obj.get_type(2)[0] #layer name of object + + if color: + self.color = color + else: + self.color = obj.get_type(62)[0] #color of object + + if frozen: + self.frozen = frozen + else: + self.flags = obj.get_type(70)[0] + self.frozen = self.flags&1 + + + def __repr__(self): + return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color) + + + +def getit(obj, typ, default=None): #------------------------------------------ + """Universal procedure for geting data from list/objects. + """ + it = default + if type(obj) == list: #if obj is a list, then searching in a list + for item in obj: + #print 'deb:getit item, type(item)', item, type(item) + try: + if item[0] == typ: + it = item[1] + break #as soon as the first found + except: + # TODO - I found one case where item was a text instance + # that failed with no __getitem__ + pass + else: #else searching in Object with get_type-Methode + item = obj.get_type(typ) + if item: + it = item[0] + #print 'deb:getit:typ, it', typ, it #---------- + return it + + + +def get_extrusion(data): #------------------------------------------------- + """Find the axis of extrusion. + + Used to get from object_data the objects Object Coordinate System (ocs). + """ + #print 'deb:get_extrusion: data: \n', data #--------------- + vec = [0,0,1] + vec[0] = getit(data, 210, 0) # 210 = x + vec[1] = getit(data, 220, 0) # 220 = y + vec[2] = getit(data, 230, 1) # 230 = z + #print 'deb:get_extrusion: vec: ', vec #--------------- + return vec + + + + + +class Solid: #----------------------------------------------------------------- + """Class for objects representing dxf solid or trace. + """ + def __init__(self, obj): + """Expects an entity object of type solid or trace as input. + """ + if obj.type == 'trace': + obj.type = 'solid' + if not obj.type == 'solid': + raise TypeError, "Wrong type \'%s\' for solid/trace object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.extrusion = get_extrusion(obj.data) + self.points = self.get_points(obj.data) + + + + def get_points(self, data): + """Gets start and end points for a solid type object. + + Solids have 3 or 4 points and fixed codes for each value. + """ + + # start x, y, z and end x, y, z = 0 + a = [0, 0, 0] + b = [0, 0, 0] + c = [0, 0, 0] + d = [0, 0, 0] + a[0] = getit(data, 10, None) # 10 = x + a[1] = getit(data, 20, None) # 20 = y + a[2] = getit(data, 30, 0) # 30 = z + b[0] = getit(data, 11, None) + b[1] = getit(data, 21, None) + b[2] = getit(data, 31, 0) + c[0] = getit(data, 12, None) + c[1] = getit(data, 22, None) + c[2] = getit(data, 32, 0) + out = [a,b,c] + + d[0] = getit(data, 13, None) + if d[0] != None: + d[1] = getit(data, 23, None) + d[2] = getit(data, 33, 0) + out.append(d) + #print 'deb:solid.vertices:---------\n', out #----------------------- + return out + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + def draw(self, settings): + """for SOLID: generate Blender_geometry. + """ + points = self.points + if not points: return + edges, faces = [], [] + l = len(self.points) + + obname = 'so_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + + vg_left, vg_right, vg_top, vg_bottom, vg_start, vg_end = [], [], [], [], [], [] + thic = set_thick(self.thic, settings) + if thic != 0: + thic_points = [[v[0], v[1], v[2] + thic] for v in points[:]] + if thic < 0.0: + thic_points.extend(points) + points = thic_points + else: + points.extend(thic_points) + + if l == 4: + faces = [[0,1,3,2], [4,6,7,5], [0,4,5,1], + [1,5,7,3], [3,7,6,2], [2,6,4,0]] + vg_left = [2,6,4,0] + vg_right = [1,5,7,3] + vg_top = [4,6,7,5] + vg_bottom = [0,1,3,2] + vg_start = [0,4,5,1] + vg_end = [3,7,6,2] + elif l == 3: + faces = [[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]] + vg_top = [3,4,5] + vg_bottom = [0,1,2] + vg_left = [2,5,3,0] + vg_right = [1,4,5,2] + vg_start = [0,3,4,1] + elif l == 2: faces = [[0,1,3,2]] + else: + if l == 4: faces = [[0,1,3,2]] + elif l == 3: faces = [[0,1,2]] + elif l == 2: edges = [[0,1]] + + + + me = Mesh.New(obname) # create a new mesh + me.verts.extend(points) # add vertices to mesh + if faces: me.faces.extend(faces) # add faces to the mesh + if edges: me.edges.extend(edges) # add faces to the mesh + + ob = SCENE.objects.new(me) # create a new mesh_object + if settings.var['vGroup_on']: + # each MeshSite becomes vertexGroup for easier material assignment --------------------- + replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.ADD/REPLACE + if vg_left: me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) + if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) + if vg_top: me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) + if vg_bottom:me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) + if vg_start:me.addVertGroup('side.start') ; me.assignVertsToGroup('side.start', vg_start, 1.0, replace) + if vg_end: me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', vg_end, 1.0, replace) + + transform(self.extrusion, 0, ob) + + return ob + + + + +class Line: #----------------------------------------------------------------- + """Class for objects representing dxf lines. + """ + def __init__(self, obj): + """Expects an entity object of type line as input. + """ + if not obj.type == 'line': + raise TypeError, "Wrong type \'%s\' for line object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0) + #print 'deb:self.thic: ', self.thic #--------------------- + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.extrusion = get_extrusion(obj.data) + self.points = self.get_points(obj.data) + + + def get_points(self, data): + """Gets start and end points for a line type object. + + Lines have a fixed number of points (two) and fixed codes for each value. + """ + # start x,y,z and end x,y,z = 0 + a = [0, 0, 0] + b = [0, 0, 0] + a[0] = getit(data, 10, None) # 10 = x + a[1] = getit(data, 20, None) # 20 = y + a[2] = getit(data, 30, 0) # 30 = z + b[0] = getit(data, 11, None) + b[1] = getit(data, 21, None) + b[2] = getit(data, 31, 0) + out = [a,b] + return out + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + def draw(self, settings): + """for LINE: generate Blender_geometry. + """ + # Generate the geometery + #settings.var['curves_on']=False + + points = self.points + + global activObjectLayer + global activObjectName + #print 'deb:draw:line.ob IN activObjectName: ', activObjectName #--------------------- + + if activObjectLayer == self.layer and settings.var['one_mesh_on']: + obname = activObjectName + #print 'deb:line.draw obname from activObjectName: ', obname #--------------------- + ob = Object.Get(obname) # open an existing mesh_object + me = Mesh.Get(ob.name) # open objects mesh data + else: + obname = 'li_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + activObjectName = ob.name + activObjectLayer = self.layer + #print ('deb:line.draw new line.ob+mesh:"%s" created!' %ob.name) #--------------------- + + #if settings.var['width_force']: # todo----------- + + faces, edges = [], [] + n = len(me.verts) + thic = set_thick(self.thic, settings) + if thic != 0: + t, e = thic, self.extrusion + #print 'deb:thic, extr: ', t, e #--------------------- + points.extend([[v[0]+t*e[0], v[1]+t*e[1], v[2]+t*e[2]] for v in points[:]]) + faces = [[0+n, 1+n, 3+n, 2+n]] + else: + me.verts.extend(points) # add vertices to mesh + edges = [[0+n, 1+n]] + + me.verts.extend(points) # add vertices to mesh + if faces: me.faces.extend(faces) # add faces to the mesh + if edges: me.edges.extend(edges) # add faces to the mesh + + if settings.var['vGroup_on']: + # entities with the same color build one vertexGroup for easier material assignment --------------------- + ob.link(me) # link mesh to that object + vG_name = 'color_%s' %self.color_index + if edges: faces = edges + replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD + try: + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: existed vGroup:', vG_name #--------------------- + except: + me.addVertGroup(vG_name) + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: create new vGroup:', vG_name #--------------------- + + + #print 'deb:draw:line.ob OUT activObjectName: ', activObjectName #--------------------- + return ob + + + +class Point: #----------------------------------------------------------------- + """Class for objects representing dxf points. + """ + def __init__(self, obj): + """Expects an entity object of type point as input. + """ + if not obj.type == 'point': + raise TypeError, "Wrong type %s for point object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0) + #print 'deb:self.thic: ', self.thic #--------------------- + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.extrusion = get_extrusion(obj.data) + self.points = self.get_points(obj.data) + + + def get_points(self, data): + """Gets coordinates for a point type object. + + Points have fixed codes for each value. + """ + a = [0, 0, 0] + a[0] = getit(data, 10, None) # 10 = x + a[1] = getit(data, 20, None) # 20 = y + a[2] = getit(data, 30, 0) # 30 = z + out = [a] + return out + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + def draw(self, settings): + """for POINT: generate Blender_geometry. + """ + points = self.points + obname = 'po_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + points_as = settings.var['points_as'] + thic = settings.var['thick_min'] + if thic < settings.var['dist_min']: thic = settings.var['dist_min'] + + if points_as in [1,3,4]: + if points_as == 1: # as 'empty' + c = 'Empty' + if points_as == 3: # as 'thin sphere' + res = settings.var['thin_res'] + c = Mesh.Primitives.UVsphere(res,res,thic) + if points_as == 4: # as 'thin box' + c = Mesh.Primitives.Cube(thic) + ob = SCENE.objects.new(c, obname) # create a new object + transform(self.extrusion, 0, ob) + ob.loc = tuple(points[0]) + + elif points_as == 2: # as 'vertex' + global activObjectLayer + global activObjectName + #print 'deb:draw:point.ob IN activObjectName: ', activObjectName #--------------------- + if activObjectLayer == self.layer and settings.var['one_mesh_on']: + obname = activObjectName + #print 'deb:draw:point.ob obname from activObjectName: ', obname #--------------------- + ob = Object.Get(obname) # open an existing mesh_object + me = Mesh.Get(ob.name) # open objects mesh data + else: + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + activObjectName = ob.name + activObjectLayer = self.layer + #print ('deb:draw:point new point.ob+mesh:"%s" created!' %ob.name) #--------------------- + me.verts.extend(points) # add vertices to mesh + + return ob + + + + +class LWpolyline: #----------------------------------------------------------------- + """Class for objects representing dxf LWpolylines. + """ + def __init__(self, obj): + """Expects an entity object of type lwpolyline as input. + """ + #print 'deb:LWpolyline.START:----------------' #------------------------ + if not obj.type == 'lwpolyline': + raise TypeError, "Wrong type %s for polyline object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.num_points = obj.get_type(90)[0] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + + self.color_index = getit(obj, 62, BYLAYER) + + self.elevation = getit(obj, 30, 0) + self.thic = getit(obj, 39, 0) + self.flags = getit(obj, 70, 0) + + self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen + + self.layer = getit(obj.data, 8, None) + self.points = self.get_points(obj.data) + self.extrusion = get_extrusion(obj.data) + + #print 'deb:LWpolyline.obj.data:\n', obj.data #------------------------ + #print 'deb:LWpolyline.ENDinit:----------------' #------------------------ + + + def get_points(self, data): + """Gets points for a polyline type object. + + LW-Polylines have no fixed number of verts, and + each vert can have a number of properties. + Verts should be coded as + 10:xvalue + 20:yvalue + 40:startwidth or 0 + 41:endwidth or 0 + 42:bulge or 0 + for each vert + """ + num = self.num_points + point = None + points = [] + for item in data: + if item[0] == 10: # 10 = x + if point: + points.append(point) + point = Vertex() + point.x = item[1] + elif item[0] == 20: # 20 = y + point.y = item[1] + elif item[0] == 40: # 40 = start width + point.swidth = item[1] + elif item[0] == 41: # 41 = end width + point.ewidth = item[1] + elif item[0] == 42: # 42 = bulge + point.bulge = item[1] + points.append(point) + return points + + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + def draw(self, settings): + """for LWPOLYLINE: generate Blender_geometry. + """ + #print 'deb:LWpolyline.draw.START:----------------' #------------------------ + points = [] + obname = 'lw_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + #settings.var['curves_on'] == True + #print 'deb:index_len: ', len(self.points) #------------------ + for i, point in enumerate(self.points): + #print 'deb:index: ', i #------------------ + if not point.bulge: + points.append(point.loc) + elif point.bulge and not self.closed and i == len(self.points)-1: + points.append(point.loc) + elif point.bulge: # + if i == len(self.points)-1: + point2 = self.points[0] + else: + point2 = self.points[i+1] + verts = drawBulge(point, point2, settings.var['arc_res']) +# if i == len(self.points)-1: +# if self.closed: +# verts.pop() #remove last(=first) vertex +# else: +# verts.pop() #remove last vertex, because this point will be writen as the next vertex + points.extend(verts) + + thic = self.thic + if settings.var['thick_force'] and thic == 0: thic = settings.var['thick_min'] + if settings.var['thick_on'] and thic != 0: + len1 = len(points) + points.extend([[point[0], point[1], point[2]+thic] for point in points]) + faces = [] + #print 'deb:len1:', len1 #----------------------- + faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] + if self.closed: + faces.append([len1-1, 0, len1, 2*len1-1]) + #print 'deb:faces_list:\n', faces #----------------------- + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(points) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + else: + edges = [[num, num+1] for num in xrange(len(points)-1)] + if self.closed: + edges.append([len(points)-1, 0]) + #print 'deb:edges_list:\n', edges #----------------------- + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(points) # add vertices to mesh + me.edges.extend(edges) # add edges to the mesh + + ob.LocZ = self.elevation + transform(self.extrusion, 0, ob) + + #print 'deb:LWpolyline.draw.END:----------------' #------------------------ + return ob + + + +class Polyline: #----------------------------------------------------------------- + """Class for objects representing dxf Polylines. + """ + def __init__(self, obj): + """Expects an entity object of type polyline as input. + """ + #print 'deb:polyline.init.START:----------------' #------------------------ + if not obj.type == 'polyline': + raise TypeError, "Wrong type %s for polyline object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + #print 'deb:polyline.obj.data[:]:\n', obj.data[:] #------------------------ + self.points = [] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.elevation = getit(obj, 30, 0) + #print 'deb:elevation: ', self.elevation #--------------- + self.thic = getit(obj, 39, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.flags = getit(obj, 70, 0) + self.closed = self.flags & 1 # closed in the M direction + self.curved = self.flags & 2 # Bezier-curve-fit vertices have been added + self.spline = self.flags & 4 # Bspline-fit vertices have been added + self.poly3d = self.flags & 8 # 3D-polyline + self.plmesh = self.flags & 16 # 3D-polygon mesh + self.closeN = self.flags & 32 # closed in the N direction + self.plface = self.flags & 64 # 3D-polyface mesh + self.contin = self.flags & 128 # the linetype pattern is generated continuously + + if self.poly3d or self.plface or self.plmesh: + self.poly2d = False # its not a 2D-polyline + else: + self.poly2d = True # it is a 2D-polyline + + self.swidth = getit(obj, 40, 0) # default start width + self.ewidth = getit(obj, 41, 0) # default end width + #self.bulge = getit(obj, 42, None) # bulge of the segment + self.vectorsM = getit(obj, 71, None) # PolyMesh: expansion in M-direction / PolyFace: number of the vertices + self.vectorsN = getit(obj, 72, None) # PolyMesh: expansion in M-direction / PolyFace: number of faces + #self.resolM = getit(obj, 73, None) # resolution of surface in M direction + #self.resolN = getit(obj, 74, None) # resolution of surface in N direction + self.curvetyp = getit(obj, 75, 0) # type of curve/surface: 0=None/5=Quadric/6=Cubic/8=Bezier + self.curvNormal = False + self.curvQBspline = False + self.curvCBspline = False + self.curvBezier = False + if self.curvetyp == 0: self.curvNormal = True + elif self.curvetyp == 5: self.curvQBspline = True + elif self.curvetyp == 6: self.curvCBspline = True + elif self.curvetyp == 8: self.curvBezier = True + + self.layer = getit(obj.data, 8, None) + self.extrusion = get_extrusion(obj.data) + + self.points = [] #list with vertices coordinats + self.faces = [] #list with vertices assigment to faces + #print 'deb:polyline.init.ENDinit:----------------' #------------ + + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + + def draw(self, settings): #-------------%%%% DRAW POLYLINE %%%--------------- + """for POLYLINE: generate Blender_geometry. + """ + ob = [] + if self.plface: #---- 3dPolyFace - mesh with free topology + ob = self.drawPlFace(settings) + elif self.plmesh: #---- 3dPolyMesh - mesh with ortogonal topology + ob = self.drawPlMesh(settings) + #---- 2dPolyline - plane polyline with arc/wide/thic segments + #---- 3dPolyline - noplane polyline (thin segments = without arc/wide/thic) + elif self.poly2d or self.poly3d: + if settings.var['curves_on']: # and self.spline: + ob = self.drawPolyCurve(settings) + else: + ob = self.drawPoly2d(settings) + return ob + + + + def drawPlFace(self, settings): #---- 3dPolyFace - mesh with free topology + """Generate the geometery of polyface. + """ + #print 'deb:polyface.draw.START:----------------' #------------------------ + points = [] + faces = [] + #print 'deb:len of pointsList ====== ', len(self.points) #------------------------ + for point in self.points: + if point.face: + faces.append(point.face) + else: + points.append(point.loc) + + + #print 'deb:len of points_list:\n', len(points) #----------------------- + #print 'deb:points_list:\n', points #----------------------- + #print 'deb:faces_list:\n', faces #----------------------- + obname = 'pf_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(points) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + transform(self.extrusion, 0, ob) + #print 'deb:polyface.draw.END:----------------' #------------------------ + + return ob + + + + def drawPlMesh(self, settings): #---- 3dPolyMesh - mesh with orthogonal topology + """Generate the geometery of polymesh. + """ + #print 'deb:polymesh.draw.START:----------------' #------------------------ + #points = [] + #print 'deb:len of pointsList ====== ', len(self.points) #------------------------ + faces = [] + m = self.vectorsM + n = self.vectorsN + for j in xrange(m - 1): + for i in xrange(n - 1): + nn = j * n + faces.append([nn+i, nn+i+1, nn+n+i+1, nn+n+i]) + + if self.closed: #mesh closed in N-direction + nn = (m-1)*n + for i in xrange(n - 1): + faces.append([nn+i, nn+i+1, i+1, i]) + + if self.closeN: #mesh closed in M-direction + for j in xrange(m-1): + nn = j * n + faces.append([nn+n-1, nn, nn+n, nn+n-1+n]) + + if self.closed and self.closeN: #mesh closed in M/N-direction + faces.append([ (n*m)-1, (m-1)*n, 0, n-1]) + + #print 'deb:len of points_list:\n', len(points) #----------------------- + #print 'deb:faces_list:\n', faces #----------------------- + obname = 'pm_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend([point.loc for point in self.points]) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + transform(self.extrusion, 0, ob) + #print 'deb:polymesh.draw.END:----------------' #------------------------ + return ob + + + def drawPolyCurve(self, settings): #---- Polyline - draw as Blender-curve + """Generate the geometery of polyline as Blender-curve. + """ + #print 'deb:polyline2dCurve.draw.START:----------------' #--- + if len(self.points) < 2: + #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- + return + + if self.spline: pline_typ = 'ps' # Polyline-nurbSpline + elif self.curved: pline_typ = 'pc' # Polyline-bezierCurve + else: pline_typ = 'pl' # Polyline + obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name + obname = obname[:MAX_NAMELENGTH] + d_points = [] + #for DXFr10-format: update all points[].loc[2] == None -> 0.0 + for point in self.points: + if point.loc[2] == None: + point.loc[2] = self.elevation + d_points.append(point) + + thic = set_thick(self.thic, settings) + + if thic != 0.0: #hack: Blender<2.45 curve-extrusion + LocZ = d_points[0].loc[2] + temp_points = [] + for point in d_points: + point.loc[2] = 0.0 + temp_points.append(point) + d_points = temp_points + + #print 'deb:polyline2dCurve.draw d_points=', d_points #--------------- + pline = Curve.New(obname) # create new curve data + + if False: #self.spline: # NURBSplines-----FAKE(with Bezier)----- + #print 'deb:polyline2dCurve.draw self.spline!' #--------------- + curve = pline.appendNurb(BezTriple.New(d_points[0])) + for p in d_points[1:]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [AUTO, AUTO] + if self.closed: + curve.flagU = 1 # Set curve cyclic=close + else: + curve.flagU = 0 # Set curve not cyclic=open + curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- + curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- + + elif self.spline: # NURBSplines-----TODO--:if curvQBspline: generate middlepoints--- + #print 'deb:polyline2dCurve.draw self.spline!' #--------------- + weight1 = 0.5 + weight2 = 1.0 + # generate middlepoints except start/end-segments --- + if self.curvQBspline: + temp_points = [] + point = d_points[0].loc + point.append(weight1) + temp_points.append(point) + for i in xrange(1,len(d_points)-2): + point1 = d_points[i].loc + point2 = d_points[i+1].loc + mpoint = list((Mathutils.Vector(point1) + Mathutils.Vector(point2)) * 0.5) + mpoint.append(weight2) + point1.append(weight1) + temp_points.append(point1) + temp_points.append(mpoint) + point2.append(weight1) + temp_points.append(point2) + point = d_points[-1].loc + point.append(weight1) + temp_points.append(point) + d_points = temp_points + else: + temp_points = [] + for d in d_points: + d = d.loc + d.append(weight1) + temp_points.append(d) + d_points = temp_points + + if not self.closed: + # generate extended startpoint and endpoint------ + point1 = Mathutils.Vector(d_points[0][:3]) + point2 = Mathutils.Vector(d_points[1][:3]) + startpoint = list(point1 - point2 + point1) + startpoint.append(weight1) + point1 = Mathutils.Vector(d_points[-1][:3]) + point2 = Mathutils.Vector(d_points[-2][:3]) + endpoint = list(point1 - point2 + point1) + endpoint.append(weight1) + temp_points = [] + temp_points.append(startpoint) + temp_points.extend(d_points) + d_points = temp_points + d_points.append(endpoint) + + point = d_points[0] + curve = pline.appendNurb(point) + curve.setType(4) #NURBS curve + for point in d_points[1:]: + curve.append(point) + if self.closed: + curve.flagU = 1 # Set curve cyclic=close + else: + curve.flagU = 0 # Set curve not cyclic=open + + elif self.curved: #--Bezier-curves---OK------- + #print 'deb:polyline2dCurve.draw self.curved!' #--------------- + curve = pline.appendNurb(BezTriple.New(d_points[0])) + for p in d_points[1:]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [AUTO, AUTO] + if self.closed: + curve.flagU = 1 # Set curve cyclic=close + else: + curve.flagU = 0 # Set curve not cyclic=open + curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- + curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- + + else: #--straight line/arc-segments----OK------ + points = [] + d_points.append(d_points[0]) #------ first vertex added ------------- + #curve.setType(0) #polygon_type of Blender_curve + for i in xrange(len(d_points)-1): + point1 = d_points[i] + point2 = d_points[i+1] + if point1.bulge and (i < len(d_points)-2 or self.closed): + arc_res = 8 + verts = drawBulge(point1, point2, arc_res) #calculate additional points for bulge + if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0])) + else: curve.append(BezTriple.New(verts[0])) + curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents + for p in verts[1:]: + curve.append(BezTriple.New(p)) + curve[-1].handleTypes = [AUTO, AUTO] #--todo--calculate bezier-tangents +# curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents + else: + if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) + else: curve.append(BezTriple.New(point1.loc)) + curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents + if self.closed: + curve.flagU = 1 # Set curve cyclic=close +# curve[0].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents + else: + curve.flagU = 0 # Set curve not cyclic=open + curve[0].handleTypes = [FREE, VECT] #--todo--calculate bezier-tangents + curve[-1].handleTypes = [VECT, FREE] #--todo--calculate bezier-tangents + + pline.update() + ob = SCENE.objects.new(pline) # create a new curve_object + + if thic != 0.0: #hack: Blender<2.45 curve-extrusion + thic = thic * 0.5 + pline.setExt1(1.0) # curve-extrusion accepts only (0.0 - 2.0) + ob.LocZ = thic + LocZ + + transform(self.extrusion, 0, ob) + # scaleZ to the thickness + if thic != 0.0: + #old_LocZ = ob.LocZ + #ob.LocZ = 0.0 + ob.SizeZ *= abs(thic) + #ob.LocZ = old_LocZ + + #print 'deb:polyline2dCurve.draw.END:----------------' #----- + return ob + + + def drawPoly2d(self, settings): #---- 2dPolyline - plane wide/thic lines + """Generate the geometery of regular polyline. + """ + #print 'deb:polyline2d.draw.START:----------------' #------------------------ + points = [] + d_points = [] + swidths = [] + ewidths = [] + swidth_default = self.swidth #default start width of POLYLINEs segments + ewidth_default = self.ewidth #default end width of POLYLINEs segments + thic = set_thick(self.thic, settings) + if self.spline: pline_typ = 'ps' + elif self.curved: pline_typ = 'pc' + else: pline_typ = 'pl' + obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name +# obname = 'pl_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + + if len(self.points) < 2: + #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- + return + #d_points = self.points[:] + #for DXFr10-format: update all points[].loc[2] == None -> 0.0 + for point in self.points: + if point.loc[2] == None: + point.loc[2] = self.elevation + d_points.append(point) + #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ + + #add duplic of the first vertex at the end of pointslist + d_points.append(d_points[0]) + + #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ + #print 'deb:d_pointsList ======:\n ', d_points #------------------------ + + + #routine to sort out of "double.vertices" -------- + minimal_dist = settings.var['dist_min'] * 0.1 + temp_points = [] + for i in xrange(len(d_points)-1): + point = d_points[i] + point2 = d_points[i+1] + #print 'deb:double.vertex p1,p2', point, point2 #------------------------ + delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc) + if delta.length > minimal_dist: + temp_points.append(point) + #else: print 'deb:double.vertex sort out!' #------------------------ + temp_points.append(d_points[-1]) #------ last vertex added ------------- + d_points = temp_points #-----vertex.list without "double.vertices" + #print 'deb:d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + + #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ + if len(d_points) < 2: + #print 'deb:drawPoly2d corrupted Vertices' #--------- + return + + #analyse of straight- and bulge-segments (generation of additional points for bulge) + exist_wide_segment = False + for i in xrange(len(d_points)-1): + point1 = d_points[i] + point2 = d_points[i+1] + #print 'deb:pline.tocalc.point1:', point1 #------------------------ + #print 'deb:pline.tocalc.point2:', point2 #------------------------ + + swidth = point1.swidth + ewidth = point1.ewidth + if swidth == None: swidth = swidth_default + if ewidth == None: ewidth = ewidth_default + + if swidth != 0.0 or ewidth != 0.0: exist_wide_segment = True + + if settings.var['width_force']: # force minimal width for thin segments + if swidth < settings.var['width_min']: swidth = settings.var['width_min'] + if ewidth < settings.var['width_min']: ewidth = settings.var['width_min'] + if not settings.var['width_on']: # then force minimal width for all segments + swidth = settings.var['width_min'] + ewidth = settings.var['width_min'] + + if point1.bulge and (i < (len(d_points)-2) or self.closed): + verts = drawBulge(point1, point2, settings.var['arc_res']) #calculate additional points for bulge + points.extend(verts) + delta_width = (ewidth - swidth) / len(verts) + width_list = [swidth + (delta_width * ii) for ii in xrange(len(verts)+1)] + swidths.extend(width_list[0:-1]) + ewidths.extend(width_list[1:]) + else: + points.append(point1.loc) + swidths.append(swidth) + ewidths.append(ewidth) + + + #--calculate width_vectors: left-side- and right-side-points ---------------- + # 1.level:IF width --------------------------------------- + if (settings.var['width_on'] and exist_wide_segment) or settings.var['width_force']: + points.append(d_points[0].loc) #temporarly add first vertex at the end (for better loop) + + pointsLs = [] # list of left-start-points + pointsLe = [] # list of left-end-points + pointsRs = [] # list of right-start-points + pointsRe = [] # list of right-end-points + pointsW = [] # list of entire-border-points + #rotMatr90 = Mathutils.Matrix(rotate 90 degree around Z-axis) = normalvectorXY + rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1]) + for i in xrange(len(points)-1): + point1 = points[i] + point2 = points[i+1] + point1vec = Mathutils.Vector(point1) + point2vec = Mathutils.Vector(point2) + swidth05 = swidths[i] * 0.5 + ewidth05 = ewidths[i] * 0.5 + if swidth05 == 0: swidth05 = 0.5 * settings.var['dist_min'] #minimal width + if ewidth05 == 0: ewidth05 = 0.5 * settings.var['dist_min'] #minimal width + + normal_vector = rotMatr90 * (point2vec-point1vec).normalize() + swidth05vec = swidth05 * normal_vector + ewidth05vec = ewidth05 * normal_vector + pointsLs.append(point1vec + swidth05vec) #vertex left start + pointsRs.append(point1vec - swidth05vec) #vertex right start + pointsLe.append(point2vec + ewidth05vec) #vertex left end + pointsRe.append(point2vec - ewidth05vec) #vertex right end + + pointsLc, pointsRc = [], [] + + # 2.level:IF width and corner-intersection activated + if settings.var['pl_section_on']: #optional clean corner-intersections + if not self.closed: + pointsLc.append(pointsLs[0]) + pointsRc.append(pointsRs[0]) + lenL = len(pointsLs)-2 #without the last point at the end of the list + else: + pointsLs.append(pointsLs[0]) + pointsRs.append(pointsRs[0]) + pointsLe.append(pointsLe[0]) + pointsRe.append(pointsRe[0]) + points.append(points[0]) + lenL = len(pointsLs)-1 #without the duplic of the first point at the end of the list + #print 'deb:pointsLs():\n', pointsLs #---------------- + #print 'deb:lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- + for i in xrange(lenL): + pointVec = Mathutils.Vector(points[i+1]) + #print 'deb:pointVec: ', pointVec #------------- + #compute left-corner-points + vecL1 = pointsLs[i] + vecL2 = pointsLe[i] + vecL3 = pointsLs[i+1] + vecL4 = pointsLe[i+1] + #print 'deb:vectorsL:---------\n', vecL1,'\n',vecL2,'\n',vecL3,'\n',vecL4 #------------- + #cornerpointL = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4) + cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) + #print 'deb:cornerpointL: ', cornerpointL #------------- + + #compute right-corner-points + vecR1 = pointsRs[i] + vecR2 = pointsRe[i] + vecR3 = pointsRs[i+1] + vecR4 = pointsRe[i+1] + #print 'deb:vectorsR:---------\n', vecR1,'\n',vecR2,'\n',vecR3,'\n',vecR4 #------------- + #cornerpointR = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4) + cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) + #print 'deb:cornerpointR: ', cornerpointR #------------- + + #if diststance(cornerL-center-cornerR) < limiter * (seg1_endWidth + seg2_startWidth) + if cornerpointL != None and cornerpointR != None: + cornerpointL = cornerpointL[0] + cornerpointR = cornerpointR[0] + max_cornerDist = (vecL2 - vecR2).length + (vecL3 - vecR3).length + is_cornerDist = (cornerpointL - pointVec).length + (cornerpointR - pointVec).length + # anglecut --------- limited by ANGLECUT_LIMIT (1.0 - 5.0) + if is_cornerDist < max_cornerDist * settings.var['angle_cut']: + pointsLc.append(cornerpointL) + pointsRc.append(cornerpointR) + else: + pointsLc.extend((pointsLe[i],pointsLs[i+1])) + pointsRc.extend((pointsRe[i],pointsRs[i+1])) + else: + pointsLc.extend((pointsLe[i],pointsLs[i+1])) + pointsRc.extend((pointsRe[i],pointsRs[i+1])) + if not self.closed: + pointsLc.append(pointsLe[-2]) + pointsRc.append(pointsRe[-2]) + else: + """ """ + + # 2.level:IF width but not corner-intersection activated + else: + # points_multiplexer of start-points and end-points + lenL = len(pointsLs) - 1 #without the duplic of the first point at the end of list + if self.closed: lenL += 1 #inclusive the duplic of the first point at the end of list + for i in xrange(lenL): + pointsLc.extend((pointsLs[i], pointsLe[i])) + pointsRc.extend((pointsRs[i], pointsRe[i])) + + pointsW = pointsLc + pointsRc # all_points_List = left_side + right_side + #print 'deb:pointsW():\n', pointsW #---------------- + len1 = int(len(pointsW) * 0.5) + #print 'deb:len1:', len1 #----------------------- + + # 2.level:IF width and thickness --------------------- + if thic != 0: + thic_pointsW = [] + thic_pointsW.extend([[point[0], point[1], point[2]+thic] for point in pointsW]) + if thic < 0.0: + thic_pointsW.extend(pointsW) + pointsW = thic_pointsW + else: + pointsW.extend(thic_pointsW) + faces = [] + f_start, f_end = [], [] + f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)] + f_top = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)] + f_left = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)] + f_right = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)] + + if self.closed: + f_bottom.append([len1-1, 0, len1, len1+len1-1]) #bottom face + f_top.append( [len1+len1+len1-1, len1+len1+len1+len1-1, len1+len1+len1, len1+len1+0]) #top face + f_left.append( [0, len1-1, len1+len1+len1-1, len1+len1]) #left face + f_right.append( [len1, len1+len1+len1, len1+len1+len1+len1-1, len1+len1-1]) #right face + else: + f_start = [[0, len1, len1+len1+len1, len1+len1]] + f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] + + faces = f_bottom + f_top + f_left + f_right + f_start + f_end + #faces = f_bottom + f_top + #faces = f_left + f_right + f_start + f_end + #print 'deb:faces_list:\n', faces #----------------------- + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(pointsW) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + # each MeshSite becomes vertexGroup for easier material assignment --------------------- + # The mesh must first be linked to an object so the method knows which object to update. + # This is because vertex groups in Blender are stored in the object -- not in the mesh, + # which may be linked to more than one object. + if settings.var['vGroup_on']: + # each MeshSite becomes vertexGroup for easier material assignment --------------------- + replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD + vg_left, vg_right, vg_top, vg_bottom = [], [], [], [] + for v in f_left: vg_left.extend(v) + for v in f_right: vg_right.extend(v) + for v in f_top: vg_top.extend(v) + for v in f_bottom: vg_bottom.extend(v) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + if not self.closed: + me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) + me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) + + + # 2.level:IF width, but no-thickness --------------------- + else: + faces = [] + faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] + if self.closed: + faces.append([len1, 0, len1-1, len1+len1-1]) + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(pointsW) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + + # 1.level:IF no-width, but thickness --------------------- + elif thic != 0: + len1 = len(points) + thic_points = [] + thic_points.extend([[point[0], point[1], point[2]+thic] for point in points]) + if thic < 0.0: + thic_points.extend(points) + points = thic_points + else: + points.extend(thic_points) + faces = [] + faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] + if self.closed: + faces.append([len1-1, 0, len1, 2*len1-1]) + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(points) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + # 1.level:IF no-width and no-thickness --------------------- + else: + edges = [[num, num+1] for num in xrange(len(points)-1)] + if self.closed: + edges.append([len(points)-1, 0]) + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + me.verts.extend(points) # add vertices to mesh + me.edges.extend(edges) # add edges to the mesh + + transform(self.extrusion, 0, ob) + #print 'deb:polyline.draw.END:----------------' #----------------------- + return ob + + + + +class Vertex(object): #----------------------------------------------------------------- + """Generic vertex object used by polylines (and maybe others). + """ + + def __init__(self, obj=None): + """Initializes vertex data. + + The optional obj arg is an entity object of type vertex. + """ + #print 'deb:Vertex.init.START:----------------' #----------------------- + self.loc = [0,0,0] + self.face = [] + self.swidth = 0 + self.ewidth = 0 + self.bulge = 0 + if obj is not None: + if not obj.type == 'vertex': + raise TypeError, "Wrong type %s for vertex object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + self.get_props(obj.data) + #print 'deb:Vertex.init.END:----------------' #------------------------ + + + def get_props(self, data): + """Gets coords for a VERTEX type object. + + Each vert can have a number of properties. + Verts should be coded as + 10:xvalue + 20:yvalue + 40:startwidth or 0 + 41:endwidth or 0 + 42:bulge or 0 + """ + self.x = getit(data, 10, None) + self.y = getit(data, 20, None) + self.z = getit(data, 30, None) + + self.flags = getit(data, 70, 0) # flags + self.curved = self.flags&1 # Bezier-curve-fit:additional-vertex + self.curv_t = self.flags&2 # Bezier-curve-fit:tangent exists + self.spline = self.flags&8 # Bspline-fit:additional-vertex + self.splin2 = self.flags&16 # Bspline-fit:control-vertex + self.poly3d = self.flags&32 # polyline3d:control-vertex + self.plmesh = self.flags&64 # polymesh3d:control-vertex + self.plface = self.flags&128 # polyface + + # if PolyFace.Vertex with Face_definition + if self.curv_t: + self.curv_tangent = getit(data, 50, None) # curve_tangent + + if self.plface and not self.plmesh: + v1 = getit(data, 71, 0) # polyface:Face.vertex 1. + v2 = getit(data, 72, 0) # polyface:Face.vertex 2. + v3 = getit(data, 73, 0) # polyface:Face.vertex 3. + v4 = getit(data, 74, None) # polyface:Face.vertex 4. + self.face = [abs(v1)-1,abs(v2)-1,abs(v3)-1] + if v4 != None: + self.face.append(abs(v4)-1) + else: #--parameter for polyline2d + self.swidth = getit(data, 40, None) # start width + self.ewidth = getit(data, 41, None) # end width + self.bulge = getit(data, 42, 0) # bulge of segment + + + def __len__(self): + return 3 + + + def __getitem__(self, key): + return self.loc[key] + + + def __setitem__(self, key, value): + if key in [0,1,2]: + self.loc[key] + + + def __iter__(self): + return self.loc.__iter__() + + + def __str__(self): + return str(self.loc) + + + def __repr__(self): + return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s, face=%s" %(self.loc, self.swidth, self.ewidth, self.bulge, self.face) + + + def getx(self): + return self.loc[0] + def setx(self, value): + self.loc[0] = value + x = property(getx, setx) + + + def gety(self): + return self.loc[1] + def sety(self, value): + self.loc[1] = value + y = property(gety, sety) + + + def getz(self): + return self.loc[2] + def setz(self, value): + self.loc[2] = value + z = property(getz, setz) + + + +class Text: #----------------------------------------------------------------- + """Class for objects representing dxf Text. + """ + def __init__(self, obj): + """Expects an entity object of type text as input. + """ + if not obj.type == 'text': + raise TypeError, "Wrong type %s for text object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.height = 1.7 * obj.get_type(40)[0] #text.height + self.value = obj.get_type(1)[0] #The text string value + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.color_index = getit(obj, 62, BYLAYER) + self.thic = getit(obj, 39, 0) + + self.rotation = getit(obj, 50, 0) # radians + self.width_factor = getit(obj, 41, 1) # Scaling factor along local x axis + self.oblique = getit(obj, 51, 0) # oblique angle: skew in degrees -90 <= oblique <= 90 + + #self.style = getit(obj, 7, 'STANDARD') # todo---- Text style name (optional, default = STANDARD) + + #Text generation flags (optional, default = 0): + #2 = backward (mirrored in X), + #4 = upside down (mirrored in Y) + self.flags = getit(obj, 71, 0) + self.mirrorX, self.mirrorY = 1.0, 1.0 + if self.flags&2: self.mirrorX = - 1.0 + if self.flags&4: self.mirrorY = - 1.0 + + # vertical.alignment: 0=baseline, 1=bottom, 2=middle, 3=top + self.valignment = getit(obj, 73, 0) + #Horizontal text justification type (optional, default = 0) integer codes (not bit-coded) + #0=left, 1=center, 2=right + #3=aligned, 4=middle, 5=fit + self.halignment = getit(obj, 72, 0) + + self.layer = getit(obj.data, 8, None) + self.loc1, self.loc2 = self.get_loc(obj.data) + if self.loc2[0] != None and self.halignment != 5: + self.loc = self.loc2 + else: + self.loc = self.loc1 + self.extrusion = get_extrusion(obj.data) + + + + def get_loc(self, data): + """Gets adjusted location for text type objects. + + If group 72 and/or 73 values are nonzero then the first alignment point values + are ignored and AutoCAD calculates new values based on the second alignment + point and the length and height of the text string itself (after applying the + text style). If the 72 and 73 values are zero or missing, then the second + alignment point is meaningless. + I don't know how to calc text size... + """ + # bottom left x, y, z and justification x, y, z = 0 + #x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0 + x = getit(data, 10, None) #First alignment point (in OCS). + y = getit(data, 20, None) + z = getit(data, 30, 0.0) + jx = getit(data, 11, None) #Second alignment point (in OCS). + jy = getit(data, 21, None) + jz = getit(data, 31, 0.0) + return [x, y, z],[jx, jy, jz] + + + def __repr__(self): + return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) + + + def draw(self, settings): + """for TEXTs: generate Blender_geometry. + """ + obname = 'tx_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + txt = Text3d.New(obname) + ob = SCENE.objects.new(txt) # create a new text_object + + txt.setText(self.value) + txt.setSize(1.0) #Blender<2.45 accepts only (0.0 - 5.0) + #txt.setSize(self.height) + #txt.setWidth(self.bold) + #setLineSeparation(sep) + txt.setShear(self.oblique/90) + + thic = set_thick(self.thic, settings) + if thic != 0.0: + thic = self.thic * 0.5 + self.loc[2] += thic + txt.setExtrudeDepth(1.0) #Blender<2.45 accepts only (0.1 - 10.0) + if self.halignment == 0: + align = Text3d.LEFT + elif self.halignment == 1: + align = Text3d.MIDDLE + elif self.halignment == 2: + align = Text3d.RIGHT + else: + align = Text3d.LEFT + txt.setAlignment(align) + + if self.valignment == 1: + txt.setYoffset(0.0) + elif self.valignment == 2: + txt.setYoffset(- self.height * 0.5) + elif self.valignment == 3: + txt.setYoffset(- self.height) + + # move the object center to the text location + ob.loc = tuple(self.loc) + transform(self.extrusion, self.rotation, ob) + + # flip it and scale it to the text width + ob.SizeX *= self.height * self.width_factor * self.mirrorX + ob.SizeY *= self.height * self.mirrorY + if thic != 0.0: ob.SizeZ *= abs(thic) + return ob + + + +def set_thick(thickness, settings): + """Set thickness relative to settings variables. + + python trick: sign(x)=cmp(x,0) + """ + if settings.var['thick_force']: + if settings.var['thick_on']: + if abs(thickness) < settings.var['thick_min']: + thic = settings.var['thick_min'] * cmp(self.thic,0) + else: thic = thickness + else: thic = settings.var['thick_min'] + else: + if settings.var['thick_on']: thic = thickness + else: thic = 0.0 + return thic + + + + +class Mtext: #----------------------------------------------------------------- + """Class for objects representing dxf Mtext. + """ + + def __init__(self, obj): + """Expects an entity object of type mtext as input. + """ + if not obj.type == 'mtext': + raise TypeError, "Wrong type %s for mtext object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.height = obj.get_type(40)[0] + self.width = obj.get_type(41)[0] + 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 + self.value = self.get_text(obj.data) # The text string value + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.color_index = getit(obj, 62, BYLAYER) + self.rotation = getit(obj, 50, 0) # radians + + self.width_factor = getit(obj, 42, 1) # Scaling factor along local x axis + self.line_space = getit(obj, 44, 1) # percentage of default + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + self.extrusion = get_extrusion(obj.data) + + + def get_text(self, data): + """Reconstructs mtext data from dxf codes. + """ + primary = '' + secondary = [] + for item in data: + if item[0] == 1: # There should be only one primary... + primary = item[1] + elif item[0] == 3: # There may be any number of extra strings (in order) + secondary.append(item[1]) + if not primary: + #raise ValueError, "Empty Mtext Object!" + string = "Empty Mtext Object!" + if not secondary: + string = primary.replace(r'\P', '\n') + else: + string = ''.join(secondary)+primary + string = string.replace(r'\P', '\n') + return string + + + def get_loc(self, data): + """Gets location for a mtext type objects. + + Mtext objects have only one point indicating + """ + loc = [0, 0, 0] + loc[0] = getit(data, 10, None) + loc[1] = getit(data, 20, None) + loc[2] = getit(data, 30, 0.0) + return loc + + + def __repr__(self): + return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) + + + def draw(self, settings): + """for MTEXTs: generate Blender_geometry. + """ + # Now Create an object + obname = 'tm_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + txt = Text3d.New(obname) + ob = SCENE.objects.new(txt) # create a new text_object + + txt.setSize(1) + # Blender doesn't give access to its text object width currently + # only to the text3d's curve width... + #txt.setWidth(text.width/10) + txt.setLineSeparation(self.line_space) + txt.setExtrudeDepth(0.5) + txt.setText(self.value) + + # scale it to the text size + ob.SizeX = self.height * self.width_factor + ob.SizeY = self.height + ob.SizeZ = self.height + + # move the object center to the text location + ob.loc = tuple(self.loc) + transform(self.extrusion, self.rotation, ob) + + return ob + + + + +class Circle: #----------------------------------------------------------------- + """Class for objects representing dxf Circles. + """ + + def __init__(self, obj): + """Expects an entity object of type circle as input. + """ + if not obj.type == 'circle': + raise TypeError, "Wrong type %s for circle object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.radius = obj.get_type(40)[0] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + self.extrusion = get_extrusion(obj.data) + + + + def get_loc(self, data): + """Gets the center location for circle type objects. + + Circles have a single coord location. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 10, None) + loc[1] = getit(data, 20, None) + loc[2] = getit(data, 30, 0.0) + return loc + + + + def __repr__(self): + return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) + + + def draw(self, settings): + """for CIRCLE: generate Blender_geometry. + """ + obname = 'ci_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + radius = self.radius + + thic = set_thick(self.thic, settings) + if settings.var['curves_on']: + c = Curve.New(obname) # create new curve data + p1 = (0, -radius, 0) + p2 = (radius, 0, 0) + p3 = (0, radius, 0) + p4 = (-radius, 0, 0) + + p1 = BezTriple.New(p1) + p2 = BezTriple.New(p2) + p3 = BezTriple.New(p3) + p4 = BezTriple.New(p4) + + curve = c.appendNurb(p1) + curve.append(p2) + curve.append(p3) + curve.append(p4) + for point in curve: + point.handleTypes = [AUTO, AUTO] + curve.flagU = 1 # Set curve cyclic=closed + c.update() + + else: + if radius < 2 * settings.var['dist_min']: # if circumfence is very small + verts_num = settings.var['thin_res'] # set a fixed number of verts + else: + #verts = circ/settings.var['dist_min'] # figure out how many verts we need + verts_num = settings.var['arc_res'] # figure out how many verts we need + if verts_num > 500: verts_num = 500 # Blender accepts only values [3:500] + if thic != 0: + loc2 = thic * 0.5 #-----blenderAPI draw Cylinder with 2*thickness + self.loc[2] += loc2 #---new location for the basis of cylinder + #print 'deb:circleDraw:self.loc2:', self.loc #----------------------- + c = Mesh.Primitives.Cylinder(int(verts_num), radius*2, abs(thic)) + else: + c = Mesh.Primitives.Circle(int(verts_num), radius*2) + + ob = SCENE.objects.new(c, obname) # create a new circle_mesh_object + ob.loc = tuple(self.loc) + transform(self.extrusion, 0, ob) + return ob + + + +class Arc: #----------------------------------------------------------------- + """Class for objects representing dxf arcs. + """ + + def __init__(self, obj): + """Expects an entity object of type arc as input. + """ + if not obj.type == 'arc': + raise TypeError, "Wrong type %s for arc object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.radius = obj.get_type(40)[0] + self.start_angle = obj.get_type(50)[0] + self.end_angle = obj.get_type(51)[0] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + self.extrusion = get_extrusion(obj.data) + + + + def get_loc(self, data): + """Gets the center location for arc type objects. + + Arcs have a single coord location. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 10, None) + loc[1] = getit(data, 20, None) + loc[2] = getit(data, 30, 0.0) + return loc + + + + def __repr__(self): + return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) + + + def draw(self, settings): + """for ARC: generate Blender_geometry. + """ + obname = 'ar_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + + center = self.loc + radius = self.radius + start = self.start_angle + end = self.end_angle + #print 'deb:drawArc: center, radius, start, end:\n', center, radius, start, end #--------- + thic = set_thick(self.thic, settings) + + if settings.var['curves_on']: + arc_res = 8 + verts, edges = drawArc(None, radius, start, end, arc_res) + arc = Curve.New(obname) # create new curve data + curve = arc.appendNurb(BezTriple.New(verts[0])) + for p in verts[1:]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [AUTO, AUTO] + #print 'deb:arc.draw point=', point #--------------- + curve[0].handleTypes = [FREE, VECT] #remi--todo----- + curve[-1].handleTypes = [VECT, FREE] #remi--todo----- + curve.flagU = 0 # Set curve not cyclic=open + arc.update() + + else: + arc = Mesh.New(obname) # create a new mesh + verts, edges = drawArc(None, radius, start, end, settings.var['arc_res']) + if thic != 0: + len1 = len(verts) + thic_verts = [] + thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) + if thic < 0.0: + thic_verts.extend(verts) + verts = thic_verts + else: + verts.extend(thic_verts) + faces = [] + #print 'deb:len1:', len1 #----------------------- + #print 'deb:verts:', verts #remi-todo----- why is this List inhomogene ---------- + faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] + + arc.verts.extend(verts) # add vertices to mesh + arc.faces.extend(faces) # add faces to the mesh + else: + arc.verts.extend(verts) # add vertices to mesh + arc.edges.extend(edges) # add edges to the mesh + + ob = SCENE.objects.new(arc) # create a new arc_object + ob.loc = tuple(center) + transform(self.extrusion, 0, ob) + #ob.size = (1,1,1) + + return ob + + +class BlockRecord: #----------------------------------------------------------------- + """Class for objects representing dxf block_records. + """ + + def __init__(self, obj): + """Expects an entity object of type block_record as input. + """ + if not obj.type == 'block_record': + raise TypeError, "Wrong type %s for block_record object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.name = getit(obj, 2, None) + + # optional data (with defaults) + self.insertion_units = getit(obj, 70, None) + self.insert_units = getit(obj, 1070, None) + """code 1070 Einfügeeinheiten: + 0 = Keine Einheiten; 1 = Zoll; 2 = Fuß; 3 = Meilen; 4 = Millimeter; + 5 = Zentimeter; 6 = Meter; 7 = Kilometer; 8 = Mikrozoll; + 9 = Mils; 10 = Yard; 11 = Angstrom; 12 = Nanometer; + 13 = Mikrons; 14 = Dezimeter; 15 = Dekameter; + 16 = Hektometer; 17 = Gigameter; 18 = Astronomische Einheiten; + 19 = Lichtjahre; 20 = Parsecs + """ + + + def __repr__(self): + return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units) + + + + +class Block: #----------------------------------------------------------------- + """Class for objects representing dxf blocks. + """ + + def __init__(self, obj): + """Expects an entity object of type block as input. + """ + if not obj.type == 'block': + raise TypeError, "Wrong type %s for block object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + self.name = obj.name + + # required data + self.flags = obj.get_type(70)[0] + self.entities = dxfObject('block_contents') #creates empty entities_container for this block + self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) + + # optional data (with defaults) + self.path = getit(obj, 1, '') + self.discription = getit(obj, 4, '') + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + + + def get_loc(self, data): + """Gets the insert point of the block. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 10, None) # 10 = x + loc[1] = getit(data, 20, None) # 20 = y + loc[2] = getit(data, 30, 0.0) # 30 = z + return loc + + + def __repr__(self): + return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path) + + + + +class Insert: #----------------------------------------------------------------- + """Class for objects representing dxf inserts. + """ + + def __init__(self, obj): + """Expects an entity object of type insert as input. + """ + if not obj.type == 'insert': + raise TypeError, "Wrong type %s for insert object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.blockname = obj.get_type(2)[0] + + # optional data (with defaults) + self.rotation = getit(obj, 50, 0) + self.space = getit(obj, 67, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + self.scale = self.get_scale(obj.data) + self.rows, self.columns = self.get_array(obj.data) + self.extrusion = get_extrusion(obj.data) + + + + def get_loc(self, data): + """Gets the center location for block type objects. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 10, 0.0) + loc[1] = getit(data, 20, 0.0) + loc[2] = getit(data, 30, 0.0) + return loc + + + + def get_scale(self, data): + """Gets the x/y/z scale factor for the block. + """ + scale = [1, 1, 1] + scale[0] = getit(data, 41, 1.0) + scale[1] = getit(data, 42, 1.0) + scale[2] = getit(data, 43, 1.0) + return scale + + + + def get_array(self, data): + """Returns the pair (row number, row spacing), (column number, column spacing). + """ + columns = getit(data, 70, 1) + rows = getit(data, 71, 1) + cspace = getit(data, 44, 0.0) + rspace = getit(data, 45, 0.0) + return (rows, rspace), (columns, cspace) + + + + def __repr__(self): + return "%s: layer - %s, blockname - %s" %(self.__class__.__name__, self.layer, self.blockname) + + + def draw(self, settings, deltaloc): + """for INSERT(block): draw empty-marker for duplicated Blender_Group. + + Blocks are made of three objects: + the block_record in the tables section + the block in the blocks section + the insert object in the entities section + + block_records give the insert units, blocks provide the objects drawn in the + block, and the insert object gives the location/scale/rotation of the block + instances. To draw a block you must first get a group with all the + blocks entities drawn in it, then scale the entities to match the world + units, then dupligroup that data to an object matching each insert object. + """ + + obname = 'in_%s' %self.blockname # create object name from block name + obname = obname[:MAX_NAMELENGTH] + + if settings.drawTypes['insert']: #if insert_drawType activated + ob = SCENE.objects.new('Empty', obname) # create a new empty_object + empty_size = 1.0 * settings.var['g_scale'] + if empty_size < 0.01: empty_size = 0.01 + elif empty_size > 10.0: empty_size = 10.0 + ob.drawSize = empty_size + + # get our block_def-group + block = settings.blocks(self.blockname) + ob.DupGroup = block + ob.enableDupGroup = True + + #print 'deb:draw.block.deltaloc:', deltaloc #-------------------- + ob.loc = tuple(self.loc) + if deltaloc: + deltaloc = rotXY_Vec(self.rotation, deltaloc) + #print 'deb:draw.block.loc:', deltaloc #-------------------- + ob.loc = [ob.loc[0]+deltaloc[0], ob.loc[1]+deltaloc[1], ob.loc[2]+deltaloc[2]] + transform(self.extrusion, self.rotation, ob) + ob.size = tuple(self.scale) + return ob + + + + +class Ellipse: #----------------------------------------------------------------- + """Class for objects representing dxf ellipses. + """ + + def __init__(self, obj): + """Expects an entity object of type ellipse as input. + """ + if not obj.type == 'ellipse': + raise TypeError, "Wrong type %s for ellipse object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # required data + self.ratio = obj.get_type(40)[0] + self.start_angle = obj.get_type(41)[0] + self.end_angle = obj.get_type(42)[0] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.thic = getit(obj, 39, 0.0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.loc = self.get_loc(obj.data) + self.major = self.get_major(obj.data) + self.extrusion = get_extrusion(obj.data) + self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2) + + + def get_loc(self, data): + """Gets the center location for arc type objects. + + Arcs have a single coord location. + """ + loc = [0.0, 0.0, 0.0] + loc[0] = getit(data, 10, 0.0) + loc[1] = getit(data, 20, 0.0) + loc[2] = getit(data, 30, 0.0) + return loc + + + def get_major(self, data): + """Gets the major axis for ellipse type objects. + + The ellipse major axis defines the rotation of the ellipse and its radius. + """ + loc = [0.0, 0.0, 0.0] + loc[0] = getit(data, 11, 0.0) + loc[1] = getit(data, 21, 0.0) + loc[2] = getit(data, 31, 0.0) + return loc + + + def __repr__(self): + return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) + + + def draw(self, settings): + """for ELLIPSE: generate Blender_geometry. + """ + # Generate the geometery + thic = set_thick(self.thic, settings) + + if settings.var['curves_on']: + ob = drawCurveArc(self) + else: + obname = 'el_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + + major = Mathutils.Vector(self.major) + #remi--todo----AngleBetweenVecs makes abs(value)!----- + delta = Mathutils.AngleBetweenVecs(major, WORLDX) + center = self.loc + radius = major.length + start = degrees(self.start_angle) + end = degrees(self.end_angle) + verts, edges = drawArc(None, radius, start, end, settings.var['arc_res']) + + if thic != 0: + len1 = len(verts) + thic_verts = [] + thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) + if thic < 0.0: + thic_verts.extend(verts) + verts = thic_verts + else: + verts.extend(thic_verts) + faces = [] + #print 'deb:len1:', len1 #----------------------- + #print 'deb:verts:', verts #remi--todo----- why is this List inhomogene? ---------- + faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] + + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + else: + me.verts.extend(verts) # add vertices to mesh + me.edges.extend(edges) # add edges to the mesh + + ob.loc = tuple(center) + ob.SizeY = self.ratio + transform(self.extrusion, 0, ob) + + return ob + + + +class Face: #----------------------------------------------------------------- + """Class for objects representing dxf 3d faces. + """ + + def __init__(self, obj): + """Expects an entity object of type 3dfaceplot as input. + """ + if not obj.type == '3dface': + raise TypeError, "Wrong type %s for 3dface object!" %obj.type + self.type = obj.type + self.data = obj.data[:] + + # optional data (with defaults) + self.space = getit(obj, 67, 0) + self.color_index = getit(obj, 62, BYLAYER) + + self.layer = getit(obj.data, 8, None) + self.points = self.get_points(obj.data) + + + def get_points(self, data): + """Gets 3-4 points for a 3d face type object. + + Faces have three or optionally four verts. + """ + a = [0, 0, 0] + b = [0, 0, 0] + c = [0, 0, 0] + d = [0, 0, 0] + a[0] = getit(data, 10, None) # 10 = x + a[1] = getit(data, 20, None) # 20 = y + a[2] = getit(data, 30, 0.0) # 30 = z + b[0] = getit(data, 11, None) + b[1] = getit(data, 21, None) + b[2] = getit(data, 31, 0.0) + c[0] = getit(data, 12, None) + c[1] = getit(data, 22, None) + c[2] = getit(data, 32, 0.0) + out = [a,b,c] + + d[0] = getit(data, 13, None) + if d[0] != None: + d[1] = getit(data, 23, None) + d[2] = getit(data, 33, 0.0) + out.append(d) + + #if len(out) < 4: print '3dface with only 3 vertices:\n',a,b,c,d #----------------- + return out + + + def __repr__(self): + return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) + + + def draw(self, settings): + """for 3DFACE: generate Blender_geometry. + """ + # Generate the geometery + points = self.points + + global activObjectLayer + global activObjectName + #print 'deb:draw:face.ob IN activObjectName: ', activObjectName #--------------------- + + if activObjectLayer == self.layer and settings.var['one_mesh_on']: + obname = activObjectName + #print 'deb:face.draw obname from activObjectName: ', obname #--------------------- + ob = Object.Get(obname) # open an existing mesh_object + else: + obname = 'fa_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object + activObjectName = ob.name + activObjectLayer = self.layer + #print ('deb:except. new face.ob+mesh:"%s" created!' %ob.name) #--------------------- + + me = Mesh.Get(ob.name) # open objects mesh data + faces, edges = [], [] + n = len(me.verts) + if len(self.points) == 4: + faces = [[0+n,1+n,2+n,3+n]] + elif len(self.points) == 3: + faces = [[0+n,1+n,2+n]] + elif len(self.points) == 2: + edges = [[0+n,1+n]] + + me.verts.extend(points) # add vertices to mesh + if faces: me.faces.extend(faces) # add faces to the mesh + if edges: me.edges.extend(edges) # add faces to the mesh + if settings.var['vGroup_on']: + # entities with the same color build one vertexGroup for easier material assignment --------------------- + ob.link(me) # link mesh to that object + vG_name = 'color_%s' %self.color_index + if edges: faces = edges + replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD + try: + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: existed vGroup:', vG_name #--------------------- + except: + me.addVertGroup(vG_name) + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: create new vGroup:', vG_name #-------------------- + + #print 'deb:draw:face.ob OUT activObjectName: ', activObjectName #--------------------- + return ob + + +#--------------------------------------------------------------------------------------- +# type to object maping (sorted-dictionary for f_obiectify ONLY!, format={'key':Class} ) type_map = { - 'line':Line, - 'lwpolyline':LWpolyline, - 'text':Text, - 'mtext':Mtext, - 'circle':Circle, - 'arc':Arc, - 'layer':Layer, - 'block_record':BlockRecord, - 'block':Block, - 'insert':Insert, - 'ellipse':Ellipse, - '3dface':Face + 'layer':Layer, + 'block_record':BlockRecord, + 'block':Block, + 'insert':Insert, + 'point':Point, + '3dface':Face, + 'line':Line, +# 'mline':MLine, + 'polyline':Polyline, + 'lwpolyline':LWpolyline, +# 'region':Region, + 'trace':Solid, + 'solid':Solid, + 'text':Text, + 'mtext':Mtext, + 'circle':Circle, + 'ellipse':Ellipse, + 'arc':Arc } -def objectify(data): - """Expects a section type object's data as input. - - Maps object data to the correct object type. - """ - objects = [] # colector for finished objects - known_types = type_map.keys() # so we don't have to call foo.keys() every iteration - index = 0 - while index < len(data): - item = data[index] - if type(item) != list and item.type in known_types: - # proccess the object and append the resulting object - objects.append(type_map[item.type](item)) - elif type(item) != list and item.type == 'table': - item.data = objectify(item.data) # tables have sub-objects - objects.append(item) - elif type(item) != list and item.type == 'polyline': - pline = Polyline(item) - while 1: - index += 1 - item = data[index] - if item.type == 'vertex': - v = Vertex(item) - pline.points.append(v) - elif item.type == 'seqend': - break - else: - print "Error: non-vertex found before seqend!" - index -= 1 - break - objects.append(pline) - else: - # we will just let the data pass un-harrased - objects.append(item) - index += 1 - return objects - -class MatColors: - """A smart container for color based materials. - - This class is a wrapper around a dictionary mapping color indicies to materials. - When called with a color index it returns a material corrisponding to that index. - Behind the scenes it checks if that index is in its keys, and if not it creates - a new material. It then adds the new index:material pair to its dict and returns - the material. - """ - - def __init__(self, map): - """Expects a dictionary mapping layer names to color idices.""" - self.map = map - self.colors = {} - - - def __call__(self, color=None): - """Return the material associated with color. - - If a layer name is provided the color of that layer is used. - """ - if not color: - color = 0 - if type(color) == str: # Layer name - try: - color = self.map[color].color # color = layer_map[name].color - except KeyError: - layer = Layer(name=color, color=0, frozen=False) - self.map[color] = layer - color = 0 - color = abs(color) - if color not in self.colors.keys(): - self.add(color) - return self.colors[color] - - - - - def add(self, color): - """Create a new material using the provided color index.""" - global color_map - mat = Material.New('ColorIndex-%s' %color) - mat.setRGBCol(color_map[color]) - mat.setMode("Shadeless", "Wire") - self.colors[color] = mat - - - - -class Blocks: - """A smart container for blocks. - - This class is a wrapper around a dictionary mapping block names to Blender data blocks. - When called with a name string it returns a block corrisponding to that name. - Behind the scenes it checks if that name is in its keys, and if not it creates - a new data block. It then adds the new name:block pair to its dict and returns - the block. - """ - - def __init__(self, map, settings): - """Expects a dictionary mapping block names to block objects.""" - self.map = map - self.settings = settings - self.blocks = {} - - - def __call__(self, name=None): - """Return the data block associated with name. - - If no name is provided return self.blocks. - """ - if not name: - return self.blocks - if name not in self.blocks.keys(): - self.add(name) - return self.blocks[name] - - - - def add(self, name): - """Create a new block group for the block with name.""" - write = self.settings.write - group = Group.New(name) - block = self.map[name] - write("\nDrawing %s block entities..." %name) - drawEntities(block.entities, self.settings, group) - write("Done!") - self.blocks[name] = group - - - - - -class Settings: - """A container for all the import settings and objects used by the draw functions. - - This is like a collection of globally accessable persistant properties and functions. - """ - # Optimization constants - MIN = 0 - MID = 1 - PRO = 2 - MAX = 3 - - def __init__(self, drawing, curves, optimization, **kwds): - """Given the drawing initialize all the important settings used by the draw functions.""" - self.curves = curves - self.optimization = optimization - print "Setting optimization level %s!" %optimization - self.drawTypes = kwds - self.layers = True - self.blocks = True - - # First sort out all the sections - sections = dict([(item.name, item) for item in drawing.data]) - - # The header section may be omited - if 'header' in sections.keys(): - self.write("Found header!") - else: - self.write("File contains no header!") - - # The tables section may be partialy or completely missing. - if 'tables' in sections.keys(): - self.write("Found tables!") - tables = dict([(item.name, item) for item in sections["tables"].data]) - if 'layer' in tables.keys(): - self.write("Found layers!") - # Read the layers table and get the layer colors - self.colors = getLayers(drawing) - else: - self.write("File contains no layers table!") - self.layers = False - self.colors = MatColors({}) - else: - self.write("File contains no tables!") - self.write("File contains no layers table!") - self.layers = False - self.colors = MatColors({}) - - # The blocks section may be omited - if 'blocks' in sections.keys(): - self.write("Found blocks!") - # Read the block definitions and build our block object - if self.drawTypes['blocks']: - self.blocks = getBlocks(drawing, self) - else: - self.write("File contains no blocks!") - self.drawTypes['blocks'] = False - def write(self, text, newline=True): - """Wraps the built-in print command in a optimization check.""" - if self.optimization <= self.MID: - if newline: - print text - else: - print text, - - def redraw(self): - """Update Blender if optimization level is low enough.""" - if self.optimization <= self.MIN: - Blender.Redraw() - - - def progress(self, done, text): - """Wrapper for Blender.Window.DrawProgressBar.""" - if self.optimization <= self.PRO: - Window.DrawProgressBar(done, text) - - - def isOff(self, name): - """Given a layer name look up the layer object and return its visable status.""" - # colors are negative if layer is off - try: - layer = self.colors.map[name] - except KeyError: - return False - - if layer.frozen or layer.color < 0: - return True - else: - return False - - - - -def main(filename=None): - editmode = Window.EditMode() # are we in edit mode? If so ... - if editmode: Window.EditMode(0) # leave edit mode before - Window.WaitCursor(True) # Let the user know we are thinking - - try: - if not filename: - print "DXF import: error, no file selected. Attempting to load default file." - try: - filename = Sys.expandpath(r".\examples\big-test.dxf") - except IOError: - print "DXF import: error finding default test file, exiting..." - return None - drawing = readDXF(filename, objectify) - drawDrawing(drawing) - finally: - # restore state even if things didn't work - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - -def getOCS(az): - """An implimentation of the Arbitrary Axis Algorithm.""" - # world x, y, and z axis - wx = WORLDX - wy = Mathutils.Vector((0,1,0)) - wz = Mathutils.Vector((0,0,1)) - - #decide if we need to transform our coords - if az[0] == 0 and az[1] == 0: - return False - # elif abs(az[0]) < 0.0001 or abs(az[1]) < 0.0001: - # return False - az = Mathutils.Vector(az) - - cap = 0.015625 # square polar cap value (1/64.0) - if abs(az.x) < cap and abs(az.y) < cap: - ax = Mathutils.CrossVecs(wy, az) - else: - ax = Mathutils.CrossVecs(wz, az) - ax = ax.normalize() - ay = Mathutils.CrossVecs(az, ax) - ay = ay.normalize() - return ax, ay, az - -def transform(normal, obj): - """Use the calculated ocs to determine the objects location/orientation in space. - - Quote from dxf docs: - The elevation value stored with an entity and output in DXF files is a sum - of the Z-coordinate difference between the UCS XY plane and the OCS XY - plane, and the elevation value that the user specified at the time the entity - was drawn. - """ - ocs = getOCS(normal) - if ocs: - #print ocs - x, y, z = ocs - x = x.resize4D() - y = y.resize4D() - z = -z.resize4D() - x.w = 0 - y.w = 0 - z.w = 0 - o = Mathutils.Vector(obj.loc) - o = o.resize4D() - mat = Mathutils.Matrix(x, y, z, o) - obj.setMatrix(mat) - -def getLayers(drawing): - """Build a dictionary of name:color pairs for the given drawing.""" - tables = drawing.tables - for table in tables.data: - if table.name == 'layer': - layers = table - break - map = {} - for item in layers.data: - if type(item) != list and item.type == 'layer': - map[item.name] = item - colors = MatColors(map) - return colors -def getBlocks(drawing, settings): - """Build a dictionary of name:block pairs for the given drawing.""" - map = {} - for item in drawing.blocks.data: - if type(item) != list and item.type == 'block': - try: - map[item.name] = item - except KeyError: - # annon block - print "Cannot map %s - %s!" %(item.name, item) - blocks = Blocks(map, settings) - return blocks -def drawDrawing(drawing): - """Given a drawing object recreate the drawing in Blender.""" - print "Getting settings..." - Window.WaitCursor(False) - #width, height = Window.GetScreenSize() - Window.SetMouseCoords() - - # Create a PupBlock to get user preferences - lines = Draw.Create(1) - arcs = Draw.Create(1) - circles = Draw.Create(1) - polylines = Draw.Create(1) - text = Draw.Create(1) - blocks = Draw.Create(1) - faces = Draw.Create(1) - optim = Draw.Create(1) - - block = [] - block.append("Draw Options:") - block.append(("Lines", lines, "Toggle drawing of lines")) - block.append(("Arcs", arcs, "Toggle drawing of arcs")) - block.append(("Circles", circles, "Toggle drawing of circles")) - block.append(("Polylines", polylines, "Toggle drawing of polylines")) - block.append(("Text", text, "Toggle drawing of text")) - block.append(("Blocks", blocks, "Toggle drawing of blocks")) - block.append(("Faces", faces, "Toggle drawing of faces")) - block.append("Update Optimization:") - block.append(("Level: ", optim, 0, 3)) - - retval = Draw.PupBlock("DXF Import", block) - - Window.WaitCursor(True) # Let the user know we are thinking - # The settings object controls how dxf entities are drawn - settings = Settings(drawing, curves=False, - optimization=int(optim.val), - lines=bool(lines.val), - arcs=bool(arcs.val), - circles=bool(circles.val), - polylines=bool(polylines.val), - text=bool(text.val), - blocks=bool(blocks.val), - faces=bool(faces.val) - ) - - settings.write("Drawings entities...") - # Draw all the know entity types in the current scene - drawEntities(drawing.entities, settings) - - # Set the visable layers - SCENE.setLayers([i+1 for i in range(18)]) - Blender.Redraw(-1) - settings.write("Done!") - - -def drawEntities(entities, settings, group=None): - """Draw every kind of thing in the entity list. - - If provided 'group' is the Blender group new entities are to be added to. - """ - for _type in type_map.keys(): - # for each known type get a list of that type and call the associated draw function - drawer(_type, entities.get_type(_type), settings, group) - - -def drawer(_type, entities, settings, group): - """Call with a list of entities and a settings object to generate Blender geometry.""" - if entities: - # Break out early if settings says we aren't drawing the current type - block = False - skip = False - if _type == 'block_record': - skip = True - if _type == 'line' and not settings.drawTypes['lines']: - skip = True - elif _type == 'arc' and not settings.drawTypes['arcs']: - skip = True - elif _type == 'circle' and not settings.drawTypes['circles']: - skip = True - elif _type in ['lwpolyline', 'polyline'] and not settings.drawTypes['polylines']: - skip = True - elif _type in ['text', 'mtext'] and not settings.drawTypes['text']: - skip = True - elif _type == 'insert': - if not settings.drawTypes['blocks']: - skip = True - block = True - elif _type == '3dface' and not settings.drawTypes['faces']: - skip = True - if skip: - settings.write("Skipping %s type entities!" %_type) - return - - message = "Drawing %ss..." %_type - settings.write(message, False) - settings.progress(0, message) - - if block: - # create one 'handle' data block to use with all blocks - handle = Mesh.New('insert') - handle.verts.extend( - [(-0.01,0,0), - (0.01,0,0), - (0,-0.01,0), - (0,0.01,0), - (0,0,-0.01), - (0,0,0.01)] - ) - handle.edges.extend([(0,1),(2,3),(4,5)]) - - # For now we only want model-space objects - entities = [entity for entity in entities if entity.space == 0] - - if group: - block_def = True - else: - block_def = False - - tot = len(entities) - cur = 1.0 - for entity in entities: - settings.write('\b.', False) - settings.progress(cur/tot, message) - cur += 1 - - # First get the layer group - if not block_def: - group = getGroup('layer %s' %entity.layer) # add overhead just to make things a little cleaner - - if block: - ob = entity.draw(handle, settings) - else: - ob = entity.draw(settings.curves) - - setColor(entity, ob, settings) - # Link it to the scene and add it to the correct group - SCENE.link(ob) - setGroup(group, ob) - - # Set the visability - if settings.isOff(entity.layer): - ob.layers = [20] - elif block_def: - ob.layers = [19] - else: - ob.layers = [i+1 for i in range(20)] - - # # Set the visability - # if settings.isOff(entity.layer) or block_def: - # ob.restrictDisplay = True - # ob.restrictRender = True - - settings.redraw() - message = "\nFinished drawing %ss!" %entities[0].type - settings.write(message) - settings.progress(1, message) - - -def getGroup(name): - """Returns a Blender group object.""" - try: - group = Group.Get(name) - except: # What is the exception? - group = Group.New(name) - return group -def setColor(entity, ob, settings): - # Set the color - if entity.color_index == BYLAYER: - mat = settings.colors(entity.layer) - else: - mat = settings.colors(entity.color_index) - try: - ob.setMaterials([mat]) - except ValueError: - settings.write("material error - %s!" %mat) - ob.colbits = 0x01 # Set OB materials. -def setGroup(group, it): - try: - group.objects.link(it) - except: - group.objects.append(it) - -def solveBulge(p1, p2): - """return the center, radius, start angle, and end angle given two points. - - Needs to take into account bulge sign. - negative = clockwise - positive = counter-clockwise - - to find center given two points, and arc angle - calculate radius - Cord = sqrt(start^2 + end^2) - S = (bulge*Cord)/2 - radius = ((Cord/2)^2+S^2)/2*S - angle of arc = 4*atan( bulge ) - angle from p1 to center is (180-angle)/2 - get vector pointing from p1 to p2 (p2 - p1) - normalize it and multiply by radius - rotate around p1 by angle to center point to center. - - start angle = angle between (center - p1) and worldX - end angle = start angle + angle of arc - """ - bulge = p1.bulge - p2 = Mathutils.Vector(p2.loc) - p1 = Mathutils.Vector(p1.loc) - cord = p2 - p1 # vector from p1 to p2 - clength = cord.length - s = (bulge * clength)/2 # sagitta (height) - radius = abs(((clength/2)**2 + s**2)/(2*s)) # magic formula - angle = abs(degrees(4*atan(bulge))) # theta (included angle) - delta = (180 - angle)/2 # the angle from cord to center - if bulge > 0: - delta = -delta - radial = cord.normalize() * radius # a radius length vector aligned with cord - rmat = Mathutils.RotationMatrix(delta, 3, 'Z') - center = p1 + (rmat * radial) # rotate radial by delta degrees, then add to p1 to find center - if bulge < 0: - sv = (p1 - center) # start from point 2 - else: - sv = (p2 - center) # start from point 1 - start = Mathutils.AngleBetweenVecs(sv, WORLDX) # start angle is the angle between the first leg of the section and the x axis - # The next bit is my cludge to figure out if start should be negative - rmat = Mathutils.RotationMatrix(start, 3, 'Z') - rstart = rmat * sv - if Mathutils.AngleBetweenVecs(rstart, WORLDX) < start: - start = -start - # the end angle is just 'angle' more than start angle - end = start + angle - return list(center), radius, start, end -def drawArc(center, radius, start, end, step=0.5): - """Draw a mesh arc with the given parameters.""" - # center is currently set by object - - # if start > end: - # start = start - 360 - if end > 360: - end = end%360 - startmatrix = Mathutils.RotationMatrix(start, 3, "Z") - startpoint = startmatrix * Mathutils.Vector((radius, 0, 0)) - endmatrix = Mathutils.RotationMatrix(end, 3, "Z") - endpoint = endmatrix * Mathutils.Vector((radius, 0, 0)) - points = [startpoint] - - if end < start: - end +=360 - - delta = end - start - length = radians(delta) * radius - if radius < step*10: # if circumfrance is too small - pieces = int(delta/10) # set a fixed step of 10 degrees - else: - pieces = int(length/step) # figure out how many pieces we need for our arc - if pieces == 0: # stupid way to avoid a div by zero error - pieces = 1 # what would be a smarter way to fix this? - step = delta/pieces # set step so pieces * step = degrees in arc - - stepmatrix = Mathutils.RotationMatrix(step, 3, "Z") - point = Mathutils.Vector(startpoint) - for i in range(int(pieces)): - point = stepmatrix * point - points.append(point) - points.append(endpoint) - - if center: - points = [[point[0]+center[0], point[1]+center[1], point[2]+center[2]] for point in points] - edges = [[num, num+1] for num in range(len(points)-1)] - - return points, edges -# Here are some alternate drawing functions for creating curve geometery. - -def drawCurveCircle(circle): - """Given a dxf circle object return a blender circle object using curves.""" - c = Curve.New('circle') # create new curve data - - center = circle.loc - radius = circle.radius - - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) - - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) - - curve = c.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - curve.flagU = 1 # Set curve cyclic - c.update() - - ob = Object.New('Curve', 'circle') # make curve object - return ob - -def drawCurveArc(arc): - """Given a dxf circle object return a blender circle object using curves.""" - if start > end: - start = start - 360 - startmatrix = Mathutils.RotationMatrix(start, 3, "Z") - startpoint = startmatrix * Mathutils.Vector((radius, 0, 0)) - endmatrix = Mathutils.RotationMatrix(end, 3, "Z") - endpoint = endmatrix * Mathutils.Vector((radius, 0, 0)) - # Note: handles must be tangent to arc and of correct length... - - a = Curve.New('arc') # create new curve data - - center = circle.loc - radius = circle.radius - - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) - - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) - - curve = a.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - curve.flagU = 1 # Set curve cyclic - a.update() - - ob = Object.New('Curve', 'arc') # make curve object - return ob + + +def objectify(data): #----------------------------------------------------------------- + """Expects a section type object's data as input. + + Maps object data to the correct object type. + """ + #print 'deb:objectify start %%%%%%%%%%%' #--------------- + objects = [] # colector for finished objects + known_types = type_map.keys() # so we don't have to call foo.keys() every iteration + curves_on = GUI_A['curves_on'].val + index = 0 + while index < len(data): + item = data[index] + #print 'deb:objectify item: \n', item #------------ + if type(item) != list and item.type == 'table': + item.data = objectify(item.data) # tables have sub-objects + objects.append(item) + elif type(item) != list and item.type == 'polyline': #remi todo----------- + #print 'deb:gosub Polyline\n' #------------- + pline = Polyline(item) + while 1: + index += 1 + item = data[index] + if item.type == 'vertex': + #print 'deb:objectify gosub Vertex--------' #------------- + v = Vertex(item) + if pline.spline: # Bspline-curve + # then for Blender-mesh filter only additional_vertices + # OR + # then for Blender-curve filter only spline_control_vertices + if (v.spline and not curves_on) or (curves_on and v.splin2): #correct for real NURBS-import + #if (v.spline and not curves_on) or (curves_on and not v.splin2): #fake for Bezier-emulation of NURBS-import + pline.points.append(v) + elif pline.curved: # Bezier-curve + # then for Blender-mesh filter only curve_additional_vertices + # OR + # then for Blender-curve filter curve_control_vertices + if not curves_on or (curves_on and not v.curved): + pline.points.append(v) + else: + pline.points.append(v) + elif item.type == 'seqend': + #print 'deb:objectify it is seqEND ---------\n' #------------- + break + else: + print "Error: non-vertex found before seqend!" + index -= 1 #so go back one step + break + objects.append(pline) + elif type(item) != list and item.type in known_types: + # proccess the object and append the resulting object + objects.append(type_map[item.type](item)) + else: + # we will just let the data pass un-harrased + objects.append(item) + index += 1 + #print 'deb:objectify objects:\n', objects #------------ + #print 'deb:objectify END %%%%%%%%' #------------ + return objects + + + +class MatColors: #----------------------------------------------------------------- + """A smart container for dxf-color based materials. + + This class is a wrapper around a dictionary mapping dxf-color indicies to materials. + When called with a color index it returns a material corrisponding to that index. + Behind the scenes it checks if that index is in its keys, and if not it creates + a new material. It then adds the new index:material pair to its dict and returns + the material. + """ + + def __init__(self, map): + """Expects a map - a dictionary mapping layer names to layers. + """ + self.map = map # a dictionary of layername:layer + self.colMaterials = {} # a dictionary of color_index:blender_material + #print 'deb:init_MatColors argument.map: ', map #------------------ + + + def __call__(self, color=None): + """Return the material associated with color. + + If a layer name is provided, the color of that layer is used. + """ + if not color: + color = 0 + if type(color) == str: + #print 'deb:color is string:--------------: ', color #--todo---bug with ARC from ARC-T0.DXF layer="T-3DARC-1"----- + try: + color = self.map[color].color + #print 'deb:color=self.map[color].color:', color #------------------ + except KeyError: + layer = Layer(name=color, color=0, frozen=False) + self.map[color] = layer + color = 0 + color = abs(color) + if color not in self.colMaterials.keys(): + self.add(color) + return self.colMaterials[color] + + + def add(self, color): + """Create a new material 'ColorNr-N' using the provided color index-N. + """ + global color_map + mat = Material.New('ColorNr-%s' %color) + mat.setRGBCol(color_map[color]) + try: + mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug + except: pass + self.colMaterials[color] = mat + + + +class MatLayers: #----------------------------------------------------------------- + """A smart container for dxf-layer based materials. + + This class is a wrapper around a dictionary mapping dxf-layer names to materials. + When called with a layer name it returns a material corrisponding to that. + Behind the scenes it checks if that layername is in its keys, and if not it creates + a new material. It then adds the new layername:material pair to its dict and returns + the material. + """ + + def __init__(self, map): + """Expects a map - a dictionary mapping layer names to layers. + """ + self.map = map # a dictionary of layername:layer + self.layMaterials = {} # a dictionary of layer_name:blender_material + #print 'deb:init_MatLayers argument.map: ', map #------------------ + + + def __call__(self, layername=None): + """Return the material associated with dxf-layer. + + If a dxf-layername is not provided, create a new material + """ + if layername not in self.layMaterials.keys(): + self.add(layername) + return self.layMaterials[layername] + + + def add(self, layername): + """Create a new material 'layername'. + """ + try: mat = Material.Get('Lay-%s' %layername) + except: mat = Material.New('Lay-%s' %layername) + #print 'deb:MatLayers material: ', mat #---------- + #print 'deb:MatLayers getMode: ', mat.getMode() #---------- + global layersmap + color = layersmap[layername].color + #print 'deb:MatLayers layer_color: ', color #----------- + global color_map + mat.setRGBCol(color_map[color]) + try: + mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug + except: pass + self.layMaterials[layername] = mat + + + + +class Blocks: #----------------------------------------------------------------- + """A smart container for blocks. + + This class is a wrapper around a dictionary mapping block names to Blender data blocks. + When called with a name string it returns a block corresponding to that name. + Behind the scenes it checks if that name is in its keys, and if not it creates + a new data block. It then adds the new name:block_data pair to its dict and returns + the block. + """ + + def __init__(self, blocksmap, settings): + """Expects a dictionary mapping block_name:block_data. + """ + self.blocksmap = blocksmap #a dictionary mapping block_name:block_data + self.settings = settings + self.blocks = {} #container for blocks + + + def __call__(self, name=None): + """Return the data block associated with that block_name. + + If that name is not in its keys, it creates a new data block. + If no name is provided return entire self.blocks container. + """ + if not name: + return self.blocks + if name not in self.blocks.keys(): + self.addBlock(name) + return self.blocks[name] + + + def addBlock(self, name): + """Create a new 'block group' for the block name. + """ + block_def = Group.New('bl_%s' %name) # groupObject contains definition of BLOCK + block = self.blocksmap[name] + self.settings.write("\nDrawing block:\'%s\' ..." % name) + drawEntities(block.entities, self.settings, block_def) + self.settings.write("Drawing block:\'%s\' done!" %name) + self.blocks[name] = block_def + + + + + +class Settings: #----------------------------------------------------------------- + """A container for all the import settings and objects used by the draw functions. + + This is like a collection of globally accessable persistant properties and functions. + """ + # Optimization constants + MIN = 0 + MID = 1 + PRO = 2 + MAX = 3 + + def __init__(self, keywords, drawTypes): + """initialize all the important settings used by the draw functions. + """ + self.obj_number = 1 #global object_number for progress_bar + + self.var = dict(keywords) #a dictionary of (key_variable:Value) control parameter + self.drawTypes = dict(drawTypes) #a dictionary of (entity_type:True/False) = import on/off for this entity_type + + self.var['colorFilter_on'] = False #deb:remi------------ + self.acceptedColors = [0,2,3,4,5,6,7,8,9, + 10 ] + + self.var['layerFilter_on'] = False #deb:remi------------ + self.acceptedLayers = ['3', + '0' + ] + + self.var['blockFilter_on'] = False #deb:remi------------ + self.acceptedBlocks = ['BOX01', + 'BOX02' + ] + + + def update(self, keywords, drawTypes): + """update all the important settings used by the draw functions. + """ + + for k, v in keywords.iteritems(): + self.var[k] = v + #print 'deb:settings_update var %s= %s' %(k, self.var[k]) #-------------- + for t, v in drawTypes.iteritems(): + self.drawTypes[t] = v + #print 'deb:settings_update drawType %s= %s' %(t, self.drawTypes[t]) #-------------- + + #print 'deb:self.drawTypes', self.drawTypes #--------------- + + + def validate(self, drawing): + """Given the drawing, build dictionaries of Layers, Colors and Blocks. + """ + + #de: paßt die distance parameter an globalScale + if self.var['g_scale'] != 1: + self.var['dist_min'] = self.var['dist_min'] / self.var['g_scale'] + self.var['thick_min'] = self.var['thick_min'] / self.var['g_scale'] + self.var['width_min'] = self.var['width_min'] / self.var['g_scale'] + + # First sort out all the section_items + sections = dict([(item.name, item) for item in drawing.data]) + + # The section:header may be omited + if 'header' in sections.keys(): + self.write("Found section:header!") + else: + self.write("File contains no section:header!") + + # The section:tables may be partialy or completely missing. + self.layersTable = False + self.colMaterials = MatColors({}) + self.layMaterials = MatLayers({}) + if 'tables' in sections.keys(): + self.write("Found section:tables!") + # First sort out all the tables + tables = dict([(item.name, item) for item in sections["tables"].data]) + if 'layer' in tables.keys(): + self.write("Found table:layers!") + self.layersTable = True + # Read the layers table and get the layer colors + global layersmap + layersmap = getLayersmap(drawing) + self.colMaterials = MatColors(layersmap) + self.layMaterials = MatLayers(layersmap) + else: + self.write("File contains no table:layers!") + else: + self.write("File contains no section:tables!") + self.write("File contains no table:layers!") + + # The section:blocks may be omited + if 'blocks' in sections.keys(): + self.write("Found section:blocks!") + # Read the block definitions and build our block object + if self.drawTypes['insert']: #if drawing of type 'Insert' activated + blocksmap, self.obj_number = getBlocksmap(drawing) #Build a dictionary of blockname:block_data pairs + self.blocks = Blocks(blocksmap, self) # initiates container for blocks_data + + #print 'deb: self.obj_number', self.obj_number #---------- + else: + self.write("File contains no section:blocks!") + self.drawTypes['insert'] = False + + # The section:entities + if 'entities' in sections.keys(): + self.write("Found section:entities!") + + self.obj_number += len(drawing.entities.data) + #print 'deb: self.obj_number', self.obj_number #---------- + self.obj_number = 1.0 / self.obj_number + + + def write(self, text, newline=True): + """Wraps the built-in print command in a optimization check. + """ + if self.var['optimization'] <= self.MID: + if newline: + print text + else: + print text, + + + def redraw(self): + """Update Blender if optimization level is low enough. + """ + if self.var['optimization'] <= self.MIN: + Blender.Redraw() + + + def progress(self, done, text): + """Wrapper for Blender.Window.DrawProgressBar. + """ + if self.var['optimization'] <= self.PRO: + progressbar = done * self.obj_number + Window.DrawProgressBar(progressbar, text) + #print 'deb:drawer done, progressbar: ', done, progressbar #----------------------- + + + def layer_isOff(self, name): + """Given a layer name, and return its visible status. + """ + # colors are negative if layer is off + try: + #print 'deb:layer_isOff self.colMaterials.map:\n', self.colMaterials.map #-------------- + layer = self.colMaterials.map[name] + except KeyError: return False + if layer.color < 0: return True + #print 'deb:layer_isOff: layer is ON' #--------------- + return False + + + def layer_isFrozen(self, name): + """Given a layer name, and return its frozen status. + """ + # colors are negative if layer is off + try: + #print 'deb:layer_isFrozen self.colMaterials.map:\n', self.colMaterials.map #--------------- + layer = self.colMaterials.map[name] + except KeyError: return False + if layer.frozen: return True + #print 'deb:layer_isFrozen: layer is not FROZEN' #--------------- + return False + + + + +def main(): #---------------#############################----------- + #print 'deb:filename:', filename #-------------- + global SCENE + editmode = Window.EditMode() # are we in edit mode? If so ... + if editmode: + Window.EditMode(0) # leave edit mode before + + #SCENE = Scene.GetCurrent() + SCENE = bpy.data.scenes.active + SCENE.objects.selected = [] # deselect all + + global cur_COUNTER #counter for progress_bar + cur_COUNTER = 0 + + try: + print "Getting settings..." + global GUI_A, GUI_B + if GUI_A['g_scale_on'].val: + GUI_A['g_scale'].val = 10.0 ** int(GUI_A['g_scale_as'].val) + else: + GUI_A['g_scale'].val = 1.0 + + keywords = {} + drawTypes = {} + for k, v in GUI_A.iteritems(): + keywords[k] = v.val + for k, v in GUI_B.iteritems(): + drawTypes[k] = v.val + #print 'deb:startUInew keywords: ', keywords #-------------- + #print 'deb:startUInew drawTypes: ', drawTypes #-------------- + + # The settings object controls how dxf entities are drawn + settings.update(keywords, drawTypes) + #print 'deb:settings.var:\n', settings.var #----------------------- + + if not settings: + #Draw.PupMenu('DXF importer: EXIT!%t') + print '\nDXF Import: terminated by user!' + return None + + dxfFile = dxfFileName.val + #print 'deb: dxfFile file: ', dxfFile #---------------------- + if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): + Window.WaitCursor(True) # Let the user know we are thinking + print 'start reading DXF file: %s.' % dxfFile + time1 = Blender.sys.time() #time marker1 + drawing = readDXF(dxfFile, objectify) + print 'finished reading DXF file in %.4f sec.' % (Blender.sys.time()-time1) + Window.WaitCursor(False) + else: + if UI_MODE: Draw.PupMenu('DXF importer: EXIT----------!%t| no valid DXF-file selected!') + print "DXF importer: error, no DXF-file selected. Abort!" + return None + + settings.validate(drawing) + + Window.WaitCursor(True) # Let the user know we are thinking + settings.write("\n\nDrawing entities...") + + # Draw all the know entity types in the current scene + global oblist + oblist = [] # a list of all created AND linked objects for final f_globalScale + time2 = Blender.sys.time() #time marker2 + + drawEntities(drawing.entities, settings) + + #print 'deb:drawEntities after: oblist:', oblist #----------------------- + if oblist and settings.var['g_scale'] != 1: + globalScale(oblist, settings.var['g_scale']) + + # Set the visable layers + SCENE.setLayers([i+1 for i in range(18)]) + Blender.Redraw(-1) + Window.WaitCursor(False) + settings.write("Import DXF to Blender: *** DONE ***") + settings.progress(1.0/settings.obj_number, 'DXF import done!') + print 'DXF importer: done in %.4f sec.' % (Blender.sys.time()-time2) + if UI_MODE: Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % (Blender.sys.time()-time2)) + + finally: + # restore state even if things didn't work + Window.WaitCursor(False) + if editmode: Window.EditMode(1) # and put things back how we fond them + + + +def getOCS(az): #----------------------------------------------------------------- + """An implimentation of the Arbitrary Axis Algorithm. + """ + #decide if we need to transform our coords + if az[0] == 0 and az[1] == 0: + return False + #elif abs(az[0]) < 0.0001 and abs(az[1]) < 0.0001: + # return False + + az = Mathutils.Vector(az) + + cap = 0.015625 # square polar cap value (1/64.0) + if abs(az.x) < cap and abs(az.y) < cap: + ax = Mathutils.CrossVecs(WORLDY, az) + else: + ax = Mathutils.CrossVecs(WORLDZ, az) + ax = ax.normalize() + ay = Mathutils.CrossVecs(az, ax) + ay = ay.normalize() + return ax, ay, az + + + +def transform(normal, rotation, obj): #-------------------------------------------- + """Use the calculated ocs to determine the objects location/orientation in space. + + Quote from dxf docs: + The elevation value stored with an entity and output in DXF files is a sum + of the Z-coordinate difference between the UCS XY plane and the OCS XY + plane, and the elevation value that the user specified at the time the entity + was drawn. + """ + ma = Mathutils.Matrix([1,0,0],[0,1,0],[0,0,1]) + o = Mathutils.Vector(obj.loc) + ocs = getOCS(normal) + if ocs: + ma = Mathutils.Matrix(ocs[0], ocs[1], ocs[2]) + o = ma.invert() * o + ma = Mathutils.Matrix(ocs[0], ocs[1], ocs[2]) + + if rotation != 0: + g = radians(-rotation) + rmat = Mathutils.Matrix([cos(g), -sin(g), 0], [sin(g), cos(g), 0], [0, 0, 1]) + ma = rmat * ma + + obj.setMatrix(ma) + obj.loc = o + #print 'deb:new obj.matrix:\n', obj.getMatrix() #-------------------- + + + +def rotXY_Vec(rotation, vec): #---------------------------------------------------- + """Rotate vector vec in XY-plane. vec must be in radians + """ + if rotation != 0: + o = Mathutils.Vector(vec) + g = radians(-rotation) + vec = o * Mathutils.Matrix([cos(g), -sin(g), 0], [sin(g), cos(g), 0], [0, 0, 1]) + return vec + + + +def getLayersmap(drawing): #------------------------------------------------------ + """Build a dictionary of layername:layer pairs for the given drawing. + """ + tables = drawing.tables + for table in tables.data: + if table.name == 'layer': + layers = table + break + layersmap = {} + for item in layers.data: + if type(item) != list and item.type == 'layer': + layersmap[item.name] = item + return layersmap + + + +def getBlocksmap(drawing): #-------------------------------------------------------- + """Build a dictionary of blockname:block_data pairs for the given drawing. + """ + blocksmap = {} + obj_number = 0 + for item in drawing.blocks.data: + #print 'deb:getBlocksmap item=' ,item #-------- + #print 'deb:getBlocksmap item.entities=' ,item.entities #-------- + #print 'deb:getBlocksmap item.entities.data=' ,item.entities.data #-------- + if type(item) != list and item.type == 'block': + obj_number += len(item.entities.data) + try: + blocksmap[item.name] = item + except KeyError: + # annon block + print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) + return blocksmap, obj_number + + + + + +def drawEntities(entities, settings, block_def=None): #---------------------------------------- + """Draw every kind of thing in the entity list. + + If provided 'block_def': the entities are to be added to the Blender 'group'. + """ + for _type in type_map.keys(): + #print 'deb:drawEntities_type:', _type #------------------ + # for each known type get a list of that type and call the associated draw function + drawer(_type, entities.get_type(_type), settings, block_def) + + +def drawer(_type, entities, settings, block_def): #------------------------------------------ + """Call with a list of entities and a settings object to generate Blender geometry. + + If 'block_def': the entities are to be added to the Blender 'group'. + """ + if entities: + # Break out early if settings says we aren't drawing the current dxf-type + global cur_COUNTER #counter for progress_bar + group = None + #print 'deb:drawer.check:_type: ', _type #-------------------- + if _type == '3dface':_type = 'face' # hack, while python_variable_name can not beginn with a nummber + if not settings.drawTypes[_type] or _type == 'block_record': + message = 'Skipping dxf\'%ss\' entities' %_type + settings.write(message, True) + cur_COUNTER += len(entities) + settings.progress(cur_COUNTER, message) + return + #print 'deb:drawer.todo:_type:', _type #----------------------- + + len_temp = len(entities) + # filtering only model-space enitities (no paper-space enitities) + entities = [entity for entity in entities if entity.space == 0] + + # filtering only objects with color from acceptedColorsList + if settings.var['colorFilter_on']: + entities = [entity for entity in entities if entity.color in settings.acceptedColors] + + # filtering only objects on layers from acceptedLayersList + if settings.var['layerFilter_on']: +# entities = [entity for entity in entities if entity.layer[0] in ['M','3','0'] and not entity.layer.endswith('H')] + entities = [entity for entity in entities if entity.layer in settings.acceptedLayers] + + # filtering only objects on not-frozen layers + entities = [entity for entity in entities if not settings.layer_isFrozen(entity.layer)] + + global activObjectLayer, activObjectName + activObjectLayer = '' + activObjectName = '' + + message = "Drawing dxf\'%ss\'..." %_type + cur_COUNTER += len_temp - len(entities) + settings.write(message, False) + settings.progress(cur_COUNTER, message) + if len(entities) > 0.1 / settings.obj_number: + show_progress = int(0.03 / settings.obj_number) + else: show_progress = 0 + cur_temp = 0 + + #print 'deb:drawer cur_COUNTER: ', cur_COUNTER #----------------------- + + for entity in entities: #----loop------------------------------------- + settings.write('\b.', False) + cur_COUNTER += 1 + if show_progress: + cur_temp += 1 + if cur_temp == show_progress: + settings.progress(cur_COUNTER, message) + cur_temp = 0 + #print 'deb:drawer show_progress=',show_progress #----------------------- + + # get the layer group (just to make things a little cleaner) + if settings.var['group_bylayer_on'] and not block_def: + group = getGroup('l:%s' % entity.layer[:MAX_NAMELENGTH-2]) + + if _type == 'insert': #---- INSERT and MINSERT=array ------------------------ + #print 'deb:insert entity.loc:', entity.loc #---------------- + columns = entity.columns[0] + coldist = entity.columns[1] + rows = entity.rows[0] + rowdist = entity.rows[1] + deltaloc = [0,0,0] + #print 'deb:insert columns, rows:', columns, rows #----------- + for col in xrange(columns): + deltaloc[0] = col * coldist + for row in xrange(rows): + deltaloc[1] = row * rowdist + #print 'deb:insert col=%s, row=%s,deltaloc=%s' %(col, row, deltaloc) #------ + ob = entity.draw(settings, deltaloc) #-----draw BLOCK---------- + setObjectProperties(ob, group, entity, settings, block_def) + if ob: + if settings.var['optimization'] <= settings.MIN: + if settings.var['g_scale'] != 1: globalScaleOne(ob, True, settings.var['g_scale']) + settings.redraw() + else: oblist.append((ob, True)) + + else: #---draw entities except BLOCKs/INSERTs--------------------- + alt_obname = activObjectName + ob = entity.draw(settings) + if ob and ob.name != alt_obname: + setObjectProperties(ob, group, entity, settings, block_def) + if settings.var['optimization'] <= settings.MIN: + if settings.var['g_scale'] != 1: globalScaleOne(ob, False, settings.var['g_scale']) + settings.redraw() + else: oblist.append((ob, False)) + + #print 'deb:Finished drawing:', entities[0].type #------------------------ + message = "\nDrawing dxf\'%ss\' done!" % _type + settings.write(message, True) + + + +def globalScale(oblist, SCALE): #--------------------------------------------------------- + """Global_scale for list of all imported objects. + + oblist is a list of pairs (ob, insertFlag), where insertFlag=True/False + """ + #print 'deb:globalScale.oblist: ---------%\n', oblist #--------------------- + for l in oblist: + ob, insertFlag = l[0], l[1] + globalScaleOne(ob, insertFlag, SCALE) + + +def globalScaleOne(ob, insertFlag, SCALE): #--------------------------------------------------------- + """Global_scale imported object. + """ + #print 'deb:globalScaleOne ob: ', ob #--------------------- + SCALE_MAT= Mathutils.Matrix([SCALE,0,0,0],[0,SCALE,0,0],[0,0,SCALE,0],[0,0,0,1]) + if insertFlag: # by BLOCKs/INSERTs only insert-point must be scaled------------ + ob.loc = Mathutils.Vector(ob.loc) * SCALE_MAT + else: # entire scaling for all other imported objects ------------ + ob.setMatrix(ob.matrixWorld*SCALE_MAT) + + + +def setObjectProperties(ob, group, entity, settings, block_def): #----------------------- + """Link object to scene. + """ + + if not ob: #remi--todo----------------------- + message = "\nObject \'%s\' not found!" %entity + settings.write(message) + return + + if group: + setGroup(group, ob) # if object belongs to group + + if block_def: # if object belongs to BLOCK_def - Move it to layer nr19 + setGroup(block_def, ob) + #print 'deb:setObjectProperties \'%s\' set to block_def_group!' %ob.name #--------- + ob.layers = [19] + else: + #ob.layers = [i+1 for i in xrange(20)] #remi--todo------------ + ob.layers = [settings.var['target_layer']] + + # Set material for any objects except empties + if ob.type != 'Empty': + setMaterial_from(entity, ob, settings, block_def) + + # Set the visibility + if settings.layer_isOff(entity.layer): + #ob.layers = [20] #remi--todo------------- + ob.restrictDisplay = True + ob.restrictRender = True + + #print 'deb:\n---------linking Object %s!' %ob.name #---------- + + + +def getGroup(name): #----------------------------------------------------------------- + """Returns a Blender group-object. + """ + try: + group = Group.Get(name) + except: # What is the exception? + group = Group.New(name) + return group + + +def setGroup(group, ob): #------------------------------------------------------------ + """Assigns object to Blender group. + """ + try: + group.objects.link(ob) + except: + group.objects.append(ob) #remi?--------------- + + + +def setMaterial_from(entity, ob, settings, block_def): #------------------------------------------------ + """ Set Blender-material for the object controled by item. + + Set Blender-material for the object + - controlled by settings.var['material_from'] + """ + if settings.var['material_from'] == 1: # 1= material from color + if entity.color_index == BYLAYER: + mat = settings.colMaterials(entity.layer) + else: + mat = settings.colMaterials(entity.color_index) + elif settings.var['material_from'] == 2: # 2= material from layer + mat = settings.layMaterials(entity.layer) +# elif settings.var['material_from'] == 3: # 3= material from layer+color +# mat = settings.layMaterials(entity.layer) +# color = entity.color_index +# if type(color) == int: +# mat.setRGBCol(color_map[abs(color)]) +# elif settings.var['material_from'] == 4: # 4= material from block +# elif settings.var['material_from'] == 5: # 5= material from INI-file + else: # set neutral material + try: + mat = Material.Get('dxf-neutral') + except: + mat = Material.New('dxf-neutral') + try: + mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug + except: pass + try: + #print 'deb:material mat:', mat #----------- + ob.setMaterials([mat]) #assigns Blender-material to object + except ValueError: + settings.write("material error - \'%s\'!" %mat) + ob.colbits = 0x01 # Set OB materials. + + + +def drawBulge(p1, p2, ARC_RESOLUTION=120): #------------------------------------------------- + """return the center, radius, start angle, and end angle given two points. + + Needs to take into account bulge sign. + negative = clockwise + positive = counter-clockwise + + to find center given two points, and arc angle + calculate radius + Cord = sqrt(start^2 + end^2) + S = (bulge*Cord)/2 + radius = ((Cord/2)^2+S^2)/2*S + angle of arc = 4*atan( bulge ) + angle from p1 to center is (180-angle)/2 + get vector pointing from p1 to p2 (p2 - p1) + normalize it and multiply by radius + rotate around p1 by angle to center, point to center. + start angle = angle between (center - p1) and worldX + end angle = angle between (center - p2) and worldX + """ + + bulge = p1.bulge + p2 = Mathutils.Vector(p2.loc) + p1 = Mathutils.Vector(p1.loc) + cord = p2 - p1 # vector from p1 to p2 + clength = cord.length + s = (bulge * clength)/2.0 # sagitta (height) + radius = abs(((clength/2.0)**2.0 + s**2.0)/(2.0*s)) # magic formula + angle = (degrees(4.0*atan(bulge))) # theta (included angle) + + pieces = int(abs(angle)/(360.0/ARC_RESOLUTION)) # set a fixed step of ARC_RESOLUTION + if pieces < 3: pieces = 3 #bulge under arc_resolution + #if pieces < 3: points = [p1, p2] ;return points + step = angle/pieces # set step so pieces * step = degrees in arc + delta = (180.0 - abs(angle))/2.0 # the angle from cord to center + if bulge < 0: delta = -delta + radial = cord.normalize() * radius # a radius length vector aligned with cord + rmat = Mathutils.RotationMatrix(-delta, 3, 'Z') + center = p1 + (rmat * radial) # rotate radial by delta degrees, then add to p1 to find center + #length = radians(abs(angle)) * radius + #print 'deb:drawBulge:\n angle, delta: ', angle, delta #---------------- + #print 'deb:center, radius: ', center, radius #---------------------- + + startpoint = p1 - center + #endpoint = p2 - center + stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") + points = [startpoint] + point = Mathutils.Vector(startpoint) + for i in xrange(int(pieces)-1): #fast (but not so acurate as: vector * RotMatrix(step * i) + point = stepmatrix * point + points.append(point) + points = [[point[0]+center[0], point[1]+center[1], point[2]+center[2]] for point in points] + return points + + + +def drawArc(center, radius, start, end, ARC_RESOLUTION=120): #----------------------------------------- + """Draw a mesh arc with the given parameters. + """ + # center is currently set by object + # if start > end: start = start - 360 + if end > 360: end = end%360.0 + + startmatrix = Mathutils.RotationMatrix(-start, 3, "Z") + startpoint = startmatrix * Mathutils.Vector(radius, 0, 0) + endmatrix = Mathutils.RotationMatrix(-end, 3, "Z") + endpoint = endmatrix * Mathutils.Vector(radius, 0, 0) + + if end < start: end +=360.0 + angle = end - start + length = radians(angle) * radius + + #if radius < MIN_DIST * 10: # if circumfence is too small + pieces = int(abs(angle)/(360.0/ARC_RESOLUTION)) # set a fixed step of ARC_RESOLUTION + if pieces < 3: pieces = 3 #cambo----- + step = angle/pieces # set step so pieces * step = degrees in arc + + stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") + points = [startpoint] + point = Mathutils.Vector(startpoint) + for i in xrange(int(pieces)): + point = stepmatrix * point + points.append(point) + points.append(endpoint) + + if center: + points = [[point[0]+center[0], point[1]+center[1], point[2]+center[2]] for point in points] + edges = [[num, num+1] for num in xrange(len(points)-1)] + + return points, edges + + + +def drawCurveCircle(circle): #--- no more used -------------------------------------------- + """Given a dxf circle object return a blender circle object using curves. + """ + c = Curve.New('circle') # create new curve data + center = circle.loc + radius = circle.radius + + p1 = (0, -radius, 0) + p2 = (radius, 0, 0) + p3 = (0, radius, 0) + p4 = (-radius, 0, 0) + + p1 = BezTriple.New(p1) + p2 = BezTriple.New(p2) + p3 = BezTriple.New(p3) + p4 = BezTriple.New(p4) + + curve = c.appendNurb(p1) + curve.append(p2) + curve.append(p3) + curve.append(p4) + for point in curve: + point.handleTypes = [AUTO, AUTO] + curve.flagU = 1 # Set curve cyclic + c.update() + + ob = Object.New('Curve', 'circle') # make curve object + return ob + + +def drawCurveArc(self): #---- only for ELLIPSE ------------------------------------------------------------- + """Given a dxf ELLIPSE object return a blender_curve. + """ + center = self.loc + radius = self.radius + start = self.start_angle + end = self.end_angle + + if start > end: + start = start - 360.0 + startmatrix = Mathutils.RotationMatrix(start, 3, "Z") + startpoint = startmatrix * Mathutils.Vector((radius, 0, 0)) + endmatrix = Mathutils.RotationMatrix(end, 3, "Z") + endpoint = endmatrix * Mathutils.Vector((radius, 0, 0)) + # Note: handles must be tangent to arc and of correct length... + + a = Curve.New('arc') # create new curve data + + p1 = (0, -radius, 0) + p2 = (radius, 0, 0) + p3 = (0, radius, 0) + p4 = (-radius, 0, 0) + + p1 = BezTriple.New(p1) + p2 = BezTriple.New(p2) + p3 = BezTriple.New(p3) + p4 = BezTriple.New(p4) + + curve = a.appendNurb(p1) + curve.append(p2) + curve.append(p3) + curve.append(p4) + for point in curve: + point.handleTypes = [AUTO, AUTO] + curve.flagU = 1 # Set curve cyclic + a.update() + + ob = Object.New('Curve', 'arc') # make curve object + return ob + + + + +# GUI STUFF -----#################################################----------------- +from Blender.BGL import * + +EVENT_NONE = 1 +EVENT_START = 2 +EVENT_REDRAW = 3 +EVENT_LOAD_INI = 4 +EVENT_SAVE_INI = 5 +EVENT_PRESET = 6 +EVENT_CHOOSE_INI = 7 +EVENT_CHOOSE_DXF = 8 +EVENT_HELP = 9 +EVENT_CONFIG = 10 +EVENT_PRESET2D = 11 +EVENT_EXIT = 100 +GUI_EVENT = EVENT_NONE + +GUI_A = {} # GUI-buttons dictionary for parameter +GUI_B = {} # GUI-buttons dictionary for drawingTypes + +# settings default, initialize ------------------------ + +points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4" +lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" +mlines_as_menu = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x4" +plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" +plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" +plmesh_as_menu = "convert to: %t|mesh %x1" +solids_as_menu = "convert to: %t|mesh %x1" +blocks_as_menu = "convert to: %t|dupl.group %x1|*real.group %x2|*exploded %x3" +texts_as_menu = "convert to: %t|text %x1|*mesh %x2" +material_from_menu= "material from: %t|COLOR %x1|LAYER %x2|*LAYER+COLOR %x3|*BLOCK %x4|*XDATA %x5|*INI-File %x6" +g_scale_list = "scale factor: %t|x 1000 %x3|x 100 %x2|x 10 %x1|x 1 %x0|x 0.1 %x-1|x 0.01 %x-2|x 0.001 %x-3|x 0.0001 %x-4|x 0.00001 %x-5" + +dxfFileName = Draw.Create("") +iniFileName = Draw.Create(INIFILE_DEFAULT_NAME) +config_UI = Draw.Create(0) #switch_on/off extended config_UI + +keywords_org = { + 'curves_on' : 0, + 'optimization': 2, + 'one_mesh_on': 1, + 'vGroup_on' : 1, + 'dummy_on' : 0, + 'target_layer' : TARGET_LAYER, + 'group_bylayer_on' : GROUP_BYLAYER, + 'g_scale' : float(G_SCALE), + 'g_scale_as': int(log10(G_SCALE)), # 0, + 'g_scale_on': 1, + 'thick_on' : 1, + 'thick_min' : float(MIN_THICK), + 'thick_force': 0, + 'width_on' : 1, + 'width_min' : float(MIN_WIDTH), + 'width_force': 0, + 'dist_on' : 1, + 'dist_min' : float(MIN_DIST), + 'dist_force': 0, + 'material_on': 1, + 'material_from': 2, + 'pl_3d' : 1, + 'arc_res' : ARC_RESOLUTION, + 'thin_res' : THIN_RESOLUTION, + 'angle_cut' : ANGLECUT_LIMIT, + 'pl_section_on': 1, + 'points_as' : 2, + 'lines_as' : 2, + 'mlines_as' : 2, + 'plines_as' : 2, + 'plines3_as': 2, + 'plmesh_as' : 1, + 'solids_as' : 1, + 'blocks_as' : 1, + 'texts_as' : 1 + } + +drawTypes_org = { + 'point' : 1, + 'line' : 1, + 'arc' : 1, + 'circle': 1, + 'ellipse': 0, + 'mline' : 0, + 'polyline': 1, + 'plmesh': 1, + 'pline3': 1, + 'lwpolyline': 1, + 'text' : 1, + 'mtext' : 0, + 'block' : 1, + 'insert': 1, + 'face' : 1, + 'solid' : 1, + 'trace' : 1 + } + +# creating of GUI-buttons +# GUI_A - GUI-buttons dictionary for parameter +# GUI_B - GUI-buttons dictionary for drawingTypes +for k, v in keywords_org.iteritems(): + GUI_A[k] = Draw.Create(v) +for k, v in drawTypes_org.iteritems(): + GUI_B[k] = Draw.Create(v) +#print 'deb:init GUI_A: ', GUI_A #--------------- +#print 'deb:init GUI_B: ', GUI_B #--------------- +# initialize settings-object controls how dxf entities are drawn +settings = Settings(keywords_org, drawTypes_org) + + + +def saveConfig(): #remi--todo----------------------------------------------- + """Save settings/config/materials from GUI to INI-file. + + Write all config data to INI-file. + """ + global iniFileName + + iniFile = iniFileName.val + #print 'deb:saveConfig inifFile: ', inifFile #---------------------- + if iniFile.lower().endswith(INIFILE_EXTENSION): + output = '[%s,%s]' %(GUI_A, GUI_B) + if output =='None': + Draw.PupMenu('DXF importer: INI-file: Alert!%t|no config-data present to save!') + else: + #if BPyMessages.Warning_SaveOver(iniFile): #<- remi find it too abstarct + if sys.exists(iniFile): + f = file(iniFile, 'r'); header_str = f.readline(); f.close() + if header_str.startswith(INIFILE_HEADER[0:12]): + if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1: + save_ok = True + elif Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile + + '|Alert: this file has no valid ImportDXF-format| ! it may belong to another aplication !') == 1: + save_ok = True + else: save_ok = False + else: save_ok = True + + if save_ok: + try: + f = file(iniFile, 'w') + f.write(INIFILE_HEADER + '\n') + f.write(output) + f.close() + Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile) + except: + Draw.PupMenu('DXF importer: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile) + + else: + Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid name/extension for INI-file selected!') + print "DXF importer: Alert!: no valid INI-file selected." + if not iniFile: + if dxfFileName.val.lower().endswith('.dxf'): + iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION + + +def loadConfig(): #remi--todo----------------------------------------------- + """Load settings/config/materials from INI-file. + + Read material-assignements from config-file. + """ + #070724 buggy Window.FileSelector(loadConfigFile, 'Load config data from INI-file', inifilename) + global iniFileName, GUI_A, GUI_B + + iniFile = iniFileName.val + #print 'deb:loadConfig iniFile: ', iniFile #---------------------- + if iniFile.lower().endswith(INIFILE_EXTENSION) and sys.exists(iniFile): + f = file(iniFile, 'r') + header_str = f.readline() + if not header_str.startswith(INIFILE_HEADER): + f.close() + Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile) + else: + data_str = f.read() + f.close() + #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #----------------------------------- + data = eval(data_str) + for k, v in data[0].iteritems(): + try: + GUI_A[k].val = v + except: + GUI_A[k] = Draw.Create(v) + for k, v in data[1].iteritems(): + try: + GUI_B[k].val = v + except: + GUI_B[k] = Draw.Create(v) + else: + Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid INI-file selected!') + print "DXF importer: Alert!: no valid INI-file selected." + if not iniFileName: + if dxfFileName.val.lower().endswith('.dxf'): + iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION + + + +def resetDefaultConfig(): #remi--todo----------------------------------------------- + """Resets settings/config/materials to defaults. + + """ + global GUI_A, GUI_B + #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #----------------------------------- + for k, v in keywords_org.iteritems(): + GUI_A[k].val = v + for k, v in drawTypes_org.iteritems(): + GUI_B[k].val = v + + +def resetDefaultConfig_2D(): #remi--todo----------------------------------------------- + """Sets settings/config/materials to defaults 2D. + + """ + resetDefaultConfig() + global GUI_A, GUI_B + drawTypes2d = { + 'point' : 1, + 'line' : 1, + 'arc' : 1, + 'circle': 1, + 'ellipse': 0, + 'mline' : 0, + 'polyline': 1, + 'plmesh': 0, + 'pline3': 0, + 'lwpolyline': 1, + 'text' : 1, + 'mtext' : 0, + 'block' : 1, + 'insert': 1, + 'face' : 0, + 'solid' : 1, + 'trace' : 1 + } + + keywords2d = { + 'curves_on' : 0, + 'one_mesh_on': 1, + 'vGroup_on' : 1, + 'dummy_on' : 0, + 'thick_on' : 0, + 'thick_force': 0, + 'width_on' : 0, + 'width_force': 0, + 'dist_on' : 1, + 'dist_force': 0, + 'pl_3d' : 0, + 'pl_section_on': 1, + 'points_as' : 2, + 'lines_as' : 2, + 'mlines_as' : 2, + 'plines_as' : 2, + 'solids_as' : 1, + 'blocks_as' : 1, + 'texts_as' : 1 + } + + for k, v in keywords2d.iteritems(): + GUI_A[k].val = v + for k, v in drawTypes2d.iteritems(): + GUI_B[k].val = v + + + +def draw_UI(): #----------------------------------------------------------------- + """ Draw startUI and setup Settings. + """ + global GUI_A, GUI_B #__version__ + global iniFileName, dxfFileName, config_UI + + # This is for easy layout changes + but_1c = 140 #button 1.column width + but_2c = 70 #button 2.column + but_3c = 70 #button 3.column + menu_margin = 10 + menu_w = but_1c + but_2c + but_3c #menu width + + simlpe_menu_h = 110 + extend_menu_h = 370 + y = simlpe_menu_h # y is menu upper.y + if config_UI.val: y += extend_menu_h + x = 10 #menu left.x + but1c = x + menu_margin #buttons 1.column position.x + but2c = but1c + but_1c + but3c = but2c + but_2c + + # Here starts menu ----------------------------------------------------- + #glClear(GL_COLOR_BUFFER_BIT) + #glRasterPos2d(8, 125) + + colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin) + Draw.Label("ImportDXF-3D v" + __version__, but1c, y, menu_w, 20) + + if config_UI.val: + y -= 30 + Draw.BeginAlign() + GUI_B['point'] = Draw.Toggle('POINT', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['point'].val, "support dxf-POINT on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['points_as'] = Draw.Menu(points_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['points_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['line'] = Draw.Toggle('LINE.ARC.CIRCLE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['line'].val, "support dxf-LINE,ARC,CIRCLE,ELLIPSE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['lines_as'] = Draw.Menu(lines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['lines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['mline'] = Draw.Toggle('*MLINE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['mline'].val, "(*wip)support dxf-MLINE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['mlines_as'] = Draw.Menu(mlines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['mlines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['polyline'] = Draw.Toggle('2D-POLYLINE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['polyline'].val, "support dxf-2D-POLYLINE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['plines_as'] = Draw.Menu(plines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['pline3'] = Draw.Toggle('3D-POLYLINE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['pline3'].val, "support dxf-3D-POLYLINE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['plines3_as'] = Draw.Menu(plines3_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plines3_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['plmesh'] = Draw.Toggle('POLYMESH/-FACE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['plmesh_as'] = Draw.Menu(plmesh_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plmesh_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['solid'] = Draw.Toggle('3DFACE.SOLID.TRACE', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['solid'].val, "support dxf-3DFACE, SOLID and TRACE on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['solids_as'] = Draw.Menu(solids_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['solids_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_B['text'].val, "support dxf-TEXT on/off") + GUI_B['mtext'] = Draw.Toggle('*MTEXT', EVENT_NONE, but1c+but_1c/2, y, but_1c/2, 20, GUI_B['mtext'].val, "(*wip)support dxf-MTEXT on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['block'] = Draw.Toggle('BLOCK / ARRAY', EVENT_NONE, but1c, y, but_1c, 20, GUI_B['block'].val, "support dxf-BLOCK and ARRAY on/off") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['blocks_as'] = Draw.Menu(blocks_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['blocks_as'].val, "select target Blender-object") + Draw.EndAlign() + + + y -= 20 + Draw.BeginAlign() + GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['material_from'].val, "material assignment from?") + Draw.Label('-->', but2c, y, but_2c, 20) + GUI_A['material_on'] = Draw.Toggle('material', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['material_on'].val, "support for material assignment on/off") + Draw.EndAlign() + + + y -= 30 + Draw.BeginAlign() + GUI_A['group_bylayer_on'] = Draw.Toggle('oneGroup', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['group_bylayer_on'].val, "group entities from the same layer on/off") + GUI_A['curves_on'] = Draw.Toggle('to Curve', EVENT_NONE, but1c+ but_1c/2, y, but_1c/2, 20, GUI_A['curves_on'].val, "draw LINE/ARC/*PLINE into Blender-Curves instead of Meshes on/off") + GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but2c, y, (but_2c+but_3c)/2, 20, GUI_A['dummy_on'].val, "dummy on/off") + GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, but2c+(but_2c+but_3c)/2, y, (but_2c+but_3c)/2, 20, GUI_A['target_layer'].val, 1, 18, "draw all into this Blender-layer (except <19> for block_definitios)") + Draw.EndAlign() + + + y -= 20 + Draw.BeginAlign() + GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['one_mesh_on'].val, "draw LINEs/3DFACEs from the same layer into one mesh-object on/off") + GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, but1c+ but_1c/2, y, but_1c/2, 20, GUI_A['vGroup_on'].val, "support Blender-VertexGroups on/off") + GUI_A['g_scale_on'] = Draw.Toggle('glob.Scale', EVENT_NONE, but2c, y, (but_2c+but_3c)/2, 20, GUI_A['g_scale_on'].val, "scaling all DXF objects on/off") + GUI_A['g_scale_as'] = Draw.Menu(g_scale_list, EVENT_NONE, but2c+(but_2c+but_3c)/2, y, (but_2c+but_3c)/2, 20, GUI_A['g_scale_as'].val, "10^ factor for scaling the DXFdata") + Draw.EndAlign() + + + y -= 20 + Draw.BeginAlign() + Draw.Label('', but1c+but_1c/2, y, but_1c/2, 20) + GUI_A['dist_on'] = Draw.Toggle('dist.:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['dist_on'].val, "support distance on/off") + GUI_A['dist_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['dist_force'].val, "force minimal distance on/off (double.vertex removing)") + GUI_A['dist_min'] = Draw.Number('', EVENT_NONE, but2c+(but_2c+but_3c)/2, y, (but_2c+but_3c)/2, 20, GUI_A['dist_min'].val, 0, 10, "minimal distance for double.vertex removing") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_A['pl_section_on'] = Draw.Toggle('self.cut:', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['pl_section_on'].val, "support POLYLINE-wide-segment-intersection on/off") + GUI_A['angle_cut'] = Draw.Number('', EVENT_NONE, but1c+but_1c/2, y, but_1c/2, 20, GUI_A['angle_cut'].val, 1, 5, "it limits POLYLINE-wide-segment-intersection: 1.0-5.0") + GUI_A['thick_on'] = Draw.Toggle('thick:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['thick_on'].val, "support thickness on/off") + GUI_A['thick_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['thick_force'].val, "force minimal thickness on/off") + GUI_A['thick_min'] = Draw.Number('', EVENT_NONE, but2c+(but_2c+but_3c)/2, y, (but_2c+but_3c)/2, 20, GUI_A['thick_min'].val, 0, 10, "minimal thickness") + Draw.EndAlign() + + + y -= 20 + Draw.BeginAlign() + GUI_A['arc_res'] = Draw.Number('arc:''', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['arc_res'].val, 4, 500, "arc/circle resolution - number of segments") + GUI_A['thin_res'] = Draw.Number('thin:', EVENT_NONE, but1c+but_1c/2, y, but_1c/2, 20, GUI_A['thin_res'].val, 4, 500, "thin cylinder resolution - number of segments") + GUI_A['width_on'] = Draw.Toggle('width:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['width_on'].val, "support width on/off") + GUI_A['width_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['width_force'].val, "force minimal width on/off") + GUI_A['width_min'] = Draw.Number('', EVENT_NONE, but2c+(but_2c+but_3c)/2, y, (but_2c+but_3c)/2, 20, GUI_A['width_min'].val, 0, 10, "minimal width") + Draw.EndAlign() + + y -= 30 + Draw.BeginAlign() + Draw.PushButton('Load', EVENT_LOAD_INI, but1c, y, but_1c/2, 20, ' Load configuration from ini-file: %s' % iniFileName.val) + Draw.PushButton('Save', EVENT_SAVE_INI, but1c+but_1c/2, y, but_1c/2, 20, 'Save configuration to ini-file: %s' % iniFileName.val) + GUI_A['optimization'] = Draw.Number('optim:', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['optimization'].val, 0, 3, "Optimisation Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=silentMode/fastest") + Draw.PushButton('3D', EVENT_PRESET, but3c, y, but_3c/2, 20, 'reset configuration to 3D-defaults') + Draw.PushButton('2D', EVENT_PRESET2D, but3c+but_3c/2, y, but_3c/2, 20, 'reset configuration to 2D-defaults') + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but1c, y, but_1c/2, 20, 'Select INI-file from project directory') + iniFileName = Draw.String(' : ', EVENT_NONE, but1c+(but_1c/2), y, but_1c/2+but_2c+but_3c, 20, iniFileName.val, FILENAME_MAX, "write here the name of the INI-file") + Draw.EndAlign() + + y -= 30 + Draw.BeginAlign() + Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but1c, y, but_1c/2, 20, 'Select DXF-file from project directory') + dxfFileName = Draw.String(' :', EVENT_NONE, but1c+(but_1c/2), y, but_1c/2+but_2c+but_3c, 20, dxfFileName.val, FILENAME_MAX, "write here the name of the imported DXF-file") + Draw.EndAlign() + + y -= 50 + Draw.BeginAlign() + Draw.Label(' ', but1c-menu_margin, y, menu_margin, 40) + Draw.PushButton('EXIT', EVENT_EXIT, but1c, y, but_1c/2, 40, '' ) + Draw.PushButton('HELP', EVENT_HELP, but1c+but_1c/2, y, but_1c/2, 20, 'manual-page on Blender-Wiki, support at www.blenderartists.org') + Draw.PushButton('START IMPORT', EVENT_START, but2c, y, but_2c+but_3c, 40, 'Start the import procedure') + Draw.Label(' ', but1c+menu_w, y, menu_margin, 40) + Draw.EndAlign() + + config_UI = Draw.Toggle('CONFIG', EVENT_CONFIG, but1c+but_1c/2, y+20, but_1c/2, 20, config_UI.val, 'Advanced configuration on/off' ) + + y -= 20 + Draw.BeginAlign() + Draw.Label("*) parts under construction", but1c, y, menu_w, 20) + Draw.EndAlign() + +#-- END GUI Stuf----------------------------------------------------- + +def colorbox(x,y,xright,bottom): + glColor3f(0.75, 0.75, 0.75) + glRecti(x + 1, y + 1, xright - 1, bottom - 1) + +def dxf_callback(input_filename): + global dxfFileName + dxfFileName.val=input_filename + +def ini_callback(input_texture): + global iniFileName + iniFileName.val=input_texture + +def event(evt, val): + if evt in (Draw.QKEY, Draw.ESCKEY) and not val: + Blender.Draw.Exit() + +def bevent(evt): +# global EVENT_NONE,EVENT_LOAD_DXF,EVENT_LOAD_INI,EVENT_SAVE_INI,EVENT_EXIT + global config_UI + + ######### Manages GUI events + if (evt==EVENT_EXIT): + Blender.Draw.Exit() + elif (evt==EVENT_CHOOSE_INI): + Window.FileSelector(ini_callback, "INI-file Selection", '*.ini') + elif (evt==EVENT_CONFIG): + Draw.Redraw() + elif (evt==EVENT_PRESET): + resetDefaultConfig() + Draw.Redraw() + elif (evt==EVENT_PRESET2D): + resetDefaultConfig_2D() + Draw.Redraw() + elif (evt==EVENT_HELP): + try: + import webbrowser + webbrowser.open('http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') + except: + Draw.PupMenu('DXF importer: HELP Alert!%t|no connection to manual-page on Blender-Wiki! try:|\ +http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') + Draw.Redraw() + elif (evt==EVENT_LOAD_INI): + loadConfig() + Draw.Redraw() + elif (evt==EVENT_SAVE_INI): + saveConfig() + Draw.Redraw() + elif (evt==EVENT_CHOOSE_DXF): + Window.FileSelector(dxf_callback, "DXF-file Selection", '*.dxf') + elif (evt==EVENT_START): + dxfFile = dxfFileName.val + #print 'deb: dxfFile file: ', dxfFile #---------------------- + if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): + main() + #Blender.Draw.Exit() + Draw.Redraw() + else: + Draw.PupMenu('DXF importer: Alert!%t|no valid DXF-file selected!') + print "DXF importer: error, no valid DXF-file selected! try again" + Draw.Redraw() if __name__ == "__main__": - Window.FileSelector(main, 'Import a DXF file', '*.dxf') + UI_MODE = True + Draw.Register(draw_UI, event, bevent) + + +""" +if 1: + # DEBUG ONLY + TIME= Blender.sys.time() + #DIR = '/dxf_r12_testfiles/' + DIR = '/metavr/' + import os + print 'Searching for files' + os.system('find %s -iname "*.dxf" > /tmp/tempdxf_list' % DIR) + # os.system('find /storage/ -iname "*.dxf" > /tmp/tempdxf_list') + print '...Done' + file= open('/tmp/tempdxf_list', 'r') + lines= file.readlines() + file.close() + # sort by filesize for faster testing + lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines] + lines_size.sort() + lines = [f[1] for f in lines_size] + + + + for i, _dxf in enumerate(lines): + if i >= 70: + #if 1: + print 'Importing', _dxf, '\nNUMBER', i, 'of', len(lines) + _dxf_file= _dxf.split('/')[-1].split('\\')[-1] + newScn= bpy.data.scenes.new(_dxf_file) + bpy.data.scenes.active = newScn + # load_dxf(_dxf, False) + dxfFileName.val = _dxf + main() + + print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) +"""
\ No newline at end of file |