X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com Message-ID: <56A1C4AE.9010703@xs4all.nl> Date: Fri, 22 Jan 2016 06:57:02 +0100 From: "Bert Timmerman (bert DOT timmerman AT xs4all DOT nl) [via geda-user AT delorie DOT com]" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.19) Gecko/20110429 Fedora/2.0.14-1.fc13 SeaMonkey/2.0.14 MIME-Version: 1.0 To: geda-user AT delorie DOT com Subject: Re: [geda-user] PCB data structures References: <1512221837 DOT AA25291 AT ivan DOT Harhan DOT ORG> <20160106133049 DOT 5A0E9809D79B AT turkos DOT aspodata DOT se> <20160106143629 DOT 4D39D809D79B AT turkos DOT aspodata DOT se> <20160106164022 DOT D0D4E809D79B AT turkos DOT aspodata DOT se> <20160106180912 DOT 42ddf4079d91384f206b7c35 AT gmail DOT com> <20160106191433 DOT 5dc5cb59 AT jive DOT levalinux DOT org> <20160106202817 DOT 56197b2c539d426a1b724c9e AT gmail DOT com> <568E09ED DOT 1080508 AT m0n5t3r DOT info> <568E6354 DOT 80302 AT m0n5t3r DOT info> <20160108002640 DOT 03233b24 AT jive DOT levalinux DOT org> <20160108175259 DOT 127a3f073616758434f7edff AT gmail DOT com> <20160109020345 DOT 1e07cb84 AT jive> <20160109112851 DOT 1129dc38 AT wind DOT levalinux DOT org> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit Reply-To: geda-user AT delorie DOT com Roland Lutz wrote: > On Sat, 9 Jan 2016, Britton Kerin (britton DOT kerin AT gmail DOT com) [via > geda-user AT delorie DOT com] wrote: >> First the existing parser needs to get separated from the innards of >> pcb. > > I agree. > >> As things stand now there's no single data structure that corresponds >> one-to-one with the format. Once this is done other equivalent formats >> could be implemented. > > So let's start with that! :-) I translated the PCB file format > definition into a set of C structs which you find below. The > rationale behind this data structures is as follows: > > - An "object" should be something that is located at some position on > the board, and which makes sense to manipulate as an entity (e.g., > both an "element instance" and a "pad" are objects, but an attribute > is not). > > - The location of an object in the hierarchy should be independent > from the actual data which makes up the object (i.e., there are no > pointers to child objects in the data structures; the hierarchy is > managed separately and points to each object's data). > > - The data structure should be semantic; any value should have an > explicit field, explicit type, and explicit meaning. Attributes are > implemented as fields in a struct so they are semantically accessible > to other users of the data structure. > > - All code operating on these data structures should be in the main > repository, so if some change to the data structure is necessary, it > can be performed without having to worry about breaking code elsewhere. > > - The data structure should not contain any fields that are internal > to the PCB implementation. > > How the in-memory object hierarchy should look like is actually a > non-trivial question. I think it's generally a good idea to have the > state of the object tree represent something on which you can do a > meaningful undo/redo: for schematics, for example, this would be each > referenced or embedded symbol, and the schematic itself. But a PCB > file consists of four different kinds of things: the PCB layout, the > imported netlist, the elements in the layout, and the stroke font. > > The netlist is a bit different in that it doesn't have a geometric > structure; it's not "objects" in the definition above. The stroke > font symbols are obvious candidates for separate object trees. The > hard question is whether to treat an element as a "group object" which > contains a bunch of element line/arc, pin, and pad objects, or to > treat it as an instantiation of an embedded element definition (a.k.a. > footprint). > > I think from a logical perspective it makes more sense to treat it as > an instantiation (you might want to update an embedded footprint, or > to not embed but reference a footprint in the future), but the way > elements are currently used suggests a group object notion, too (for > example changing the sizes of individual pads/pins in an existing > element). Since I had to choose, I finally went with treating them as > an instantiation (this is at least consistent with the way we treat > symbols in gEDA/gaf). > > > ### Object hierarchy ### > > A PCB file contains a PCB layout, an arbitrary number of footprints, > and (usually) 94 symbols. > > The PCB layout has an object of type pcb_layout as the root object, > which can contain an arbitrary number of pcb_layer objects--which in > turn contain the geometric primitives--and pcb_element objects which > aren't associated with a layer. Objects of type pcb_polygon can have > child objects of type pcb_polygon_hole: > > pcb_layout > +- pcb_layer > +- pcb_arc > +- pcb_line > +- pcb_pad > +- pcb_pin > +- pcb_polygon > +- pcb_polygon_hole > +- pcb_rat > +- pcb_text > +- pcb_via > +- pcb_element > > A footprint (element definition) has a pcb_footprint object as the > root object which can only contain objects of the types > pcb_element_arc, pcb_element_line, pcb_pad, and pcb_pin: > > pcb_footprint > +- pcb_element_arc > +- pcb_element_line > +- pcb_pad > +- pcb_pin > > A symbol definition has a pcb_symbol object as the root object which > can contain pcb_symbol_line objects: > > pcb_symbol > +- pcb_symbol_line > > > ### Struct definitions ### > > I'm using double coordinates here. This is not a meant as a statement > regarding integer vs. floating-point values; you can simply replace > "double" with your favorite kind of "int". > > The "flags" field gave me a bit of trouble since it is a kind of > general-purpose field which contains a lot of unrelated information. > Most of this is only valid for certain object types, though, so I > moved these flags to the appropriate type structs. What remained is > five flags which apply to most geometric objects: > > /* Helper struct > used by arc, line, pad, pin, rat, text, via, element, and element > text */ > > struct pcb_flags { > bool found; > bool selected; > bool failed_drc; > bool locked; > bool connected; > }; > > It may make sense to move some of this information (found and selected > objects, DRC result) to a different place later since it represents a > set of objects, not a state of an individual object. > > There are some directives (Grid, PolyArea, Thermal, DRC, Styles) which > relate to the PCB file as a whole and can't be used more than once, so > I grouped them into the pcb_layout data structure: > > struct pcb_layout { > struct string name; > struct double2d size; > struct { > double step; > struct double2d offset; > bool visible; > } grid; > struct { > double area; > } poly_area; > struct { > double scale; > } thermal; > struct { > double bloat; > double shrink; > double line; > double silk; > double drill; > double ring; > } drc; > struct { > bool showdrc; > bool rubberband; > bool nameonpcb; > bool autodrc; > /* ... flags ... */ > } flags; > struct string groups; > struct { > struct string name; > double thickness; > double diameter; > double drill; > double keepaway; > } styles[4]; > struct { > bool grid_imperial; > double grid_size; > /* ... attributes ... */ > } attributes; > }; > > I probably missed some flags and attributes because I couldn't find a > list in the documentation and guessed from an example file. > > There isn't much data associated with a layer, just the number and a > name: > > struct pcb_layer { > int number; > struct string name; > }; > > The geometric objects contain a "flags" field (except for > pcb_polygon). Some flags which are only valid for certain object types > are defined directly in the object's data structure, and pcb_element > contains two sets of flags, one for the element itself and one for its > text label: > > struct pcb_arc { > struct double2d pos; > struct double2d radius; > double thickness; > double clearance; > int startangle; > int deltaangle; > bool clear_polygons; > struct pcb_flags flags; > }; > > struct pcb_element { > struct pcb_flags flags; > struct string desc; > struct string name; > struct string value; > struct double2d mark; > struct double2d text; > int tdir; > double tscale; > bool hide_element_name; > bool show_pin_names; > bool onsolder; > struct pcb_flags tflags; > struct pointer footprint; > }; > > struct pcb_line { > struct double2d pos[2]; > double thickness; > double clearance; > bool clear_polygons; > bool autorouted; > struct pcb_flags flags; > }; > > struct pcb_pad { > struct double2d pos[2]; > double thickness; > double clearance; > double mask; > struct string name; > struct string number; > bool nopaste; > bool onsolder; > bool square; > bool warn; > bool edge2; > struct pcb_flags flags; > }; > > struct pcb_pin { > struct double2d pos; > double thickness; > double clearance; > double mask; > double drill; > struct string name; > struct string number; > bool hole; > bool square; > bool warn; > bool octagon; > bool edge2; > struct pcb_flags flags; > }; > > struct pcb_polygon { > struct double2d_list vertices; > bool clear; > bool full; > }; > > struct pcb_polygon_hole { > struct double2d_list vertices; > }; > > struct pcb_rat { > struct double2d pos[2]; > int group[2]; > struct pcb_flags flags; > }; > > struct pcb_text { > struct double2d pos; > int direction; > double scale; > struct string string; > struct pcb_flags flags; > }; > > struct pcb_via { > struct double2d pos; > double thickness; > double clearance; > double mask; > double drill; > struct string name; > bool hole; > bool autorouted; > bool warn; > bool octagon; > struct pcb_flags flags; > }; > > The pcb_footprint structure has much duplication with pcb_element. > Some of this can probably be removed since some fields only make sense > for an element instance and others for a footprint, but since I'm not > too familiar with the way PCB works, I thought it would be safer to > keep them for now: > > struct pcb_footprint { > struct string desc; > struct string name; > struct string value; > struct double2d mark; > struct double2d text; > int tdir; > double tscale; > bool hide_element_name; > bool show_pin_names; > bool onsolder; > struct { > struct string device; > struct string manufacturer; > struct string manufacturer_part_number; > struct string vendor; > struct string vendor_part_number; > /* ... attributes ... */ > } attributes; > }; > > As with the PCB file, I guessed the attributes from an example file > and probably missed some. > > struct pcb_element_arc { > struct double2d pos; > struct double2d radius; > int startangle; > int deltaangle; > double thickness; > }; > > struct pcb_element_line { > struct double2d pos[2]; > double thickness; > }; > > Finally, symbol definitions: > > struct pcb_symbol { > wchar_t ch; > double delta; > }; > > struct pcb_symbol_line { > struct double2d pos[2]; > double thickness; > }; Hi, AFAICT a via lives on board level. All the via_pads beloging to a via have all the same location/dimensions/connectivity and are switched on/off per layer level inside the via definition. Kind regards, Bert Timmerman.