diff options
author | Remigiusz Fiedler <migius@gmx.net> | 2008-05-08 19:58:00 +0400 |
---|---|---|
committer | Remigiusz Fiedler <migius@gmx.net> | 2008-05-08 19:58:00 +0400 |
commit | 3faf12770700a87eec348868b3c53d3080b6739e (patch) | |
tree | 60f907c675404d5915993241ad8271fb52e283a1 /release | |
parent | e71a6bd79ea1982dbed05468cc98def7093e9228 (diff) |
DXF-importer prepared for ProE files, which are outside of DXF-specification.
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/bpymodules/dxfReader.py | 619 |
1 files changed, 309 insertions, 310 deletions
diff --git a/release/scripts/bpymodules/dxfReader.py b/release/scripts/bpymodules/dxfReader.py index d4a39cf63d6..df4ebc309e4 100644 --- a/release/scripts/bpymodules/dxfReader.py +++ b/release/scripts/bpymodules/dxfReader.py @@ -1,11 +1,12 @@ """This module provides a function for reading dxf files and parsing them into a useful tree of objects and data. - The convert function is called by the readDXF fuction to convert dxf strings into the correct data based - on their type code. readDXF expects a (full path) file name as input. + The convert function is called by the readDXF fuction to convert dxf strings into the correct data based + on their type code. readDXF expects a (full path) file name as input. """ # -------------------------------------------------------------------------- # DXF Reader v0.9 by Ed Blake (AKA Kitsu) +# 2008.05.08 modif.def convert() by Remigiusz Fiedler (AKA migius) # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -30,215 +31,215 @@ #from dxfImportObjects import * class Object: - """Empty container class for dxf objects""" - - def __init__(self, _type='', block=False): - """_type expects a string value.""" - self.type = _type - self.name = '' - self.data = [] - - def __str__(self): - if self.name: - return self.name - else: - return self.type - - def __repr__(self): - return str(self.data) - - def get_type(self, kind=''): - """Despite the name, this method actually returns all objects of type 'kind' from self.data.""" - if type: - objects = [] - for item in self.data: - if type(item) != list and item.type == kind: - # we want this type of object - objects.append(item) - elif type(item) == list and item[0] == kind: - # we want this type of data - objects.append(item[1]) - return objects - + """Empty container class for dxf objects""" + + def __init__(self, _type='', block=False): + """_type expects a string value.""" + self.type = _type + self.name = '' + self.data = [] + + def __str__(self): + if self.name: + return self.name + else: + return self.type + + def __repr__(self): + return str(self.data) + + def get_type(self, kind=''): + """Despite the name, this method actually returns all objects of type 'kind' from self.data.""" + if type: + objects = [] + for item in self.data: + if type(item) != list and item.type == kind: + # we want this type of object + objects.append(item) + elif type(item) == list and item[0] == kind: + # we want this type of data + objects.append(item[1]) + return objects + class InitializationError(Exception): pass class StateMachine: - """(finite) State Machine from the great David Mertz's great Charming Python article.""" - - def __init__(self): - self.handlers = [] - self.startState = None - self.endStates = [] - - def add_state(self, handler, end_state=0): - """All states and handlers are functions which return - a state and a cargo.""" - self.handlers.append(handler) - if end_state: - self.endStates.append(handler) - def set_start(self, handler): - """Sets the starting handler function.""" - self.startState = handler - - - def run(self, cargo=None): - if not self.startState: - raise InitializationError,\ - "must call .set_start() before .run()" - if not self.endStates: - raise InitializationError, \ - "at least one state must be an end_state" - handler = self.startState - while 1: - (newState, cargo) = handler(cargo) - #print cargo - if newState in self.endStates: - return newState(cargo) - #break - elif newState not in self.handlers: - raise RuntimeError, "Invalid target %s" % newState - else: - handler = newState + """(finite) State Machine from the great David Mertz's great Charming Python article.""" + + def __init__(self): + self.handlers = [] + self.startState = None + self.endStates = [] + + def add_state(self, handler, end_state=0): + """All states and handlers are functions which return + a state and a cargo.""" + self.handlers.append(handler) + if end_state: + self.endStates.append(handler) + def set_start(self, handler): + """Sets the starting handler function.""" + self.startState = handler + + + def run(self, cargo=None): + if not self.startState: + raise InitializationError,\ + "must call .set_start() before .run()" + if not self.endStates: + raise InitializationError, \ + "at least one state must be an end_state" + handler = self.startState + while 1: + (newState, cargo) = handler(cargo) + #print cargo + if newState in self.endStates: + return newState(cargo) + #break + elif newState not in self.handlers: + raise RuntimeError, "Invalid target %s" % newState + else: + handler = newState def get_name(data): - """Get the name of an object from its object data. - - Returns a pair of (data_item, name) where data_item is the list entry where the name was found - (the data_item can be used to remove the entry from the object data). Be sure to check - name not None before using the returned values! - """ - value = None - for item in data: - if item[0] == 2: - value = item[1] - break - return item, value + """Get the name of an object from its object data. + + Returns a pair of (data_item, name) where data_item is the list entry where the name was found + (the data_item can be used to remove the entry from the object data). Be sure to check + name not None before using the returned values! + """ + value = None + for item in data: + if item[0] == 2: + value = item[1] + break + return item, value def get_layer(data): - """Expects object data as input. - - Returns (entry, layer_name) where entry is the data item that provided the layer name. - """ - value = None - for item in data: - if item[0] == 8: - value = item[1] - break - return item, value + """Expects object data as input. + + Returns (entry, layer_name) where entry is the data item that provided the layer name. + """ + value = None + for item in data: + if item[0] == 8: + value = item[1] + break + return item, value def convert(code, value): - """Convert a string to the correct Python type based on its dxf code. - code types: - ints = 60-79, 170-179, 270-289, 370-389, 400-409, 1060-1070 - longs = 90-99, 420-429, 440-459, 1071 - floats = 10-39, 40-59, 110-139, 140-149, 210-239, 460-469, 1010-1059 - hex = 105, 310-379, 390-399 - strings = 0-9, 100, 102, 300-309, 410-419, 430-439, 470-479, 999, 1000-1009 - """ - if 59 < code < 80 or 169 < code < 180 or 269 < code < 290 or 369 < code < 390 or 399 < code < 410 or 1059 < code < 1071: - value = int(value) - elif 89 < code < 100 or 419 < code < 430 or 439 < code < 460 or code == 1071: - value = long(value) - elif 9 < code < 60 or 109 < code < 150 or 209 < code < 240 or 459 < code < 470 or 1009 < code < 1060: - value = float(value) - elif code == 105 or 309 < code < 380 or 389 < code < 400: - value = int(value, 16) # should be left as string? - else: # it's already a string so do nothing - pass - return value + """Convert a string to the correct Python type based on its dxf code. + code types: + ints = 60-79, 170-179, 270-289, 370-389, 400-409, 1060-1070 + longs = 90-99, 420-429, 440-459, 1071 + floats = 10-39, 40-59, 110-139, 140-149, 210-239, 460-469, 1010-1059 + hex = 105, 310-379, 390-399 + strings = 0-9, 100, 102, 300-309, 410-419, 430-439, 470-479, 999, 1000-1009 + """ + if 59 < code < 80 or 169 < code < 180 or 269 < code < 290 or 369 < code < 390 or 399 < code < 410 or 1059 < code < 1071: + value = int(float(value)) + elif 89 < code < 100 or 419 < code < 430 or 439 < code < 460 or code == 1071: + value = long(float(value)) + elif 9 < code < 60 or 109 < code < 150 or 209 < code < 240 or 459 < code < 470 or 1009 < code < 1060: + value = float(value) + elif code == 105 or 309 < code < 380 or 389 < code < 400: + value = int(value, 16) # should be left as string? + else: # it's already a string so do nothing + pass + return value def findObject(infile, kind=''): - """Finds the next occurance of an object.""" - obj = False - while 1: - line = infile.readline() - if not line: # readline returns '' at eof - return False - if not obj: # We're still looking for our object code - if line.lower().strip() == '0': - obj = True # found it - else: # we are in an object definition - if kind: # if we're looking for a particular kind - if line.lower().strip() == kind: - obj = Object(line.lower().strip()) - break - else: # otherwise take anything non-numeric - if line.lower().strip() not in string.digits: - obj = Object(line.lower().strip()) - break - obj = False # whether we found one or not it's time to start over - return obj + """Finds the next occurance of an object.""" + obj = False + while 1: + line = infile.readline() + if not line: # readline returns '' at eof + return False + if not obj: # We're still looking for our object code + if line.lower().strip() == '0': + obj = True # found it + else: # we are in an object definition + if kind: # if we're looking for a particular kind + if line.lower().strip() == kind: + obj = Object(line.lower().strip()) + break + else: # otherwise take anything non-numeric + if line.lower().strip() not in string.digits: + obj = Object(line.lower().strip()) + break + obj = False # whether we found one or not it's time to start over + return obj def handleObject(infile): - """Add data to an object until end of object is found.""" - line = infile.readline() - if line.lower().strip() == 'section': - return 'section' # this would be a problem - elif line.lower().strip() == 'endsec': - return 'endsec' # this means we are done with a section - else: # add data to the object until we find a new object - obj = Object(line.lower().strip()) - obj.name = obj.type - done = False - data = [] - while not done: - line = infile.readline() - if not data: - if line.lower().strip() == '0': - #we've found an object, time to return - return obj - else: - # first part is always an int - data.append(int(line.lower().strip())) - else: - data.append(convert(data[0], line.strip())) - obj.data.append(data) - data = [] + """Add data to an object until end of object is found.""" + line = infile.readline() + if line.lower().strip() == 'section': + return 'section' # this would be a problem + elif line.lower().strip() == 'endsec': + return 'endsec' # this means we are done with a section + else: # add data to the object until we find a new object + obj = Object(line.lower().strip()) + obj.name = obj.type + done = False + data = [] + while not done: + line = infile.readline() + if not data: + if line.lower().strip() == '0': + #we've found an object, time to return + return obj + else: + # first part is always an int + data.append(int(line.lower().strip())) + else: + data.append(convert(data[0], line.strip())) + obj.data.append(data) + data = [] def handleTable(table, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(table.data) - if name: # We should always find a name - table.data.remove(item) - table.name = name.lower() - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'table': - print "Warning: previous table not closed!" - return table - elif obj.type == 'endtab': - return table # this means we are done with the table - else: # add objects to the table until one of the above is found - table.data.append(obj) - - - + """Special handler for dealing with nested table objects.""" + item, name = get_name(table.data) + if name: # We should always find a name + table.data.remove(item) + table.name = name.lower() + # This next bit is from handleObject + # handleObject should be generalized to work with any section like object + while 1: + obj = handleObject(infile) + if obj.type == 'table': + print "Warning: previous table not closed!" + return table + elif obj.type == 'endtab': + return table # this means we are done with the table + else: # add objects to the table until one of the above is found + table.data.append(obj) + + + def handleBlock(block, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(block.data) - if name: # We should always find a name - block.data.remove(item) - block.name = name - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'block': - print "Warning: previous block not closed!" - return block - elif obj.type == 'endblk': - return block # this means we are done with the table - else: # add objects to the table until one of the above is found - block.data.append(obj) - - - + """Special handler for dealing with nested table objects.""" + item, name = get_name(block.data) + if name: # We should always find a name + block.data.remove(item) + block.name = name + # This next bit is from handleObject + # handleObject should be generalized to work with any section like object + while 1: + obj = handleObject(infile) + if obj.type == 'block': + print "Warning: previous block not closed!" + return block + elif obj.type == 'endblk': + return block # this means we are done with the table + else: # add objects to the table until one of the above is found + block.data.append(obj) + + + """These are the states/functions used in the State Machine. states: @@ -250,133 +251,131 @@ states: """ def start(cargo): - """Expects the infile as cargo, initializes the cargo.""" - #print "Entering start state!" - infile = cargo - drawing = Object('drawing') - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return error, (infile, "Failed to find any sections!") + """Expects the infile as cargo, initializes the cargo.""" + #print "Entering start state!" + infile = cargo + drawing = Object('drawing') + section = findObject(infile, 'section') + if section: + return start_section, (infile, drawing, section) + else: + return error, (infile, "Failed to find any sections!") def start_section(cargo): - """Expects [infile, drawing, section] as cargo, builds a nested section object.""" - #print "Entering start_section state!" - infile = cargo[0] - drawing = cargo[1] - section = cargo[2] - # read each line, if it is an object declaration go to object mode - # otherwise create a [index, data] pair and add it to the sections data. - done = False - data = [] - while not done: - line = infile.readline() - - if not data: # if we haven't found a dxf code yet - if line.lower().strip() == '0': - # we've found an object - while 1: # no way out unless we find an end section or a new section - obj = handleObject(infile) - if obj == 'section': # shouldn't happen - print "Warning: failed to close previous section!" - return end_section, (infile, drawing) - elif obj == 'endsec': # This section is over, look for the next - drawing.data.append(section) - return end_section, (infile, drawing) - elif obj.type == 'table': # tables are collections of data - obj = handleTable(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - elif obj.type == 'block': # the same is true of blocks - obj = handleBlock(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - else: # found another sub-object - section.data.append(obj) - else: - data.append(int(line.lower().strip())) - else: # we have our code, now we just need to convert the data and add it to our list. - data.append(convert(data[0], line.strip())) - section.data.append(data) - data = [] + """Expects [infile, drawing, section] as cargo, builds a nested section object.""" + #print "Entering start_section state!" + infile = cargo[0] + drawing = cargo[1] + section = cargo[2] + # read each line, if it is an object declaration go to object mode + # otherwise create a [index, data] pair and add it to the sections data. + done = False + data = [] + while not done: + line = infile.readline() + + if not data: # if we haven't found a dxf code yet + if line.lower().strip() == '0': + # we've found an object + while 1: # no way out unless we find an end section or a new section + obj = handleObject(infile) + if obj == 'section': # shouldn't happen + print "Warning: failed to close previous section!" + return end_section, (infile, drawing) + elif obj == 'endsec': # This section is over, look for the next + drawing.data.append(section) + return end_section, (infile, drawing) + elif obj.type == 'table': # tables are collections of data + obj = handleTable(obj, infile) # we need to find all there contents + section.data.append(obj) # before moving on + elif obj.type == 'block': # the same is true of blocks + obj = handleBlock(obj, infile) # we need to find all there contents + section.data.append(obj) # before moving on + else: # found another sub-object + section.data.append(obj) + else: + data.append(int(line.lower().strip())) + else: # we have our code, now we just need to convert the data and add it to our list. + data.append(convert(data[0], line.strip())) + section.data.append(data) + data = [] def end_section(cargo): - """Expects (infile, drawing) as cargo, searches for next section.""" - #print "Entering end_section state!" - infile = cargo[0] - drawing = cargo[1] - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return end, (infile, drawing) + """Expects (infile, drawing) as cargo, searches for next section.""" + #print "Entering end_section state!" + infile = cargo[0] + drawing = cargo[1] + section = findObject(infile, 'section') + if section: + return start_section, (infile, drawing, section) + else: + return end, (infile, drawing) def end(cargo): - """Expects (infile, drawing) as cargo, called when eof has been reached.""" - #print "Entering end state!" - infile = cargo[0] - drawing = cargo[1] - #infile.close() - return drawing + """Expects (infile, drawing) as cargo, called when eof has been reached.""" + #print "Entering end state!" + infile = cargo[0] + drawing = cargo[1] + #infile.close() + return drawing def error(cargo): - """Expects a (infile, string) as cargo, called when there is an error during processing.""" - #print "Entering error state!" - infile = cargo[0] - err = cargo[1] - infile.close() - print "There has been an error:" - print err - return False + """Expects a (infile, string) as cargo, called when there is an error during processing.""" + #print "Entering error state!" + infile = cargo[0] + err = cargo[1] + infile.close() + print "There has been an error:" + print err + return False def readDXF(filename, objectify): - """Given a file name try to read it as a dxf file. - - Output is an object with the following structure - drawing - header - header data - classes - class data - tables - table data - blocks - block data - entities - entity data - objects - object data - where foo data is a list of sub-objects. True object data - is of the form [code, data]. -""" - infile = open(filename) - - sm = StateMachine() - sm.add_state(error, True) - sm.add_state(end, True) - sm.add_state(start_section) - sm.add_state(end_section) - sm.add_state(start) - sm.set_start(start) - try: - drawing = sm.run(infile) - if drawing: - drawing.name = filename - for obj in drawing.data: - item, name = get_name(obj.data) - if name: - obj.data.remove(item) - obj.name = name.lower() - setattr(drawing, name.lower(), obj) - # Call the objectify function to cast - # raw objects into the right types of object - obj.data = objectify(obj.data) - #print obj.name - finally: - infile.close() - return drawing -if __name__ == "__main__": - filename = r".\examples\block-test.dxf" - drawing = readDXF(filename) - for item in drawing.entities.data: - print item + """Given a file name try to read it as a dxf file. + Output is an object with the following structure + drawing + header + header data + classes + class data + tables + table data + blocks + block data + entities + entity data + objects + object data + where foo data is a list of sub-objects. True object data + is of the form [code, data]. +""" + infile = open(filename) + sm = StateMachine() + sm.add_state(error, True) + sm.add_state(end, True) + sm.add_state(start_section) + sm.add_state(end_section) + sm.add_state(start) + sm.set_start(start) + try: + drawing = sm.run(infile) + if drawing: + drawing.name = filename + for obj in drawing.data: + item, name = get_name(obj.data) + if name: + obj.data.remove(item) + obj.name = name.lower() + setattr(drawing, name.lower(), obj) + # Call the objectify function to cast + # raw objects into the right types of object + obj.data = objectify(obj.data) + #print obj.name + finally: + infile.close() + return drawing +if __name__ == "__main__": + filename = r".\examples\block-test.dxf" + drawing = readDXF(filename) + for item in drawing.entities.data: + print item |