6060 get_resource ('dxf.json.template' )).items ()}
6161
6262
63- def get_key (blob , field , code ):
64- try :
65- line = blob [np .nonzero (blob [:, 1 ] == field )[0 ][0 ] + 1 ]
66- except IndexError :
67- return None
68- if line [0 ] == code :
69- try :
70- return int (line [1 ])
71- except ValueError :
72- return line [1 ]
73- else :
74- return None
75-
76-
7763def load_dxf (file_obj , ** kwargs ):
7864 """
7965 Load a DXF file to a dictionary containing vertices and
@@ -88,56 +74,6 @@ def load_dxf(file_obj, **kwargs):
8874 result: dict, keys are entities, vertices and metadata
8975 """
9076
91- def get_metadata ():
92- """
93- Get metadata from DXF objects section of the file.
94-
95- Returns
96- ----------
97- metadata : dict
98- Any available metadata stored in XRecord
99- """
100- metadata = {}
101- # save file version info
102- metadata ['ACADVER' ] = get_key (header_blob , '$ACADVER' , '1' )
103-
104- # get the section which contains objects in the DXF file
105- obj_start = np .nonzero (blob [:, 1 ] == 'OBJECTS' )[0 ]
106-
107- if len (obj_start ) == 0 :
108- return metadata
109- obj_start = obj_start [0 ]
110-
111- obj_end = endsec [np .searchsorted (endsec , obj_start )]
112- obj_blob = blob [obj_start :obj_end ]
113-
114- # the index of xrecords are one past the group code key
115- xrecords = np .nonzero ((
116- obj_blob == ['100' , 'ACDBXRECORD' ]).all (axis = 1 ))[0 ] + 1
117-
118- # if there are no XRecords return
119- if len (xrecords ) == 0 :
120- return metadata
121-
122- # resplit the file data without upper() to preserve case
123- blob_lower = np .array (str .splitlines (raw )).reshape ((- 1 , 2 ))
124- # newlines and split should never be effected by upper()
125- assert len (blob_lower ) == len (blob )
126-
127- # the likely exceptions are related to JSON decoding
128- try :
129- # loop through xrecords by group code
130- for code , data in blob_lower [obj_start :obj_end ][xrecords ]:
131- if code == str (XRECORD_METADATA ):
132- metadata .update (json .loads (data ))
133- # we could store xrecords in the else here
134- # but they have a lot of garbage so don't
135- # metadata['XRECORD_' + code] = data
136- except BaseException :
137- log .error ('failed to load metadata!' , exc_info = True )
138-
139- return metadata
140-
14177 def info (e ):
14278 """
14379 Pull metadata based on group code, and return as a dict.
@@ -367,7 +303,7 @@ def convert_bspline(e):
367303 # no converter to ASCII DXF available
368304 raise ValueError ('binary DXF not supported!' )
369305 else :
370- # convert to R14 ASCII DXF
306+ # convert binary DXF to R14 ASCII DXF
371307 raw = _teigha_convert (raw , extension = 'dxf' )
372308 else :
373309 # we've been passed bytes that don't have the
@@ -392,26 +328,30 @@ def convert_bspline(e):
392328 entity_end = endsec [np .searchsorted (endsec , entity_start )]
393329 entity_blob = blob [entity_start :entity_end ]
394330
395- # try to load path metadata from xrecords stored in DXF
396- try :
397- metadata = get_metadata ()
398- except BaseException :
399- log .error ('failed to extract metadata!' ,
400- exc_info = True )
401- metadata = {}
331+ # store some properties from the DXF header
332+ metadata = {'DXF_HEADER' : {}}
333+
334+ for key in ['$DIMSCALE' , '$DIMUNIT' , '$INSUNITS' , '$LUNITS' ]:
335+ value = get_key (header_blob ,
336+ key ,
337+ '70' )
338+ if value is not None :
339+ metadata ['DXF_HEADER' ][key ] = value
402340
403341 # store unit data pulled from the header of the DXF
404342 # prefer LUNITS over INSUNITS
405343 # I couldn't find a table for LUNITS values but they
406344 # look like they are 0- indexed versions of
407345 # the INSUNITS keys, so for now offset the key value
408- for offset , key in [(0 , '$INSUNITS ' ),
409- (- 1 , '$LUNITS ' )]:
346+ for offset , key in [(- 1 , '$LUNITS ' ),
347+ (0 , '$INSUNITS ' )]:
410348 # get the key from the header blob
411349 units = get_key (header_blob , key , '70' )
412350 # if it exists add the offset
413- if units is not None :
414- units += offset
351+ if units is None :
352+ continue
353+ metadata [key ] = units
354+ units += offset
415355 # if the key is in our list of units store it
416356 if units in _DXF_UNITS :
417357 metadata ['units' ] = _DXF_UNITS [units ]
@@ -498,7 +438,7 @@ def convert_bspline(e):
498438 return result
499439
500440
501- def export_dxf (path , include_metadata = False ):
441+ def export_dxf (path ):
502442 """
503443 Export a 2D path object to a DXF file
504444
@@ -667,28 +607,6 @@ def convert_generic(entity, vertices):
667607 """
668608 return convert_line (entity , vertices )
669609
670- def convert_metadata ():
671- """
672- Save path metadata as a DXF Xrecord object.
673- """
674- if (not include_metadata ) or len (path .metadata ) == 0 :
675- return ''
676- # dump metadata to compact JSON
677- # make sure there are no newlines to break DXF
678- # util.jsonify will be able to convert numpy arrays
679- as_json = util .jsonify (
680- path .metadata ,
681- separators = (',' , ':' )).replace ('\n ' , ' ' )
682-
683- # create an XRECORD for our use
684- xrecord = TEMPLATES ['xrecord' ].substitute ({
685- 'INDEX' : XRECORD_METADATA ,
686- 'DATA' : as_json })
687- # add the XRECORD to an objects section
688- result = TEMPLATES ['objects' ].substitute ({
689- 'OBJECTS' : xrecord })
690- return result
691-
692610 # make sure we're not losing a ton of
693611 # precision in the string conversion
694612 np .set_printoptions (precision = 12 )
@@ -717,12 +635,10 @@ def convert_metadata():
717635 entities = TEMPLATES ['entities' ].substitute ({
718636 'ENTITIES' : entities_str })
719637 footer = TEMPLATES ['footer' ].substitute ()
720- # metadata encoded as objects section
721- objects = convert_metadata ()
638+
722639 # filter out empty sections
723640 sections = [i for i in [header ,
724641 entities ,
725- objects ,
726642 footer ]
727643 if len (i ) > 0 ]
728644
@@ -759,6 +675,24 @@ def load_dwg(file_obj, **kwargs):
759675 return result
760676
761677
678+ def get_key (blob , field , code ):
679+ """
680+ Given a loaded (n, 2) blob and a field name
681+ get a value by code.
682+ """
683+ try :
684+ line = blob [np .nonzero (blob [:, 1 ] == field )[0 ][0 ] + 1 ]
685+ except IndexError :
686+ return None
687+ if line [0 ] == code :
688+ try :
689+ return int (line [1 ])
690+ except ValueError :
691+ return line [1 ]
692+ else :
693+ return None
694+
695+
762696def _teigha_convert (data , extension = 'dwg' ):
763697 """
764698 Convert any DXF/DWG to R14 ASCII DXF using Teigha Converter.
@@ -836,11 +770,13 @@ def _teigha_convert(data, extension='dwg'):
836770
837771
838772# the DWG to DXF converter
773+ # they renamed it at some point but it is the same
839774for _name in ['ODAFileConverter' ,
840775 'TeighaFileConverter' ]:
841776 _teigha = find_executable (_name )
842777 if _teigha is not None :
843778 break
779+
844780# suppress X11 output
845781_xvfb_run = find_executable ('xvfb-run' )
846782
0 commit comments