Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/bpymodules/dxfReader.py')
-rw-r--r--release/scripts/bpymodules/dxfReader.py619
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