00001 """This module provides wrapper objects for dxf entities.
00002
00003 The wrappers expect a "dxf object" as input. The dxf object is
00004 an object with a type and a data attribute. Type is a lowercase
00005 string matching the 0 code of a dxf entity. Data is a list containing
00006 dxf objects or lists of [code, data] pairs.
00007
00008 This module is not general, and is only for dxf import.
00009 """
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 from math import *
00033
00034
00035
00036
00037 BYBLOCK=0
00038 BYLAYER=256
00039
00040
00041 ANONYMOUS =1
00042 NON_CONSTANT_ATTRIBUTES =2
00043 XREF =4
00044 XREF_OVERLAY =8
00045 EXTERNAL =16
00046 RESOLVED =32
00047 REFERENCED =64
00048
00049
00050
00051 TOP_LEFT = 1
00052 TOP_CENTER = 2
00053 TOP_RIGHT = 3
00054 MIDDLE_LEFT = 4
00055 MIDDLE_CENTER = 5
00056 MIDDLE_RIGHT = 6
00057 BOTTOM_LEFT = 7
00058 BOTTOM_CENTER = 8
00059 BOTTOM_RIGHT = 9
00060
00061 LEFT_RIGHT = 1
00062 TOP_BOTTOM = 3
00063 BY_STYLE = 5
00064
00065 AT_LEAST = 1
00066 EXACT = 2
00067
00068
00069 CLOSED =1
00070 CURVE_FIT =2
00071 SPLINE_FIT =4
00072 POLYLINE_3D =8
00073 POLYGON_MESH =16
00074 CLOSED_N =32
00075 POLYFACE_MESH =64
00076 CONTINOUS_LINETYPE_PATTERN =128
00077
00078
00079
00080 LEFT = 0
00081 CENTER = 1
00082 RIGHT = 2
00083 ALIGNED = 3
00084 MIDDLE = 4
00085 FIT = 5
00086
00087 BASELINE = 0
00088 BOTTOM = 1
00089 MIDDLE = 2
00090 TOP = 3
00091 class Object:
00092 """Empty container class for dxf objects"""
00093
00094 def __init__(self, _type=''):
00095 """_type expects a string value."""
00096 self.type = _type
00097 self.name = ''
00098 self.data = []
00099
00100 def __str__(self):
00101 if self.name:
00102 return self.name
00103 else:
00104 return self.type
00105
00106 def __repr__(self):
00107 return str(self.data)
00108
00109 def get_type(self, kind=''):
00110 """Despite the name, this method actually returns all objects of type 'kind' from self.data."""
00111 if type:
00112 objects = []
00113 for item in self.data:
00114 if type(item) != list and item.type == kind:
00115
00116 objects.append(item)
00117 elif type(item) == list and item[0] == kind:
00118
00119 objects.append(item[1])
00120 return objects
00121
00122
00123 class Layer:
00124 """Class for objects representing dxf layers."""
00125
00126 def __init__(self, obj):
00127 """Expects an entity object of type line as input."""
00128 self.type = obj.type
00129 self.data = obj.data[:]
00130
00131 self.name = obj.get_type(2)[0]
00132 self.color = obj.get_type(62)[0]
00133 self.flags = obj.get_type(70)[0]
00134 self.frozen = self.flags&1
00135
00136
00137
00138 def __repr__(self):
00139 return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color)
00140
00141
00142
00143 class Line:
00144 """Class for objects representing dxf lines."""
00145
00146 def __init__(self, obj):
00147 """Expects an entity object of type line as input."""
00148 if not obj.type == 'line':
00149 raise TypeError, "Wrong type %s for line object!" %obj.type
00150 self.type = obj.type
00151 self.data = obj.data[:]
00152
00153 self.space = obj.get_type(67)
00154 if self.space:
00155 self.space = self.space[0]
00156 else:
00157 self.space = 0
00158
00159 self.color_index = obj.get_type(62)
00160 if self.color_index:
00161 self.color_index = self.color_index[0]
00162 else:
00163 self.color_index = BYLAYER
00164
00165 discard, self.layer, discard_index = get_layer(obj.data)
00166 del obj.data[discard_index]
00167
00168 self.points = self.get_points(obj.data)
00169
00170
00171
00172
00173 def get_points(self, data):
00174 """Gets start and end points for a line type object.
00175
00176 Lines have a fixed number of points (two) and fixed codes for each value.
00177 """
00178
00179
00180 sx, sy, sz, ex, ey, ez = 0, 0, 0, 0, 0, 0
00181 for item in data:
00182 if item[0] == 10:
00183 sx = item[1]
00184 elif item[0] == 20:
00185 sy = item[1]
00186 elif item[0] == 30:
00187 sz = item[1]
00188 elif item[0] == 11:
00189 ex = item[1]
00190 elif item[0] == 21:
00191 ey = item[1]
00192 elif item[0] == 31:
00193 ez = item[1]
00194 return [[sx, sy, sz], [ex, ey, ez]]
00195
00196
00197
00198 def __repr__(self):
00199 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00200
00201
00202
00203 class LWpolyline:
00204 """Class for objects representing dxf LWpolylines."""
00205
00206 def __init__(self, obj):
00207 """Expects an entity object of type lwpolyline as input."""
00208 if not obj.type == 'lwpolyline':
00209 raise TypeError, "Wrong type %s for polyline object!" %obj.type
00210 self.type = obj.type
00211 self.data = obj.data[:]
00212
00213
00214 self.num_points = obj.get_type(90)[0]
00215
00216
00217 self.space = obj.get_type(67)
00218 if self.space:
00219 self.space = self.space[0]
00220 else:
00221 self.space = 0
00222
00223 self.color_index = obj.get_type(62)
00224 if self.color_index:
00225 self.color_index = self.color_index[0]
00226 else:
00227 self.color_index = BYLAYER
00228
00229 self.elevation = obj.get_type(38)
00230 if self.elevation:
00231 self.elevation = self.elevation[0]
00232 else:
00233 self.elevation = 0
00234
00235 self.flags = obj.get_type(70)
00236 if self.flags:
00237 self.flags = self.flags[0]
00238 else:
00239 self.flags = 0
00240
00241 self.closed = self.flags&1
00242 discard, self.layer, discard_index = get_layer(obj.data)
00243 del obj.data[discard_index]
00244 self.points = self.get_points(obj.data)
00245 self.extrusion = self.get_extrusion(obj.data)
00246
00247
00248
00249
00250
00251
00252 def get_points(self, data):
00253 """Gets points for a polyline type object.
00254
00255 Polylines have no fixed number of verts, and
00256 each vert can have a number of properties.
00257 Verts should be coded as
00258 10:xvalue
00259 20:yvalue
00260 40:startwidth or 0
00261 41:endwidth or 0
00262 42:bulge or 0
00263 for each vert
00264 """
00265 num = self.num_points
00266 point = None
00267 points = []
00268 for item in data:
00269 if item[0] == 10:
00270 if point:
00271 points.append(point)
00272 point = Vertex()
00273 point.x = item[1]
00274 elif item[0] == 20:
00275 point.y = item[1]
00276 elif item[0] == 40:
00277 point.swidth = item[1]
00278 elif item[0] == 41:
00279 point.ewidth = item[1]
00280 elif item[0] == 42:
00281 point.bulge = item[1]
00282 points.append(point)
00283 return points
00284
00285
00286 def get_extrusion(self, data):
00287 """Find the axis of extrusion.
00288
00289 Used to get the objects Object Coordinate System (ocs).
00290 """
00291 vec = [0,0,1]
00292 for item in data:
00293 if item[0] == 210:
00294 vec[0] = item[1]
00295 elif item[0] == 220:
00296 vec[1] = item[1]
00297 elif item[0] == 230:
00298 vec[2] = item[1]
00299 return vec
00300
00301
00302 def __repr__(self):
00303 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00304
00305
00306
00307 class Polyline:
00308 """Class for objects representing dxf LWpolylines."""
00309
00310 def __init__(self, obj):
00311 """Expects an entity object of type polyline as input."""
00312 if not obj.type == 'polyline':
00313 raise TypeError, "Wrong type %s for polyline object!" %obj.type
00314 self.type = obj.type
00315 self.data = obj.data[:]
00316 self.points = []
00317
00318
00319 self.space = obj.get_type(67)
00320 if self.space:
00321 self.space = self.space[0]
00322 else:
00323 self.space = 0
00324
00325 self.color_index = obj.get_type(62)
00326 if self.color_index:
00327 self.color_index = self.color_index[0]
00328 else:
00329 self.color_index = BYLAYER
00330
00331 self.elevation = obj.get_type(30)
00332 if self.elevation:
00333 self.elevation = self.elevation[0]
00334 else:
00335 self.elevation = 0
00336
00337 self.flags = obj.get_type(70)
00338 if self.flags:
00339 self.flags = self.flags[0]
00340 else:
00341 self.flags = 0
00342
00343 self.closed = self.flags&1
00344
00345 discard, self.layer, discard_index = get_layer(obj.data)
00346 del obj.data[discard_index]
00347 self.extrusion = self.get_extrusion(obj.data)
00348
00349
00350
00351
00352
00353 def get_extrusion(self, data):
00354 """Find the axis of extrusion.
00355
00356 Used to get the objects Object Coordinate System (ocs).
00357 """
00358 vec = [0,0,1]
00359 for item in data:
00360 if item[0] == 210:
00361 vec[0] = item[1]
00362 elif item[0] == 220:
00363 vec[1] = item[1]
00364 elif item[0] == 230:
00365 vec[2] = item[1]
00366 return vec
00367
00368
00369 def __repr__(self):
00370 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00371
00372
00373
00374 class Vertex(object):
00375 """Generic vertex object used by polylines (and maybe others)."""
00376
00377 def __init__(self, obj=None):
00378 """Initializes vertex data.
00379
00380 The optional obj arg is an entity object of type vertex.
00381 """
00382 self.loc = [0,0,0]
00383 self.bulge = 0
00384 self.swidth = 0
00385 self.ewidth = 0
00386 self.flags = 0
00387
00388 if obj is not None:
00389 if not obj.type == 'vertex':
00390 raise TypeError, "Wrong type %s for vertex object!" %obj.type
00391 self.type = obj.type
00392 self.data = obj.data[:]
00393
00394 self.get_props(obj.data)
00395
00396
00397 def get_props(self, data):
00398 """Gets coords for a vertex type object.
00399
00400 Each vert can have a number of properties.
00401 Verts should be coded as
00402 10:xvalue
00403 20:yvalue
00404 40:startwidth or 0
00405 41:endwidth or 0
00406 42:bulge or 0
00407 """
00408 for item in data:
00409 if item[0] == 10:
00410 self.x = item[1]
00411 elif item[0] == 20:
00412 self.y = item[1]
00413 elif item[0] == 30:
00414 self.z = item[1]
00415 elif item[0] == 40:
00416 self.swidth = item[1]
00417 elif item[0] == 41:
00418 self.ewidth = item[1]
00419 elif item[0] == 42:
00420 self.bulge = item[1]
00421 elif item[0] == 70:
00422 self.flags = item[1]
00423
00424
00425 def __len__(self):
00426 return 3
00427
00428
00429 def __getitem__(self, key):
00430 return self.loc[key]
00431
00432
00433 def __setitem__(self, key, value):
00434 if key in [0,1,2]:
00435 self.loc[key]
00436
00437
00438 def __iter__(self):
00439 return self.loc.__iter__()
00440
00441
00442 def __str__(self):
00443 return str(self.loc)
00444
00445
00446 def __repr__(self):
00447 return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s" %(self.loc, self.swidth, self.ewidth, self.bulge)
00448
00449
00450 def getx(self):
00451 return self.loc[0]
00452
00453 def setx(self, value):
00454 self.loc[0] = value
00455
00456 x = property(getx, setx)
00457
00458
00459 def gety(self):
00460 return self.loc[1]
00461
00462 def sety(self, value):
00463 self.loc[1] = value
00464
00465 y = property(gety, sety)
00466
00467
00468 def getz(self):
00469 return self.loc[2]
00470
00471 def setz(self, value):
00472 self.loc[2] = value
00473
00474 z = property(getz, setz)
00475
00476
00477
00478 class Text:
00479 """Class for objects representing dxf Text."""
00480
00481 def __init__(self, obj):
00482 """Expects an entity object of type text as input."""
00483 if not obj.type == 'text':
00484 raise TypeError, "Wrong type %s for text object!" %obj.type
00485 self.type = obj.type
00486 self.data = obj.data[:]
00487
00488
00489 self.height = obj.get_type(40)[0]
00490 self.value = obj.get_type(1)[0]
00491
00492
00493 self.space = obj.get_type(67)
00494 if self.space:
00495 self.space = self.space[0]
00496 else:
00497 self.space = 0
00498
00499 self.color_index = obj.get_type(62)
00500 if self.color_index:
00501 self.color_index = self.color_index[0]
00502 else:
00503 self.color_index = BYLAYER
00504
00505 self.rotation = obj.get_type(50)
00506 if not self.rotation:
00507 self.rotation = 0
00508 else:
00509 self.rotation = self.rotation[0]
00510
00511 self.width_factor = obj.get_type(41)
00512 if not self.width_factor:
00513 self.width_factor = 1
00514 else:
00515 self.width_factor = self.width_factor[0]
00516
00517 self.oblique = obj.get_type(51)
00518 if not self.oblique:
00519 self.oblique = 0
00520 else:
00521 self.oblique = self.oblique[0]
00522
00523 self.halignment = obj.get_type(72)
00524 if not self.halignment:
00525 self.halignment = 0
00526 else:
00527 self.halignment = self.halignment[0]
00528
00529 self.valignment = obj.get_type(73)
00530 if not self.valignment:
00531 self.valignment = 0
00532 else:
00533 self.valignment = self.valignment[0]
00534
00535 discard, self.layer, discard_index = get_layer(obj.data)
00536 del obj.data[discard_index]
00537 self.loc = self.get_loc(obj.data, self.halignment, self.valignment)
00538 self.extrusion = self.get_extrusion(obj.data)
00539
00540
00541
00542
00543 def get_loc(self, data, halign, valign):
00544 """Gets adjusted location for text type objects.
00545
00546 If group 72 and/or 73 values are nonzero then the first alignment point values
00547 are ignored and AutoCAD calculates new values based on the second alignment
00548 point and the length and height of the text string itself (after applying the
00549 text style). If the 72 and 73 values are zero or missing, then the second
00550 alignment point is meaningless.
00551
00552 I don't know how to calc text size...
00553 """
00554
00555 x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0
00556 for item in data:
00557 if item[0] == 10:
00558 x = item[1]
00559 elif item[0] == 20:
00560 y = item[1]
00561 elif item[0] == 30:
00562 z = item[1]
00563 elif item[0] == 11:
00564 jx = item[1]
00565 elif item[0] == 21:
00566 jy = item[1]
00567 elif item[0] == 31:
00568 jz = item[1]
00569
00570 if halign or valign:
00571 x, y, z = jx, jy, jz
00572 return [x, y, z]
00573
00574 def get_extrusion(self, data):
00575 """Find the axis of extrusion.
00576
00577 Used to get the objects Object Coordinate System (ocs).
00578 """
00579 vec = [0,0,1]
00580 for item in data:
00581 if item[0] == 210:
00582 vec[0] = item[1]
00583 elif item[0] == 220:
00584 vec[1] = item[1]
00585 elif item[0] == 230:
00586 vec[2] = item[1]
00587 return vec
00588
00589
00590 def __repr__(self):
00591 return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
00592
00593
00594
00595 class Mtext:
00596 """Class for objects representing dxf Mtext."""
00597
00598 def __init__(self, obj):
00599 """Expects an entity object of type mtext as input."""
00600 if not obj.type == 'mtext':
00601 raise TypeError, "Wrong type %s for mtext object!" %obj.type
00602 self.type = obj.type
00603 self.data = obj.data[:]
00604
00605
00606 self.height = obj.get_type(40)[0]
00607 self.width = obj.get_type(41)[0]
00608 self.alignment = obj.get_type(71)[0]
00609 self.value = self.get_text(obj.data)
00610
00611
00612 self.space = obj.get_type(67)
00613 if self.space:
00614 self.space = self.space[0]
00615 else:
00616 self.space = 0
00617
00618 self.color_index = obj.get_type(62)
00619 if self.color_index:
00620 self.color_index = self.color_index[0]
00621 else:
00622 self.color_index = BYLAYER
00623
00624 self.rotation = obj.get_type(50)
00625 if not self.rotation:
00626 self.rotation = 0
00627 else:
00628 self.rotation = self.rotation[0]
00629
00630 self.width_factor = obj.get_type(42)
00631 if not self.width_factor:
00632 self.width_factor = 1
00633 else:
00634 self.width_factor = self.width_factor[0]
00635
00636 self.line_space = obj.get_type(44)
00637 if not self.line_space:
00638 self.line_space = 1
00639 else:
00640 self.line_space = self.line_space[0]
00641
00642 discard, self.layer, discard_index = get_layer(obj.data)
00643 del obj.data[discard_index]
00644 self.loc = self.get_loc(obj.data)
00645 self.extrusion = self.get_extrusion(obj.data)
00646
00647
00648
00649
00650
00651 def get_text(self, data):
00652 """Reconstructs mtext data from dxf codes."""
00653 primary = ''
00654 secondary = []
00655 for item in data:
00656 if item[0] == 1:
00657 primary = item[1]
00658 elif item[0] == 3:
00659 secondary.append(item[1])
00660 if not primary:
00661
00662 string = "Empty Mtext Object!"
00663 if not secondary:
00664 string = primary.replace(r'\P', '\n')
00665 else:
00666 string = ''.join(secondary)+primary
00667 string = string.replace(r'\P', '\n')
00668 return string
00669 def get_loc(self, data):
00670 """Gets location for a mtext type objects.
00671
00672 Mtext objects have only one point indicating location.
00673 """
00674 loc = [0,0,0]
00675 for item in data:
00676 if item[0] == 10:
00677 loc[0] = item[1]
00678 elif item[0] == 20:
00679 loc[1] = item[1]
00680 elif item[0] == 30:
00681 loc[2] = item[1]
00682 return loc
00683
00684
00685
00686
00687 def get_extrusion(self, data):
00688 """Find the axis of extrusion.
00689
00690 Used to get the objects Object Coordinate System (ocs).
00691 """
00692 vec = [0,0,1]
00693 for item in data:
00694 if item[0] == 210:
00695 vec[0] = item[1]
00696 elif item[0] == 220:
00697 vec[1] = item[1]
00698 elif item[0] == 230:
00699 vec[2] = item[1]
00700 return vec
00701
00702
00703 def __repr__(self):
00704 return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
00705
00706
00707
00708 class Circle:
00709 """Class for objects representing dxf Circles."""
00710
00711 def __init__(self, obj):
00712 """Expects an entity object of type circle as input."""
00713 if not obj.type == 'circle':
00714 raise TypeError, "Wrong type %s for circle object!" %obj.type
00715 self.type = obj.type
00716 self.data = obj.data[:]
00717
00718
00719 self.radius = obj.get_type(40)[0]
00720
00721
00722 self.space = obj.get_type(67)
00723 if self.space:
00724 self.space = self.space[0]
00725 else:
00726 self.space = 0
00727
00728 self.color_index = obj.get_type(62)
00729 if self.color_index:
00730 self.color_index = self.color_index[0]
00731 else:
00732 self.color_index = BYLAYER
00733
00734 discard, self.layer, discard_index = get_layer(obj.data)
00735 del obj.data[discard_index]
00736 self.loc = self.get_loc(obj.data)
00737 self.extrusion = self.get_extrusion(obj.data)
00738
00739
00740
00741
00742
00743 def get_loc(self, data):
00744 """Gets the center location for circle type objects.
00745
00746 Circles have a single coord location.
00747 """
00748 loc = [0, 0, 0]
00749 for item in data:
00750 if item[0] == 10:
00751 loc[0] = item[1]
00752 elif item[0] == 20:
00753 loc[1] = item[1]
00754 elif item[0] == 30:
00755 loc[2] = item[1]
00756 return loc
00757
00758
00759
00760 def get_extrusion(self, data):
00761 """Find the axis of extrusion.
00762
00763 Used to get the objects Object Coordinate System (ocs).
00764 """
00765 vec = [0,0,1]
00766 for item in data:
00767 if item[0] == 210:
00768 vec[0] = item[1]
00769 elif item[0] == 220:
00770 vec[1] = item[1]
00771 elif item[0] == 230:
00772 vec[2] = item[1]
00773 return vec
00774
00775
00776 def __repr__(self):
00777 return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
00778
00779
00780
00781 class Arc:
00782 """Class for objects representing dxf arcs."""
00783
00784 def __init__(self, obj):
00785 """Expects an entity object of type arc as input."""
00786 if not obj.type == 'arc':
00787 raise TypeError, "Wrong type %s for arc object!" %obj.type
00788 self.type = obj.type
00789 self.data = obj.data[:]
00790
00791
00792 self.radius = obj.get_type(40)[0]
00793 self.start_angle = obj.get_type(50)[0]
00794 self.end_angle = obj.get_type(51)[0]
00795
00796
00797 self.space = obj.get_type(67)
00798 if self.space:
00799 self.space = self.space[0]
00800 else:
00801 self.space = 0
00802
00803 self.color_index = obj.get_type(62)
00804 if self.color_index:
00805 self.color_index = self.color_index[0]
00806 else:
00807 self.color_index = BYLAYER
00808
00809 discard, self.layer, discard_index = get_layer(obj.data)
00810 del obj.data[discard_index]
00811 self.loc = self.get_loc(obj.data)
00812 self.extrusion = self.get_extrusion(obj.data)
00813
00814
00815
00816
00817
00818 def get_loc(self, data):
00819 """Gets the center location for arc type objects.
00820
00821 Arcs have a single coord location.
00822 """
00823 loc = [0, 0, 0]
00824 for item in data:
00825 if item[0] == 10:
00826 loc[0] = item[1]
00827 elif item[0] == 20:
00828 loc[1] = item[1]
00829 elif item[0] == 30:
00830 loc[2] = item[1]
00831 return loc
00832
00833
00834
00835 def get_extrusion(self, data):
00836 """Find the axis of extrusion.
00837
00838 Used to get the objects Object Coordinate System (ocs).
00839 """
00840 vec = [0,0,1]
00841 for item in data:
00842 if item[0] == 210:
00843 vec[0] = item[1]
00844 elif item[0] == 220:
00845 vec[1] = item[1]
00846 elif item[0] == 230:
00847 vec[2] = item[1]
00848 return vec
00849
00850
00851 def __repr__(self):
00852 return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
00853
00854
00855
00856 class BlockRecord:
00857 """Class for objects representing dxf block_records."""
00858
00859 def __init__(self, obj):
00860 """Expects an entity object of type block_record as input."""
00861 if not obj.type == 'block_record':
00862 raise TypeError, "Wrong type %s for block_record object!" %obj.type
00863 self.type = obj.type
00864 self.data = obj.data[:]
00865
00866
00867 self.name = obj.get_type(2)[0]
00868
00869
00870 self.insertion_units = obj.get_type(70)
00871 if not self.insertion_units:
00872 self.insertion_units = None
00873 else:
00874 self.insertion_units = self.insertion_units[0]
00875
00876 self.insert_units = obj.get_type(1070)
00877 if not self.insert_units:
00878 self.insert_units = None
00879 else:
00880 self.insert_units = self.insert_units[0]
00881
00882
00883
00884
00885
00886
00887 def __repr__(self):
00888 return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units)
00889
00890
00891
00892
00893 class Block:
00894 """Class for objects representing dxf blocks."""
00895
00896 def __init__(self, obj):
00897 """Expects an entity object of type block as input."""
00898 if not obj.type == 'block':
00899 raise TypeError, "Wrong type %s for block object!" %obj.type
00900 self.type = obj.type
00901 self.data = obj.data[:]
00902
00903
00904 self.flags = obj.get_type(70)[0]
00905 self.entities = Object('block_contents')
00906 self.entities.data = objectify([ent for ent in obj.data if type(ent) != list])
00907
00908
00909 self.name = obj.get_type(3)
00910 if self.name:
00911 self.name = self.name[0]
00912 else:
00913 self.name = obj.get_type(2)
00914 if self.name:
00915 self.name = self.name[0]
00916 else:
00917 self.name = 'blank'
00918
00919 self.path = obj.get_type(1)
00920 if self.path:
00921 self.path = self.path[0]
00922 else:
00923 self.path = ''
00924
00925 self.discription = obj.get_type(4)
00926 if self.discription:
00927 self.discription = self.discription[0]
00928 else:
00929 self.discription = ''
00930
00931 discard, self.layer, discard_index = get_layer(obj.data)
00932 del obj.data[discard_index]
00933 self.loc = self.get_loc(obj.data)
00934
00935
00936
00937
00938
00939 def get_loc(self, data):
00940 """Gets the insert point of the block."""
00941 loc = [0, 0, 0]
00942 for item in data:
00943 if type(item) != list:
00944 continue
00945 if item[0] == 10:
00946 loc[0] = item[1]
00947 elif item[0] == 20:
00948 loc[1] = item[1]
00949 elif item[0] == 30:
00950 loc[2] = item[1]
00951 return loc
00952
00953
00954
00955 def __repr__(self):
00956 return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path)
00957
00958
00959
00960
00961 class Insert:
00962 """Class for objects representing dxf inserts."""
00963
00964 def __init__(self, obj):
00965 """Expects an entity object of type insert as input."""
00966 if not obj.type == 'insert':
00967 raise TypeError, "Wrong type %s for insert object!" %obj.type
00968 self.type = obj.type
00969 self.data = obj.data[:]
00970
00971
00972 self.block = obj.get_type(2)[0]
00973
00974
00975 self.rotation = obj.get_type(50)
00976 if self.rotation:
00977 self.rotation = self.rotation[0]
00978 else:
00979 self.rotation = 0
00980
00981 self.space = obj.get_type(67)
00982 if self.space:
00983 self.space = self.space[0]
00984 else:
00985 self.space = 0
00986
00987 self.color_index = obj.get_type(62)
00988 if self.color_index:
00989 self.color_index = self.color_index[0]
00990 else:
00991 self.color_index = BYLAYER
00992
00993 discard, self.layer, discard_index = get_layer(obj.data)
00994 del obj.data[discard_index]
00995 self.loc = self.get_loc(obj.data)
00996 self.scale = self.get_scale(obj.data)
00997 self.rows, self.columns = self.get_array(obj.data)
00998 self.extrusion = self.get_extrusion(obj.data)
00999
01000
01001
01002
01003
01004 def get_loc(self, data):
01005 """Gets the center location for circle type objects.
01006
01007 Circles have a single coord location.
01008 """
01009 loc = [0, 0, 0]
01010 for item in data:
01011 if item[0] == 10:
01012 loc[0] = item[1]
01013 elif item[0] == 20:
01014 loc[1] = item[1]
01015 elif item[0] == 30:
01016 loc[2] = item[1]
01017 return loc
01018
01019
01020
01021 def get_scale(self, data):
01022 """Gets the x/y/z scale factor for the block.
01023 """
01024 scale = [1, 1, 1]
01025 for item in data:
01026 if item[0] == 41:
01027 scale[0] = item[1]
01028 elif item[0] == 42:
01029 scale[1] = item[1]
01030 elif item[0] == 43:
01031 scale[2] = item[1]
01032 return scale
01033
01034
01035
01036 def get_array(self, data):
01037 """Returns the pair (row number, row spacing), (column number, column spacing)."""
01038 columns = 1
01039 rows = 1
01040 cspace = 0
01041 rspace = 0
01042 for item in data:
01043 if item[0] == 70:
01044 columns = item[1]
01045 elif item[0] == 71:
01046 rows = item[1]
01047 if item[0] == 44:
01048 cspace = item[1]
01049 elif item[0] == 45:
01050 rspace = item[1]
01051 return (rows, rspace), (columns, cspace)
01052
01053
01054
01055 def get_extrusion(self, data):
01056 """Find the axis of extrusion.
01057
01058 Used to get the objects Object Coordinate System (ocs).
01059 """
01060 vec = [0,0,1]
01061 for item in data:
01062 if item[0] == 210:
01063 vec[0] = item[1]
01064 elif item[0] == 220:
01065 vec[1] = item[1]
01066 elif item[0] == 230:
01067 vec[2] = item[1]
01068 return vec
01069
01070
01071 def __repr__(self):
01072 return "%s: layer - %s, block - %s" %(self.__class__.__name__, self.layer, self.block)
01073
01074
01075
01076
01077 class Ellipse:
01078 """Class for objects representing dxf ellipses."""
01079
01080 def __init__(self, obj):
01081 """Expects an entity object of type ellipse as input."""
01082 if not obj.type == 'ellipse':
01083 raise TypeError, "Wrong type %s for ellipse object!" %obj.type
01084 self.type = obj.type
01085 self.data = obj.data[:]
01086
01087
01088 self.ratio = obj.get_type(40)[0]
01089 self.start_angle = obj.get_type(41)[0]
01090 self.end_angle = obj.get_type(42)[0]
01091
01092
01093 self.space = obj.get_type(67)
01094 if self.space:
01095 self.space = self.space[0]
01096 else:
01097 self.space = 0
01098
01099 self.color_index = obj.get_type(62)
01100 if self.color_index:
01101 self.color_index = self.color_index[0]
01102 else:
01103 self.color_index = BYLAYER
01104
01105 discard, self.layer, discard_index = get_layer(obj.data)
01106 del obj.data[discard_index]
01107 self.loc = self.get_loc(obj.data)
01108 self.major = self.get_major(obj.data)
01109 self.extrusion = self.get_extrusion(obj.data)
01110 self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2)
01111
01112
01113
01114
01115 def get_loc(self, data):
01116 """Gets the center location for arc type objects.
01117
01118 Arcs have a single coord location.
01119 """
01120 loc = [0, 0, 0]
01121 for item in data:
01122 if item[0] == 10:
01123 loc[0] = item[1]
01124 elif item[0] == 20:
01125 loc[1] = item[1]
01126 elif item[0] == 30:
01127 loc[2] = item[1]
01128 return loc
01129
01130
01131
01132 def get_major(self, data):
01133 """Gets the major axis for ellipse type objects.
01134
01135 The ellipse major axis defines the rotation of the ellipse and its radius.
01136 """
01137 loc = [0, 0, 0]
01138 for item in data:
01139 if item[0] == 11:
01140 loc[0] = item[1]
01141 elif item[0] == 21:
01142 loc[1] = item[1]
01143 elif item[0] == 31:
01144 loc[2] = item[1]
01145 return loc
01146
01147
01148
01149 def get_extrusion(self, data):
01150 """Find the axis of extrusion.
01151
01152 Used to get the objects Object Coordinate System (ocs).
01153 """
01154 vec = [0,0,1]
01155 for item in data:
01156 if item[0] == 210:
01157 vec[0] = item[1]
01158 elif item[0] == 220:
01159 vec[1] = item[1]
01160 elif item[0] == 230:
01161 vec[2] = item[1]
01162 return vec
01163
01164
01165 def __repr__(self):
01166 return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
01167
01168
01169
01170 class Face:
01171 """Class for objects representing dxf 3d faces."""
01172
01173 def __init__(self, obj):
01174 """Expects an entity object of type 3dfaceplot as input."""
01175 if not obj.type == '3dface':
01176 raise TypeError, "Wrong type %s for 3dface object!" %obj.type
01177 self.type = obj.type
01178 self.data = obj.data[:]
01179
01180
01181 self.space = obj.get_type(67)
01182 if self.space:
01183 self.space = self.space[0]
01184 else:
01185 self.space = 0
01186
01187 self.color_index = obj.get_type(62)
01188 if self.color_index:
01189 self.color_index = self.color_index[0]
01190 else:
01191 self.color_index = BYLAYER
01192
01193 discard, self.layer, discard_index = get_layer(obj.data)
01194 del obj.data[discard_index]
01195 self.points = self.get_points(obj.data)
01196
01197
01198
01199
01200 def get_points(self, data):
01201 """Gets 3-4 points for a 3d face type object.
01202
01203 Faces have three or optionally four verts.
01204 """
01205
01206 a = [0, 0, 0]
01207 b = [0, 0, 0]
01208 c = [0, 0, 0]
01209 d = False
01210 for item in data:
01211
01212 if item[0] == 10:
01213 a[0] = item[1]
01214 elif item[0] == 20:
01215 a[1] = item[1]
01216 elif item[0] == 30:
01217 a[2] = item[1]
01218
01219 elif item[0] == 11:
01220 b[0] = item[1]
01221 elif item[0] == 21:
01222 b[1] = item[1]
01223 elif item[0] == 31:
01224 b[2] = item[1]
01225
01226 elif item[0] == 12:
01227 c[0] = item[1]
01228 elif item[0] == 22:
01229 c[1] = item[1]
01230 elif item[0] == 32:
01231 c[2] = item[1]
01232
01233 elif item[0] == 13:
01234 d = [0, 0, 0]
01235 d[0] = item[1]
01236 elif item[0] == 23:
01237 d[1] = item[1]
01238 elif item[0] == 33:
01239 d[2] = item[1]
01240 out = [a,b,c]
01241 if d:
01242 out.append(d)
01243 return out
01244
01245
01246 def __repr__(self):
01247 return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
01248
01249
01250 def get_name(data):
01251 """Get the name of an object from its object data.
01252
01253 Returns a pair of (data_item, name) where data_item is the list entry where the name was found
01254 (the data_item can be used to remove the entry from the object data). Be sure to check
01255 name not None before using the returned values!
01256 """
01257 value = None
01258 for i, item in enumerate(data):
01259 if item[0] == 2:
01260 value = item[1]
01261 break
01262 return item, value, i
01263
01264 def get_layer(data):
01265 """Expects object data as input.
01266
01267 Returns (entry, layer_name, entry_index) where entry is the data item that provided the layer name.
01268 """
01269 value = None
01270 for i, item in enumerate(data):
01271 if item[0] == 8:
01272 value = item[1]
01273 break
01274 return item, value, i
01275
01276
01277
01278 type_map = {
01279 'line':Line,
01280 'lwpolyline':LWpolyline,
01281 'text':Text,
01282 'mtext':Mtext,
01283 'circle':Circle,
01284 'arc':Arc,
01285 'layer':Layer,
01286 'block_record':BlockRecord,
01287 'block':Block,
01288 'insert':Insert,
01289 'ellipse':Ellipse,
01290 '3dface':Face
01291 }
01292
01293 def objectify(data):
01294 """Expects a section type object's data as input.
01295
01296 Maps object data to the correct object type.
01297 """
01298 objects = []
01299 known_types = type_map.keys()
01300 index = 0
01301 while index < len(data):
01302 item = data[index]
01303 if type(item) != list and item.type in known_types:
01304
01305 objects.append(type_map[item.type](item))
01306 elif type(item) != list and item.type == 'table':
01307 item.data = objectify(item.data)
01308 objects.append(item)
01309 elif type(item) != list and item.type == 'polyline':
01310 pline = Polyline(item)
01311 while 1:
01312 index += 1
01313 item = data[index]
01314 if item.type == 'vertex':
01315 v = Vertex(item)
01316 pline.points.append(v)
01317 elif item.type == 'seqend':
01318 break
01319 else:
01320 print "Error: non-vertex found before seqend!"
01321 index -= 1
01322 break
01323 objects.append(pline)
01324 else:
01325
01326 objects.append(item)
01327 index += 1
01328 return objects
01329 if __name__ == "__main__":
01330 print "No example yet!"