# # Copyright (c) 2003 Art Haas # # This file is part of PythonCAD. # # PythonCAD is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PythonCAD is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PythonCAD; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # simple DXF file reader # import sys def read_dxf(handle): handle.seek(0,0) while True: _code, _data = get_group(handle) if _code == 0 and _data == 'EOF': break if _code == 0 and _data == 'SECTION': _secdata = read_section(handle) def read_section(handle): _sdata = None while True: _code, _data = get_group(handle) if _code == 0 and _data == 'EOF': break if _code != 2: raise ValueError, "Expected code 2; got %d" % _code _sdata = None if _data == 'HEADER': _sdata = read_header(handle) print "HEADER data:" elif _data == 'CLASSES': _sdata = read_classes(handle) print "CLASSES data:" elif _data == 'TABLES': _sdata = read_tables(handle) print "TABLES data:" elif _data == 'BLOCKS': _sdata = read_blocks(handle) print "BLOCKS data:" elif _data == 'ENTITIES': _sdata = read_entities(handle) print "ENTITY data:" elif _data == 'OBJECTS': _sdata = read_objects(handle) print "OBJECTS data:" else: while True: _code, _data = get_group(handle) if _code == 0 and (_data == 'ENDSEC' or _data == 'EOF'): break if _sdata is not None: _keys = _sdata.keys() _keys.sort() for _key in _keys: print "%s -> %s" % (_key, str(_sdata[_key])) break return _sdata def read_header(handle): _hmap = {} _code, _data = get_group(handle) while True: if _code == 0 and (_data == 'EOF' or _data == 'ENDSEC'): break if _code != 9: raise ValueError, "Expected code 9; got %d" % _code while True: _var = _data[1:] _dlist = [] while True: _code, _data = get_group(handle) if _code == 0 or _code == 9: break _dlist.append(_data) if len(_dlist) == 1: _hmap[_var] = _dlist[0] else: _hmap[_var] = tuple(_dlist) if _code == 0: break return _hmap def read_classes(handle): _cmap = {} while True: _code, _r0 = get_group(handle) if _code != 0: raise ValueError, "Expected code 0, got %d" % _code if _r0 == 'EOF' or _r0 == 'ENDSEC': break _code, _r1 = get_group(handle) if _code != 1: raise ValueError, "Expected code 1, got %d" % _code _code, _r2 = get_group(handle) if _code != 2: raise ValueError, "Expected code 2, got %d" % _code _code, _r3 = get_group(handle) if _code != 3: raise ValueError, "Expected code 3, got %d" % _code _code, _r90 = get_group(handle) if _code != 90: raise ValueError, "Expected code 90, got %d" % _code _code, _r280 = get_group(handle) if _code != 280: raise ValueError, "Expected code 280, got %d" % _code _code, _r281 = get_group(handle) if _code != 281: raise ValueError, "Expected code 281, got %d" % _code _cmap[_r1] = (_r2, _r3, _r90, _r280, _r281) return _cmap def read_tables(handle): _tmap = {} while True: _code, _r0 = get_group(handle) if _code == 0 and (_r0 == 'EOF' or _r0 == 'ENDSEC'): break if _code == 0 and _r0 == 'TABLE': _code, _name = get_group(handle) if _code != 2: raise ValueError, "Expected code 2 for table name: %d" % _code _tdata = [] while True: _code, _val = get_group(handle) if _code == 0 and _val == 'ENDTAB': break _tdata.append((_code, _val)) _tmap[_name] = _tdata return _tmap def read_blocks(handle): _bmap = {} _i = 0 _code, _val = get_group(handle) while True: if _code != 0: raise ValueError, "Expected code 0; got %d" % _code if _val == 'EOF' or _val == 'ENDSEC': break if _val != 'BLOCK': raise ValueError, "Expected BLOCK, got " + str(_val) _bdata = [] while True: _code, _val = get_group(handle) if _code == 0 and _val == 'ENDBLK': break _bdata.append((_code, _val)) _ebdata = [] while True: _code, _val = get_group(handle) if _code == 0 and (_val == 'BLOCK' or _val == 'ENDSEC'): break _ebdata.append((_code, _val)) _bmap[_i] = _bdata + _ebdata _i = _i + 1 return _bmap def read_entities(handle): _emap = {} _i = 0 _code, _val = get_group(handle) while True: if _code != 0: raise ValueError, "Expected code 0; got %d" % _code if _val == 'EOF' or _val == 'ENDSEC': break _edata = [] _edata.append((_code, _val)) # entity type is _val while True: _code, _val = get_group(handle) if _code == 0: # either next entity or end of section break _edata.append((_code, _val)) _emap[_i] = _edata _i = _i + 1 return _emap def read_objects(handle): _omap = {} _i = 0 _code, _val = get_group(handle) while True: if _code != 0: raise ValueError, "Expected code 0: got %d" % _code if _val == 'EOF' or _val == 'ENDSEC': break _odata = [] _odata.append((_code, _val)) # object type is _val while True: _code, _val = get_group(handle) if _code == 0: # either next object or end of section break _odata.append((_code, _val)) _omap[_i] = _odata _i = _i + 1 return _omap def get_group(handle): _code = int(handle.readline()) _dfun = get_data_type(_code) _data = _dfun(handle.readline()) return _code, _data def string_data(text): return text.strip() def float_data(text): return float(text) def int_data(text): return int(text) def unicode_data(text): return unicode(text.strip()) def handle_data(text): return int(text.strip(), 16) # fixme def hex_data(text): return int(text.strip(), 16) # ??? def bin_data(text): _str = text.strip() _bytes = [] if not len(_str) % 2: # even length -> good data ... for _i in range(0, len(_str), 2): _bytes.append(chr(int(_str[_i:_i+2], 16))) return _bytes def bool_data(text): _btext = text.strip() if _btext == '0': _flag = False elif _btext == '1': _flag = True else: raise ValueError, "Unexpected boolean data string: %s" % _btext return _flag def get_data_type(code): if (0 <= code <= 9): _dfun = string_data elif (10 <= code <= 59): _dfun = float_data elif (60 <= code <= 79): _dfun = int_data # 16-bit int elif (90 <= code <= 99): _dfun = int_data # 32-bit int elif (code == 100): _dfun = unicode_data elif (code == 102): _dfun = unicode_data elif (code == 105): _dfun = handle_data elif (110 <= code <= 139): _dfun = float_data # not in dxf spec elif (140 <= code <= 149): # says 147 in dxf spec _dfun = float_data elif (170 <= code <= 179): # says 175 in dxf spec _dfun = int_data # 16-bit int elif (270 <= code <= 279): _dfun = int_data # not in dxf spec elif (280 <= code <= 289): _dfun = int_data # 8-bit int elif (290 <= code <= 299): _dfun = bool_data elif (300 <= code <= 309): _dfun = string_data elif (310 <= code <= 319): _dfun = bin_data elif (320 <= code <= 329): _dfun = handle_data elif (330 <= code <= 369): _dfun = hex_data elif (370 <= code <= 379): _dfun = int_data # 8-bit int elif (380 <= code <= 389): _dfun = int_data # 8-bit int elif (390 <= code <= 399): _dfun = handle_data elif (400 <= code <= 409): _dfun = int_data # 16-bit int elif (410 <= code <= 419): _dfun = string_data elif (code == 999): _dfun = string_data # comment elif (1000 <= code <= 1009): _dfun = string_data elif (1010 <= code <= 1059): _dfun = float_data elif (1060 <= code <= 1070): _dfun = int_data # 16-bit int elif (code == 1071): _dfun = int_data # 32-bit int else: raise ValueError, "Unexpected code: %d" % code return _dfun if __name__ == '__main__': if len(sys.argv) < 2: print "usage: dxf.py filename" sys.exit(1) try: _fh = file(sys.argv[1]) except: print "failed to open '%s'. Exiting ..." % sys.argv[1] sys.exit(1) read_dxf(_fh) _fh.close()