From ahaas at airmail.net Fri Oct 3 12:09:39 2003 From: ahaas at airmail.net (Art Haas) Date: Fri Oct 3 12:11:01 2003 Subject: [PythonCAD] Improved DWG Reader Message-ID: <20031003160939.GA18218@artsapartment.org> Hi. After several fits and starts I've finished enough of the next iteration of the DWG reader that I'm making it available for testing. This version is currently set up for reading just R15 file formats; I'll be working on beating the R13/R14 reader into shape shortly. The new DWG reader is structured like this: dwgbase.py: Class definition for Dwg class, file entities, and common routines for version-specific readers. dwg15.py: R15 file reading functions The 'dwg.py' file will be renamed to 'dwg1314.py'. The 'dwg12.py' will be adjusted to fit in the layout after some feedback about the new layout is obtained. I'm not sold on the name 'dwgbase.py' yet, so that may change, but I think I like the way things are laid out with regards to the approach of reading DWG files. So, how does this beastie work? Like this ... $ python >>> import dwgbase >>> dwg = dwgbase.Dwg("/path/to/the/dwg/file.dwg") [ ... right now 'file.dwg' must be an R15 file - that will change once once the other readers are converted ... ] >>> keys = dwg.getHeaderKeys() [ ... retrieve all the header variables from the file and store them in the dwg object. The value of each variable can be extracted like so ... ] >>> dwg.getHeader('DIMSZ') 1.0 >>> dwg.getHeader('LTSCALE') 10.0 [ ... etc, etc, etc ...] >>> keys = dwg.getClassKeys() [ ... retrieve the class key info in the file. These keys are currently integer values. The class data is needed for reading the objects in the file, so let's move on to that ... ] >>> objs = dwg.getObjects() [ ... read all(*) the objects in the file and store them in a list. Let's pretend we have 100 objects ... ] >>> objs[0].getType() 27 [ ... this is a point object - see the OpenDWG spec ... ] >>> objs[0].getHandle() (0, 2, 5, 30) [ ... or something similiar - remember this is pretend :-) ... ] >>> objs[0].getEntityKeys() ['point', 'thickness', 'extrusion', 'x_axis_angle'] [ ... these are the entity specific values ... ] >>> objs[0].getEntityData('point') (0.0, 1.0, 0.5) [ ... the point's coordinates ... ] >>> objs[0].getEntityData('extrusion') (0.0, 0.0, 1.0) [ ... the extrusion value ... ] If you're wondering what "all(*)" meant, remember that some of the entities are not completely described in the OpenDWG spec, and there are a few entities omitted from the spec that are appearing in drawings I've been sent. The reader does the best it can but there are some omissions. Now lets pretend that objs[50] is a circle at (40, 20) with a radius of 14.25: >>> objs[50].getType() 18 [ ... see the OpenDWG specs ... ] >>> objs[50].getEntityKeys() [ 'center', 'radius', 'thickness', 'extrusion' ] >>> objs[50].getEntityData('center') (40.0, 20.0, 0.0) >>> objs[50].getEntityData('radius') 14.25 The above gives you an idea of how things work. The various entity-specific fields are listed with a getEntityKeys() call, then each field can be obtained with a getEntityData() call. Instead of using DXF codes as the keys I chose to use descriptive strings because, well, they are descriptive. It is clearer to figure out this ... getEntityData('radius') ... than something like ... getEntityData(40) The code is a short of documentation now, so you'll have to read it a bit if you want to play with it. In the case of the 'Dwg' class, methods that start with 'get' are free to be used, and methods starting with '_set' are meant for use only within the reader code. For the class repreenting the objects in the file, the same restriction holds, but these objects have more 'get/_set' methods. I think this is a design flaw that will probably be amended in the next iteration. To recap: import dwgbase dwg = dwgbase.Dwg("/path/to/file.dwg") headers = dwg.getHeaderKeys() classes = dwg.getClassKeys() objects = dwg.getObjects() The 'Dwg' class also has methods for retrieving the image data that R13, R14, and R15 files may have stored ... bmpimg = dwg.getImageData('BMP') # could return None wmfimg = dwg.getImageData('WMF') # could return None These methods need testing as I haven't tried to do anything with them yet. For each object in the 'objects' list above the following methods will probably be used the most ... obj = objects[0] # pick one ... type = obj.getType() handle = obj.getHandle() keys = obj.getEntityKeys() val = obj.getEntityData('foo') # one of the valid entity keys ... The 'dwg15.py' file is somewhat messy now due to this conversion. It will be cleaned up in due time. The immediate goal is to provide a usable interface for extracting the drawing info stored in the DWG file so please let me know what you think of the means I've provided so far. If you find some potential method call missing please provide feedback. While working on this conversion I found and fixed a number of bugs in the R15 reader, and also found that there are at least two entity types not described in the OpenDWG spec that appear in some of the drawings I've been sent. The DXF info I have called 'AutoCAD 2000 DXF Reference' lists several entitys that the OpenDWG spec omits (i.e. ARCALIGNEDTEXT) so maybe someone can create a simple drawing with one or two of these entities in both DWG and DXF formats and we can try to figure out the bit layout in the DWG file. Congrats if you've made it this far through this message ... :-) Those people willing to test this can send me an e-mail and I'll mail off the files to you. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From michael at themontagnes.com Fri Oct 3 12:20:36 2003 From: michael at themontagnes.com (Michael Montagne) Date: Fri Oct 3 12:19:39 2003 Subject: [PythonCAD] Improved DWG Reader In-Reply-To: <20031003160939.GA18218@artsapartment.org> References: <20031003160939.GA18218@artsapartment.org> Message-ID: <20031003162036.GA8887@themontagnes.com> This could be a really useful tool. You can't even use ObjectDBX and VBA to get sysvars for lots of drawings! What are the plans to read Acad2004(R16)? Doesn't OpenDwg have libraries for that too? mjm >On 10/03/03, Art Haas busted out the keyboard and typed: > Hi. > > After several fits and starts I've finished enough of the next iteration > of the DWG reader that I'm making it available for testing. This version > is currently set up for reading just R15 file formats; I'll be working on > beating the R13/R14 reader into shape shortly. > > The new DWG reader is structured like this: > > dwgbase.py: Class definition for Dwg class, file entities, and common > routines for version-specific readers. > dwg15.py: R15 file reading functions > > The 'dwg.py' file will be renamed to 'dwg1314.py'. The 'dwg12.py' will > be adjusted to fit in the layout after some feedback about the new > layout is obtained. I'm not sold on the name 'dwgbase.py' yet, so that may > change, but I think I like the way things are laid out with regards to > the approach of reading DWG files. > > So, how does this beastie work? Like this ... > > $ python > >>> import dwgbase > >>> dwg = dwgbase.Dwg("/path/to/the/dwg/file.dwg") > [ ... right now 'file.dwg' must be an R15 file - that will change once > once the other readers are converted ... ] > >>> keys = dwg.getHeaderKeys() > [ ... retrieve all the header variables from the file and store them > in the dwg object. The value of each variable can be extracted > like so ... ] > >>> dwg.getHeader('DIMSZ') > 1.0 > >>> dwg.getHeader('LTSCALE') > 10.0 > [ ... etc, etc, etc ...] > > >>> keys = dwg.getClassKeys() > [ ... retrieve the class key info in the file. These keys are currently > integer values. The class data is needed for reading the objects > in the file, so let's move on to that ... ] > > >>> objs = dwg.getObjects() > [ ... read all(*) the objects in the file and store them in a list. > Let's pretend we have 100 objects ... ] > >>> objs[0].getType() > 27 > [ ... this is a point object - see the OpenDWG spec ... ] > >>> objs[0].getHandle() > (0, 2, 5, 30) > [ ... or something similiar - remember this is pretend :-) ... ] > >>> objs[0].getEntityKeys() > ['point', 'thickness', 'extrusion', 'x_axis_angle'] > [ ... these are the entity specific values ... ] > >>> objs[0].getEntityData('point') > (0.0, 1.0, 0.5) > [ ... the point's coordinates ... ] > >>> objs[0].getEntityData('extrusion') > (0.0, 0.0, 1.0) > [ ... the extrusion value ... ] > > If you're wondering what "all(*)" meant, remember that some of the > entities are not completely described in the OpenDWG spec, and there are > a few entities omitted from the spec that are appearing in drawings I've > been sent. The reader does the best it can but there are some omissions. > > Now lets pretend that objs[50] is a circle at (40, 20) with a radius of > 14.25: > > >>> objs[50].getType() > 18 > [ ... see the OpenDWG specs ... ] > >>> objs[50].getEntityKeys() > [ 'center', 'radius', 'thickness', 'extrusion' ] > >>> objs[50].getEntityData('center') > (40.0, 20.0, 0.0) > >>> objs[50].getEntityData('radius') > 14.25 > > The above gives you an idea of how things work. The various > entity-specific fields are listed with a getEntityKeys() call, then each > field can be obtained with a getEntityData() call. Instead of using DXF > codes as the keys I chose to use descriptive strings because, well, they > are descriptive. It is clearer to figure out this ... > > getEntityData('radius') > > ... than something like ... > > getEntityData(40) > > The code is a short of documentation now, so you'll have to read it a > bit if you want to play with it. In the case of the 'Dwg' class, methods > that start with 'get' are free to be used, and methods starting with '_set' > are meant for use only within the reader code. For the class repreenting > the objects in the file, the same restriction holds, but these objects > have more 'get/_set' methods. I think this is a design flaw that will > probably be amended in the next iteration. > > To recap: > > import dwgbase > dwg = dwgbase.Dwg("/path/to/file.dwg") > headers = dwg.getHeaderKeys() > classes = dwg.getClassKeys() > objects = dwg.getObjects() > > The 'Dwg' class also has methods for retrieving the image data that R13, > R14, and R15 files may have stored ... > > bmpimg = dwg.getImageData('BMP') # could return None > wmfimg = dwg.getImageData('WMF') # could return None > > These methods need testing as I haven't tried to do anything with them > yet. > > For each object in the 'objects' list above the following methods will > probably be used the most ... > > obj = objects[0] # pick one ... > type = obj.getType() > handle = obj.getHandle() > keys = obj.getEntityKeys() > val = obj.getEntityData('foo') # one of the valid entity keys ... > > The 'dwg15.py' file is somewhat messy now due to this conversion. It > will be cleaned up in due time. The immediate goal is to provide a > usable interface for extracting the drawing info stored in the DWG file > so please let me know what you think of the means I've provided so far. > If you find some potential method call missing please provide feedback. > > While working on this conversion I found and fixed a number of bugs in > the R15 reader, and also found that there are at least two entity types > not described in the OpenDWG spec that appear in some of the drawings > I've been sent. The DXF info I have called 'AutoCAD 2000 DXF Reference' > lists several entitys that the OpenDWG spec omits (i.e. ARCALIGNEDTEXT) > so maybe someone can create a simple drawing with one or two of these > entities in both DWG and DXF formats and we can try to figure out the > bit layout in the DWG file. > > Congrats if you've made it this far through this message ... :-) > > Those people willing to test this can send me an e-mail and I'll mail > off the files to you. > > Art -- Michael Montagne michael@themontagnes.com http://www.themontagnes.com From ahaas at airmail.net Fri Oct 3 13:01:49 2003 From: ahaas at airmail.net (Art Haas) Date: Fri Oct 3 13:02:00 2003 Subject: [PythonCAD] Improved DWG Reader In-Reply-To: <20031003162036.GA8887@themontagnes.com> References: <20031003160939.GA18218@artsapartment.org> <20031003162036.GA8887@themontagnes.com> Message-ID: <20031003170149.GB18218@artsapartment.org> On Fri, Oct 03, 2003 at 09:20:36AM -0700, Michael Montagne wrote: > This could be a really useful tool. You can't even use ObjectDBX and > VBA to get sysvars for lots of drawings! What are the plans to read > Acad2004(R16)? Doesn't OpenDwg have libraries for that too? > The AutoCAD 2004 DWG format is apparently completely different from previous versions, and based on the info at the OpenDWG group much more complex. The format involves various encryption techniques and other data mangling "features" that made the file format more complex. The OpenDWG people have reverse engineered some/most/(all?) of the file format but haven't made public the format. If it gets made public I'll work on adding it, but trying to decode the format myself is not possible right now. There is enough to do in supporting the older formats, and it would be nice to add writing DWG files to the library. That is a long-term goal. The OpenDWG people do offer libraries that can handle the newest format. I have never used them so I have no idea how they perform. I'd suggest visiting the OpenDWG forums for more info and feedback. I've also become interested in seeing these DWG readers be written in Perl, as I know that would be immensely useful to anyone using Perl when dealing with DWG files. Once the DWG readers take some sort of stable form it may be an interesting project to convert the readers to Perl. I've looked a bit at this and it seems like a Perl reader could be created without relying on any extra modules - the vec() function will almost certainly be used for handling the the bitstreams that the objects are stored in. Having the readers written in Perl would potentially draw in more developers who could help maintain any open-source DWG handling programs, correct errors and omissions found in the OpenDWG spec, and contribute their skills to enhance the performance of any DWG reader or writer. Let's not forget the occasional flame war or two as well ... :-) Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Sun Oct 5 17:01:51 2003 From: ahaas at airmail.net (Art Haas) Date: Sun Oct 5 17:02:12 2003 Subject: [PythonCAD] Improved DWG reader, take 2 ... Message-ID: <20031005210151.GA24061@artsapartment.org> Hi. I've hacked and beaten the R13/R14 reader into something that now fits in with my design for the general DWG file reader, and it is available for testing. If you want to try it out, send me an e-mail and I'll mail the files to you. You'll get a tar archive with 'dwgbase.py', 'dwg1314.py', and 'dwg15.py'. Using these files is pretty much like I'd described in my earlier mail regarding my design for the revision-neutral DWG reader. Here's the link to my initial mail posting and an early description of how things work. http://mail.python.org/pipermail/pythoncad/2003-October/000094.html I've made a few changes since then - the '_setXXX' methods lose the leading underscore (I'm funny about underscores), but these methods are still only meant for use within the actual file reading and data extraction code. The 'getXXX' methods are meant for use to retrieve the values from the Dwg instance and the various dwgEntity instances. I've also changed a few dictionary keys here and there to strings I thought were a little clearer. Here's a simple example that gets all the objects out a a file: $ python >>> import dwgbase >>> dwg = dwgbase.Dwg("/path/to/the/file.dwg") [ ... the 'file.dwg' can be an R13, R14, or R15 file ... ] >>> objs = dwg.getObjects() [ ... the 'objs' will be a list of dwgEntity objects - we'll look at the first one ... ] >>> obj = objs[0] >>> obj.getType() 20 >>> obj.getEntityKeys() ['foo', 'bar', 'blah'] >>> fooval = obj.getEntityData('foo') >>> barval = obj.getEntityData('bar') I've added lots of doc strings to the 'dwgbase.py' file to provide a starting point of documentation. Getting the object data for each of the objects in the DWG file is pretty much done like in my fictional example above - the getEntityKeys() returns descriptive strings listing the data that is unique for the object, and getEntityData() returns the value for that key. I've tried my new-fangled reader on a number of different DWG files, and it has worked decently enough. So now it goes out in hopes of generating some feedback. Thanks in advance to anyone wishing to test this. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ewilhelm at sbcglobal.net Sun Oct 5 18:02:55 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Sun Oct 5 18:03:20 2003 Subject: [PythonCAD] Improved DWG reader, take 2 ... In-Reply-To: <20031005210151.GA24061@artsapartment.org> References: <20031005210151.GA24061@artsapartment.org> Message-ID: <200310051702.55708.ewilhelm@sbcglobal.net> > The following was supposedly scribed by > Art Haas > on Sunday 05 October 2003 04:01 pm: >>>> import dwgbase >>>> dwg = dwgbase.Dwg("/path/to/the/file.dwg") >[ ... the 'file.dwg' can be an R13, R14, or R15 file ... ] >>>> objs = dwg.getObjects() >[ ... the 'objs' will be a list of dwgEntity objects - we'll look at > the first one ... ] >>>> obj = objs[0] >>>> obj.getType() >20 >>>> obj.getEntityKeys() >['foo', 'bar', 'blah'] >>>> fooval = obj.getEntityData('foo') >>>> barval = obj.getEntityData('bar') As butchered as the code gets when quoted here, I like this design for having abstracted the file format to an interface which is independent of the version. The only thing I could ask for beyond that is that the entities not have to be processed as a list. This may be prohibitive given the nature of the dwg format, but is there a way to randomly access entities based on properties like layer and entity type? Maybe this is premature optimization. I'll try digging through the code some more and see if there is a simple and robust way to do it (such as storing the offset to an entity as it is loaded (slight cost in memory, but might enable a much faster access if you only want part of the data.)) If the simplest method is to let them be a list, what about a method which steps through the list, returning a handle to one entity at a time (similar to read() and seek() functions?) --Eric From ahaas at airmail.net Sun Oct 5 19:54:00 2003 From: ahaas at airmail.net (Art Haas) Date: Sun Oct 5 19:55:26 2003 Subject: [PythonCAD] Improved DWG reader, take 2 ... In-Reply-To: <200310051702.55708.ewilhelm@sbcglobal.net> References: <20031005210151.GA24061@artsapartment.org> <200310051702.55708.ewilhelm@sbcglobal.net> Message-ID: <20031005235400.GA16285@artsapartment.org> On Sun, Oct 05, 2003 at 05:02:55PM -0500, Eric Wilhelm wrote: > > [ ... snip my code snippet ... ] > As butchered as the code gets when quoted here, I like this design for having > abstracted the file format to an interface which is independent of the > version. > Good. > The only thing I could ask for beyond that is that the entities not have > to be processed as a list. This may be prohibitive given the nature of > the dwg format, but is there a way to randomly access entities based on > properties like layer and entity type? I don't see it if there is. The entites are all stored in the object map section of the file, and there is no telling what type of object the entity represents until you seek to the correct offset in the file, read in the right amount of bits/bytes, and start decoding them. I don't think the DWG file format lends itself to the sort of access you are looking. If someone out there can correct me, please do, as it would be nice to be able to read only certain entity types from the file, or maybe entities that are on a specific layer. > > Maybe this is premature optimization. I'll try digging through the code some > more and see if there is a simple and robust way to do it (such as storing > the offset to an entity as it is loaded (slight cost in memory, but might > enable a much faster access if you only want part of the data.)) > > If the simplest method is to let them be a list, what about a method which > steps through the list, returning a handle to one entity at a time (similar > to read() and seek() functions?) > The way reading the entities works, at least with the R13, R14, and R15 readers, is the object map section is read in first, creating a list of file offsets where the objects are stored. At this point the number of entities in the file is known. So there can certainly be something written where each each entity is individually read in. In the code I've made, this is kinda-sorta done in the read_objects() functions, This function just saves all the entities it reads in as a list then returns the list. Some sort of generator-type code could be created to where each entry taken from the object map processed one "object" at a time. Take a peek at the code and see if you can come up with what you are looking for, or write some pseudo-code and send it to the list. I'd bet something can be cooked up ... Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ewilhelm at sbcglobal.net Sun Oct 5 21:56:14 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Sun Oct 5 21:56:37 2003 Subject: [PythonCAD] DWG reader via perl Message-ID: <200310052056.14068.ewilhelm@sbcglobal.net> While it might be interesting to rewrite the dwg read/write library in Perl, I don't see myself coming up with the time. Since I am rewriting the CAD::Drawing module to use the openDWG libraries via Inline (where before the wrapper was built with swig and has some serious problems,) I've been doing some research on how inline works. See below for a [not-so] nice example. The structure of my CAD::Drawing module is beginning to show itself. It looks like it will be breaking into the following modules: CAD::Drawing new() add methods query methods (Get() GetAddrByColor(), etc) delete method(s?) CAD::Drawing::Calculate methods specific to Drawing CAD::Drawing::Defined constants usable by all Drawing::* modules CAD::Drawing::Manipulate Move() Copy() Clone() Rotate() Mirror() (group functions for performing all of the above) CAD::Drawing::IO (front-end functions) load() save() loadgzip() savegzip() CAD::Drawing::IO::openDWG (optional if you have the OpenDwg libraries) loaddwg() savedwg() CAD::Drawing::IO::Image saveimg() CAD::Drawing::IO::PostScript saveps CAD::Drawing::IO::GPLdwg (This is where I will wrap in the pythoncad library) loaddwg() savedwg() --Eric http://www.perl.com/pub/a/2001/02/inline.html use Inline Python; my $language = shift; print $language, (match($language, 'Perl') ? ' rules' : ' sucks'), "!\n"; __END__ __Python__ import sys import re def match(str, regex): f = re.compile(regex); if f.match(str): return 1 return 0 -- The opinions expressed in this e-mail were randomly generated by the computer and do not necessarily reflect the views of its owner. --Management From ewilhelm at sbcglobal.net Sun Oct 5 22:23:29 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Sun Oct 5 22:23:53 2003 Subject: [PythonCAD] seek to entity In-Reply-To: <20031005235400.GA16285@artsapartment.org> References: <20031005210151.GA24061@artsapartment.org> <200310051702.55708.ewilhelm@sbcglobal.net> <20031005235400.GA16285@artsapartment.org> Message-ID: <200310052123.29902.ewilhelm@sbcglobal.net> > The following was supposedly scribed by > Art Haas > on Sunday 05 October 2003 06:54 pm: >The way reading the entities works, at least with the R13, R14, and R15 >readers, is the object map section is read in first, creating a list of >file offsets where the objects are stored. At this point the number of >entities in the file is known. So there can certainly be something >written where each each entity is individually read in. In the code I've >made, this is kinda-sorta done in the read_objects() functions, This >function just saves all the entities it reads in as a list then returns >the list. Some sort of generator-type code could be created to where >each entry taken from the object map processed one "object" at a time. I'm not a fluent speaker of Python, so correct me if I'm reading this incorrectly. It looks like the read_objects() function is storing the entity data in a data structure and then adding this entire structure to the return list. What I had in mind (since it looks like you are going to run through yet another level of code before getting this into your pythoncad data structure anyway) is something more along the lines of: (if you don't mind me speaking in Perl) $dwg = Class::Whatever->new() $dwg->load("file/from/disk.dwg"); $handle = $dwg->StartEntityGet("modelspace"); # rewinds the list while($object = $dwg->getObject($handle) ) { $type = $object->type(); if($type eq "line") { # whatever, you get the point my %data = ( "pts" => $object->getPoints(), "color" => $object->getColor(), ); $self->addline(\%data); } } # end while See, I am going to loop over the entity list and load the data into a structure of my own design (as I am guessing you plan to do as well.) For this reason, I think it makes sense to simply provide a way to get to the next entity (I agree that the format does not seem to lend itself to random access.) If you set it up like this, it is similar to while($line = ) and you simply burn through the list, picking and choosing what you want. I only suggest this because it looks like the current function is using memory, when the data is going to be reassigned to another structure in the long run anyway. If everything is just pointers and references, then that is fine (and my apologies for not speaking the native tongue.) --Eric -- Cult: A small, unpopular religion. Religion: A large, popular cult. -- Unknown From ahaas at airmail.net Mon Oct 6 11:21:40 2003 From: ahaas at airmail.net (Art Haas) Date: Mon Oct 6 11:21:49 2003 Subject: [PythonCAD] seek to entity In-Reply-To: <200310052123.29902.ewilhelm@sbcglobal.net> References: <20031005210151.GA24061@artsapartment.org> <200310051702.55708.ewilhelm@sbcglobal.net> <20031005235400.GA16285@artsapartment.org> <200310052123.29902.ewilhelm@sbcglobal.net> Message-ID: <20031006152140.GB17381@artsapartment.org> On Sun, Oct 05, 2003 at 09:23:29PM -0500, Eric Wilhelm wrote: > > [ ... snip ... ] > > I'm not a fluent speaker of Python, so correct me if I'm reading this > incorrectly. > > It looks like the read_objects() function is storing the entity data in a data > structure and then adding this entire structure to the return list. > > What I had in mind (since it looks like you are going to run through yet > another level of code before getting this into your pythoncad data structure > anyway) is something more along the lines of: > > (if you don't mind me speaking in Perl) > > $dwg = Class::Whatever->new() > $dwg->load("file/from/disk.dwg"); > $handle = $dwg->StartEntityGet("modelspace"); # rewinds the list > while($object = $dwg->getObject($handle) ) { > $type = $object->type(); > if($type eq "line") { # whatever, you get the point > my %data = ( > "pts" => $object->getPoints(), > "color" => $object->getColor(), > ); > $self->addline(\%data); > } > } # end while > > See, I am going to loop over the entity list and load the data into a > structure of my own design (as I am guessing you plan to do as well.) > You can do this now with the current reading code as it stands now. Start python and load in the 'dwgbase' module ... >>> dwg = dwgbase.Dwg("/path/to/file.dwg") >>> for obj in dwg.getObjects(): type = obj.getType() if type == 34: # or whatever value floats your boat ... data = {} for key in obj.getEntityKeys(): data[key] = obj.getEntityData[key] # use data in some fashion here ... >>> > For this reason, I think it makes sense to simply provide a way to get > to the next entity (I agree that the format does not seem to lend itself > to random access.) If you set it up like this, it is similar to > while($line = ) and you simply burn through the list, picking and > choosing what you want. I believe what you want is available now. My example code in earlier mail messages demonstrated how the entire list of objects can be saved in a list. The one thing my current design does to is cache the objects after it reads them, so there is a price in memory to be paid. My thinking was that it would be good to save them so that multiple calls of getObjects() would not require scanning the file again. Time will tell if this choice is a good path to take. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ewilhelm at sbcglobal.net Mon Oct 6 16:16:59 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Mon Oct 6 16:17:25 2003 Subject: [PythonCAD] seek to entity In-Reply-To: <20031006152140.GB17381@artsapartment.org> References: <20031005210151.GA24061@artsapartment.org> <200310052123.29902.ewilhelm@sbcglobal.net> <20031006152140.GB17381@artsapartment.org> Message-ID: <200310061516.59983.ewilhelm@sbcglobal.net> > The following was supposedly scribed by > Art Haas > on Monday 06 October 2003 10:21 am: >The one thing my current design does to is cache the objects after it >reads them, so there is a price in memory to be paid. My thinking was >that it would be good to save them so that multiple calls of >getObjects() would not require scanning the file again. Time will tell >if this choice is a good path to take. IMO, it isn't worth the memory to cache the entire object. I'm still just guessing that you have a plan to load the data into another structure before it shows up onscreen (is this correct?) If this is the case, there will never be another call to getObjects() and if you are doing some kind of selective read, it is reading all of the data before you have a chance to skip the data which you don't want to load. >From my reading of your code, it seems that the getObjects() in dwgbase.py makes a call to r15_read_objects() (let's say we're just talking about r15 files for now). r15_read_objects() then calls a few other functions and passes (_handle,_omap,_cmap) to read_objects(), which then runs through the list of objkeys. Amoung other things, this function seeks to the "_last_loc" in the filehandle and gets an entity handle. It then goes on to process the entity and load it into the return list with _objlist.append(_ent) In the interest of reducing the amount of memory used and also reducing the amount of duplicated code in the library, I suggest that the calling program be allowed to fly a little closer to the raw data (but with a unified interface like the one provided by dwgbase.py.) In my example, I showed a function call which initialized the entity list. This would perform many of the functions of your r15_read_objects() function (everything that has to do with calculating offsets and the mapping of the file (cmap, omap, sections, etc.) The other task would be to set the _last_loc variable to the beginning of the object list. So, the program would call dwg.getObjectInit() and then have a loop of: while enthandle, type = dwg.getNextObj() I guess that getNextObj() would basically do what happens inside of your "for _obj in _objkeys" loop (inside of read_objects()). The speed benefit of this is that you save a loop, but you might also save yourself some code, and you will save memory as well. With my benchmark 9.8MB pile of circles (250000 of them), it takes about 3 minutes and 292MB of ram to call objs = dwg.getObjects() and I would still have to make my way through that list and load all of this info into another data structure before the dwg object goes out of scope and the memory gets freed. I'll try to look at the code some more and see if I can come up with a good way to do it, but my feeling is that you will be better served by providing a consistent interface to what is happening in the loop of read_objects(). This will make the whole thing scalable and the efficiency can be gained in the code which lies on the next layer above the library (at the price of repeated function calls rather than possibly huge amounts of duplicated memory.) --Eric -- "...our schools have been scientifically designed to prevent overeducation from happening." --William Troy Harris From ahaas at airmail.net Mon Oct 6 18:30:35 2003 From: ahaas at airmail.net (Art Haas) Date: Mon Oct 6 18:30:56 2003 Subject: [PythonCAD] seek to entity In-Reply-To: <200310061516.59983.ewilhelm@sbcglobal.net> References: <20031005210151.GA24061@artsapartment.org> <200310052123.29902.ewilhelm@sbcglobal.net> <20031006152140.GB17381@artsapartment.org> <200310061516.59983.ewilhelm@sbcglobal.net> Message-ID: <20031006223035.GB985@artsapartment.org> On Mon, Oct 06, 2003 at 03:16:59PM -0500, Eric Wilhelm wrote: > > [ ... snip ... ] > >The one thing my current design does to is cache the objects after it > >reads them, so there is a price in memory to be paid. My thinking was > >that it would be good to save them so that multiple calls of > >getObjects() would not require scanning the file again. Time will tell > >if this choice is a good path to take. > > IMO, it isn't worth the memory to cache the entire object. > > I'm still just guessing that you have a plan to load the data into another > structure before it shows up onscreen (is this correct?) If this is the > case, there will never be another call to getObjects() and if you are doing > some kind of selective read, it is reading all of the data before you have a > chance to skip the data which you don't want to load. > I've not really thought about how I want to get the data into PythonCAD just yet. One idea is to write out a temporary file in PythonCAD's format and read it in. Another idea is to write out the XML data directly into PythonCAD. I didn't see re-using the object data for the purpose I had in mind, but I thought someone else may want to do that, so I coded things as you see them at present. It may end up not being worthwhile to do this, and if someone wants to cache the info they'll have to do it from their code and not from the Dwg interface. See my comments below ... > >From my reading of your code, it seems that the getObjects() in dwgbase.py > makes a call to r15_read_objects() (let's say we're just talking about r15 > files for now). > > r15_read_objects() then calls a few other functions and passes > (_handle,_omap,_cmap) to read_objects(), which then runs through the list of > objkeys. Amoung other things, this function seeks to the "_last_loc" in the > filehandle and gets an entity handle. It then goes on to process the entity > and load it into the return list with _objlist.append(_ent) > That sounds about right. The '_last_loc' is the offset in the file where the entity data resides - this value comes from the object map section. > In the interest of reducing the amount of memory used and also reducing the > amount of duplicated code in the library, I suggest that the calling program > be allowed to fly a little closer to the raw data (but with a unified > interface like the one provided by dwgbase.py.) > > In my example, I showed a function call which initialized the entity list. > This would perform many of the functions of your r15_read_objects() function > (everything that has to do with calculating offsets and the mapping of the > file (cmap, omap, sections, etc.) The other task would be to set the > _last_loc variable to the beginning of the object list. > > So, the program would call dwg.getObjectInit() and then have a loop of: > while enthandle, type = dwg.getNextObj() > > I guess that getNextObj() would basically do what happens inside of your > "for _obj in _objkeys" loop (inside of read_objects()). The speed benefit of > this is that you save a loop, but you might also save yourself some code, and > you will save memory as well. That loop would end up being moved to a function to read each the entities one at a time. Looking at the code with the idea of doing this then a small cleanup of making the extended entity data reading become its own function as well. > With my benchmark 9.8MB pile of circles (250000 of them), it takes about 3 > minutes and 292MB of ram to call objs = dwg.getObjects() and I would still > have to make my way through that list and load all of this info into another > data structure before the dwg object goes out of scope and the memory gets > freed. That is a lot of memory - more than my machine has in both real and swap. Ugh ... I'll look at modifying the R15 reader to do entity-at-a-time reading, and we'll see what comes out. The R13/R14 file I'll leave alone until we get something that looks reasonable, then I'll change that one as well. It will probably take a day or two for the new code to appear. > I'll try to look at the code some more and see if I can come up with a good > way to do it, but my feeling is that you will be better served by providing a > consistent interface to what is happening in the loop of read_objects(). > This will make the whole thing scalable and the efficiency can be gained in > the code which lies on the next layer above the library (at the price of > repeated function calls rather than possibly huge amounts of duplicated > memory.) Let me know what you come up with. Thanks for the feedback and suggestions, and when I've got a new version of the code to send out I'll post a mail to the mailing list. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ewilhelm at sbcglobal.net Mon Oct 6 19:01:41 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Mon Oct 6 19:02:09 2003 Subject: [PythonCAD] seek to entity In-Reply-To: <20031006223035.GB985@artsapartment.org> References: <20031005210151.GA24061@artsapartment.org> <200310061516.59983.ewilhelm@sbcglobal.net> <20031006223035.GB985@artsapartment.org> Message-ID: <200310061801.41977.ewilhelm@sbcglobal.net> > The following was supposedly scribed by > Art Haas > on Monday 06 October 2003 05:30 pm: >I didn't see re-using the object data for the purpose I had in mind, but >I thought someone else may want to do that, so I coded things as you see >them at present. It may end up not being worthwhile to do this, and if >someone wants to cache the info they'll have to do it from their code >and not from the Dwg interface. I can't see using a dwg library as the heart of a drafting or modeling program without really sinking yourself into a rut. Any need to export to another format would mean mapping between a dwg structure and the other format. It would also be restrictive to your code's design. It looks like you will need a load_dwg() function which steps through the dwg data to get it into pythoncad. I've found your imageio.load_image() function (I'm assuming that this is your main data structure?) Hopefully, I've got the DWG::Drawing module working within two weeks. I'm currently shooting for a data structure which looks like: $self->{geom}{$layer}{$type}{$index} = \%objecthash; where: %obh_lines = ( "pts" => [ [ $x1, $y1, $z1], [$x2, $y2, $z2] ], "color" => $color, "linetype" => $linetype, "anything" => $anything, ); This will give a lot of flexibility in what can be loaded into the module. The primary use of this is for batch processing, so it is centered around being able to identify entities based on their properties. This doesn't mean that it wouldn't be good for building a backend to a quick gui, but you would need a way to tie the on-screen entities to the data structure. I imagine that would be done via the $address hash-references that I have been using (any add function returns an address of the form {"layer" => $layer, "type" => $type, "index" => $index} and all manipulation functions accept these as the "name" of the entity on which to operate. Were I to use this in some sort of graphical selection routine, I would either link the item to the address or the address to the item (haven't looked into the Perl bindings to gtk or Tk far enough to figure out how this would be done.) It's all made me into quite a "hash addict." Programming is so much easier when there is no search involved! --Eric -- "Matter will be damaged in direct proportion to its value." --Murphy's Constant From ahaas at airmail.net Wed Oct 8 16:37:06 2003 From: ahaas at airmail.net (Art Haas) Date: Wed Oct 8 16:41:03 2003 Subject: [PythonCAD] Improved DWG Reader, Take 3 Message-ID: <20031008203706.GA20405@artsapartment.org> Hi. After the exchange of e-mail regarding the previous DWG reader, I set about to add a means of reading the entities from the DWG file one entity at a time. Thanks to the neat new Python feature of generators adding this ability has been easier than I'd hoped. I've only changed the R15 reader to do handle this new reading facitlity. The code to use this facility is simple ... >>> dwg = dwgbase.Dwg("/path/to/file.dwg") >>> for obj in dwg.getObject(): ... [ ... do stuff here ... ] Each object in the file is returned one is extracted, and the entities are not cached in the Dwg instance. This should greatly reduce the memory requirements when reading large files. The previous method call getObjects(); which stores the entities, is still present. I still think this can be useful in some situations, and caching the entities is certainly faster if they list of entities needs to be examined repeatedly. Some of the earlier mail had perl code in them, so here's a perl-ish representation of what the Dwg class now does. In the example code pretend that the data in the file doesn't need processing in the way that the DWG bitstream data does,. Let's start with some variable setting code ... my $file = '/path/to/some/file'; open(DWG, <$file) or die "Can't open '$file'! $!\n"; Using the entity-at-a-time getObject() call: while() { ... do stuff with the data ... } close(DWG); In this case if you need to look at the contents of the file again you have to re-read it. Likewise, the getObject() code has returned a dwgEntity() object for you to use, but the Dwg class doesn't keep it around. Using the getObjects() call as was seen previously: @data = close(DWG); All the info from the file is stored in @data, and in the Dwg class all the entities are saved away for quick retrieval. If you only want to look at the info once then the getObject() approach should work. If you need to repeatedly scan the data then use getObjects(). The R15 code is now messier due to these changes. I've consolidated some of the separate functions into single functions, and split some of the large functions into several smaller ones. Aside from the fact that there is now more unused code still in the R15 file, the direction things are moving looks good. If you want the code to play with it just mail me and I'll send it along. I wish that the subversion repo was accessible now. It is unlikely I'll get to work on get the subversion software installed on that machine this week or weekend. Hopefully soon ... Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Sun Oct 12 12:14:36 2003 From: ahaas at airmail.net (Art Haas) Date: Sun Oct 12 12:14:44 2003 Subject: [PythonCAD] Improved DWG Reader, Take 4 Message-ID: <20031012161436.GA27472@artsapartment.org> Hi. I've modified the R13/R14 reader so it more closely matches the R15 reader, so now is a good time to make the reader again available for testing. The cleanups removed a nasty global variable by adding a method to the Dwg class for getting and setting the version of the DWG file being examined. This version info is then set in the entity. My quick testing on a couple of files works, so things look good from here. Let me know if you would like the files. Also, I've upgraded to Python 2.3.2 this weekend. My build is from the Python CVS repo as of a day or two ago. As I'm now on Python 2.3 I should start seeing any of the errors and warnings other people have reported. Doing this upgraded made me re-install the pygtk stuff, and my installation of that package, again from CVS, printed out a few warnings I hadn't seen before regarding int/float values in GTK calls. These will be fixed promptly. As the last two months have been spent working on these DWG/DXF readers, there hasn't been much work done on the PythonCAD code itself. I'm hoping to change that over the next couple of weeks, as the DWG reader seems to be at a point where it is feasible to begin working on a real import mechanism of DWG files into PythonCAD. There are still many entities in AutoCAD that don't exist in PythonCAD - ellipses and splines are examples of that. I've wanted to add both, and now that the idea of importing DWG data is at least possible, the addition of these new entities into PythonCAD is due. Hatching and printing are still not working, nor is there any sign that development of either will change in the short-term future. :-( Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Sun Oct 12 12:18:22 2003 From: ahaas at airmail.net (Art Haas) Date: Sun Oct 12 12:18:27 2003 Subject: [PythonCAD] OS Survey Message-ID: <20031012161822.GB27472@artsapartment.org> Hi. I've wondered just what OSes people are running PythonCAD under. I use Linux - Debian unstable with my CVS builds of various packages. I'm sure that there are others using other Linux distributions as well. Do we have any *BSD users, or AIX, Solaris, Irix, HP-UX or Windows users out there? Curious, Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Tue Oct 14 14:39:23 2003 From: ahaas at airmail.net (Art Haas) Date: Tue Oct 14 14:39:33 2003 Subject: [PythonCAD] [ANNOUNCE] Tenth release of PythonCAD now available Message-ID: <20031014183923.GB26044@artsapartment.org> I'd like to announce the tenth development release of PythonCAD, a CAD package for open-source software users. As the name implies, PythonCAD is written entirely in Python. The goal of this project is to create a fully scriptable drafting program that will match and eventually exceed features found in commercial CAD software. PythonCAD is released under the GNU Public License (GPL). PythonCAD requires Python 2.2 or Python 2.3. The interface is GTK 2.0 based, and uses the PyGTK module for interfacing to GTK. The design of PythonCAD is built around the idea of separating the interface from the back end as much as possible. By doing this, it is hoped that both GNOME and KDE interfaces can be added to PythonCAD through usage of the appropriate Python module. Addition of other interfaces will depend on the availability of a Python module for that particular interface and developer interest and action. The tenth release contains many fixes for running PythonCAD on Python 2.3. The latest Python release has a variety of internal changes, and various bits of code in PythonCAD triggered deprecation warnings from Python. All known warnings have been removed, so PythonCAD should run cleanly on this new Python release, as well as the older 2.2 releases. This release also includes the code for reading AutoCAD DWG files, though PythonCAD still is unable to import the files. This code will be the basis for importing DWG files into PythonCAD directly. A number of entity clipping algorithms have been added for use in redrawing the screen and future use in improving the internal entity storage and access. Radial dimensions entities now can display the diameter value of a circle instead of just the radius. This release also contains a number of other small bug fixes and code improvements, though the redraw bug in release eight is still not fixed. The DWG file format information came from the OpenDWG group, so my thanks to them for providing this information on the web. The OpenDWG website is at http://www.opendwg.org The mailing list for the development and use of PythonCAD is available. Visit the following page for information about subscribing and viewing the mailing list archive: http://mail.python.org/mailman/listinfo/pythoncad Visit the PythonCAD web site for more information about what PythonCAD does and aims to be: http://www.pythoncad.org/ Come and join me in developing PythonCAD into a world class drafting program! Art Haas -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Thu Oct 16 13:09:20 2003 From: ahaas at airmail.net (Art Haas) Date: Thu Oct 16 13:09:27 2003 Subject: [PythonCAD] Bug in Generic/dwg15.py in latest PythonCAD release Message-ID: <20031016170920.GA21232@artsapartment.org> Hi. I found a dumb bug in the dwg15.py file that went out with the latest release. The 'get_default_double()' function needs to have 'dwgutil' added as a prefix. This change is easy to do in a text editor. Simply search for 'get_default_double' and prepend 'dwgutil.' to it. Sorry about letting this slip by ... -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ewilhelm at sbcglobal.net Fri Oct 17 12:37:24 2003 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Fri Oct 17 12:37:25 2003 Subject: [PythonCAD] Re: new Perl module CAD::Drawing In-Reply-To: <3F9017AA.7040201@nyetwork.org> References: <3F9017AA.7040201@nyetwork.org> Message-ID: <200310171137.24482.ewilhelm@sbcglobal.net> > The following was supposedly scribed by > Wim Kerkhoff > on Friday 17 October 2003 11:24 am: > Hi Eric, > Your CAD::Drawing module looks pretty interesting: > http://mail.python.org/pipermail/pythoncad/2003-September/000089.html > I'd like to do some testing and experimenting with it. We want to > convert SVG XML created by Flash/ActionScript into DXF using some sort > of Perl web service, and this looks like it could solve the missing link. > http://search.cpan.org/src/EWILHELM/CAD-Drawing-0.00/README > Any targets for something downloadable? Sorry, not yet. I'm currently on a development schedule worthy of a royal hair-pulling. If you'd be interested in creating an SVG XML I/O backend, I'd certainly try to get something together asap. You will need to be able to use the OpenDWG toolkit (cannot distribute it with the module due to licensing) in order to save/load dwg or dxf files for now. For this, you'll need a license from the opendwg consortium (free for internal use, with fees for distribution.) I plan to eventually have a gpl-compatible dwg/dxf I/O backend using Art's python library (and there also exists the possibility of doing dxf with the dime library.) I've been trying to work out an installation procedure for the Inline.pm - based toolkit wrapper, since the install could be somewhat hairy right now. --Eric From wim at nyetwork.org Fri Oct 17 12:19:29 2003 From: wim at nyetwork.org (Wim Kerkhoff) Date: Fri Oct 17 12:38:35 2003 Subject: [PythonCAD] Fwd: new Perl module CAD::Drawing Message-ID: <3F901691.4040202@nyetwork.org> Hi Eric, Your CAD::Drawing module looks pretty interesting: http://mail.python.org/pipermail/pythoncad/2003-September/000089.html I'd like to do some testing and experimenting with it. We want to convert SVG XML created by Flash/ActionScript into DXF using some sort of Perl web service, and this looks like it could solve the missing link. http://search.cpan.org/src/EWILHELM/CAD-Drawing-0.00/README Any targets for something downloadable? Wim From ahaas at airmail.net Fri Oct 17 12:46:04 2003 From: ahaas at airmail.net (Art Haas) Date: Fri Oct 17 12:46:36 2003 Subject: [PythonCAD] Plans for eleventh release Message-ID: <20031017164604.GA26689@artsapartment.org> Hi. Now that the tenth release is out the door, the time is right to make an estimation as to what will be in the eleventh release. I've been tweaking the DWG/DXF code, and would like to have a DXF module similar to the one for DWG present. It would be great to have a first cut at a file importer for either or both of these formats. The DWG code is at a point where this is feasible, but the DXF code isn't there yet. I want to add an ellipse and elliptical arc entities to the program, and some sort of spline line as well. These types of entities were planned to be added, but had not as yet been done. As the DWG files have these entities, now would be a good time to get them in. The missing hatching and printing functionality still annoys me greatly, but I haven't made any headway on either. I've tried to figure out some sort of undo/redo mechanism as well, but haven't had any ideas on that front. Ideas and suggestions welcomed. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Tue Oct 21 10:16:03 2003 From: ahaas at airmail.net (Art Haas) Date: Tue Oct 21 10:16:11 2003 Subject: [PythonCAD] Looking for info on NURBS Message-ID: <20031021141603.GA5183@artsapartment.org> Hi. Can anyone provide some links for background on NURBS? A search on Google has many links, but many of them are not very helpful - links to college classes, references to papers, etc. If you have a favorite link handy please pass it along. I did find this link on Apple's site: http://devworld.apple.com/dev/techsupport/develop/issue25/schneider.html This page provides a good background of NURBS, with equations and pictures that illustrate how they operate. This page was written for Mac programmers who were writting QuickDraw3D code. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Tue Oct 21 10:36:55 2003 From: ahaas at airmail.net (Art Haas) Date: Tue Oct 21 10:37:01 2003 Subject: [PythonCAD] Looking for info on NURBS In-Reply-To: <20031021141603.GA5183@artsapartment.org> References: <20031021141603.GA5183@artsapartment.org> Message-ID: <20031021143655.GC5183@artsapartment.org> On Tue, Oct 21, 2003 at 09:16:03AM -0500, Art Haas wrote: > Hi. > > Can anyone provide some links for background on NURBS? A search on > Google has many links, but many of them are not very helpful - links > to college classes, references to papers, etc. If you have a favorite > link handy please pass it along. > > I did find this link on Apple's site: > > http://devworld.apple.com/dev/techsupport/develop/issue25/schneider.html > > This page provides a good background of NURBS, with equations and > pictures that illustrate how they operate. This page was written for Mac > programmers who were writting QuickDraw3D code. > A quick response to myself and the list ... http://mathworld.wolfram.com/B-Spline.html http://mathworld.wolfram.com/NURBSCurve.html -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From pfrostie at yahoo.com Tue Oct 21 11:30:00 2003 From: pfrostie at yahoo.com (phrostie) Date: Tue Oct 21 11:30:40 2003 Subject: [PythonCAD] Looking for info on NURBS In-Reply-To: <20031021141603.GA5183@artsapartment.org> Message-ID: <20031021153000.67703.qmail@web11003.mail.yahoo.com> a quick search of sourceforge.net found: http://sourceforge.net/projects/libnurbs/ http://sourceforge.net/projects/nmnurbs/ there were others, but these looked the most general. --- Art Haas wrote: > Hi. > > Can anyone provide some links for background on NURBS? A search on > Google has many links, but many of them are not very helpful - links > to college classes, references to papers, etc. If you have a favorite > link handy please pass it along. > > I did find this link on Apple's site: > > http://devworld.apple.com/dev/techsupport/develop/issue25/schneider.html > > This page provides a good background of NURBS, with equations and > pictures that illustrate how they operate. This page was written for Mac > programmers who were writting QuickDraw3D code. > > Art > -- > Man once surrendering his reason, has no remaining guard against absurdities > the most monstrous, and like a ship without rudder, is the sport of every > wind. > > -Thomas Jefferson to James Smith, 1822 > > _______________________________________________ > PythonCAD mailing list > PythonCAD@python.org > http://mail.python.org/mailman/listinfo/pythoncad ===== phrostie Oh I have slipped the surly bonds of DOS and danced the skies on Linux silvered wings. http://pfrostie.freeservers.com/cad-tastrafy/ http://www.freelists.org/webpage/cad-linux __________________________________ Do you Yahoo!? The New Yahoo! Shopping - with improved product search http://shopping.yahoo.com From ahaas at airmail.net Thu Oct 23 12:21:33 2003 From: ahaas at airmail.net (Art Haas) Date: Thu Oct 23 12:21:46 2003 Subject: [PythonCAD] NURBS stuff Message-ID: <20031023162133.GD27461@artsapartment.org> Hi. Using the links I've posted and some sent to me I've found some good starting info on NURBS. I've written a some Python code to generate the basis functions and plot out the points on the curves, and having made the plots (in Gnuplot) they look more-or-less correct. My method of calculated the basis functions is recursive, and I've spent a good bit of time trying to do the calculations in a non-recursive manner as well. I'm just not getting the non-recursive stuff to work at all, and some of the code examples I've found haven't been helpful. The code is in C, and the author hadn't considered many potential condtions in the code, like if the knots are duplicated. This, by the way, can lead to divide-by-zero errors, so if you don't catch this the code will crash. There is still much more to be done with adding NURBS to PythonCAD, not the least of which is figuring out some way to interactively create them. I can see adding the control points by clicking on the drawing area, but I'm not clear on how to add the knots. Also, adjusting the weights of the control points is still a mystery. Can anyone post a few comments about programs they have used handle creating this sort of thing? How does AutoCAD do it, or how to other CAD packages do it? As NURBS are used in many animation or other drawing programs, how are they created in those programs as well? Thanks. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822