PDA

View Full Version : Creating compound paths



bassPenguin
28th March 2012, 08:37
Hi, I am writing a printed circuit board image file (Gerber) viewer that must render to am interactive vector image. The image files are lists of coordinates and drawing mode switches (line vs arc vs outline fill) in between. There are usually many filled polygons with holes knocked out of them. The problem is that these knockouts are not independent in that the solid parts of the shapes are listed first, and then the knockouts are listed on top. This means that I cannot draw a complete compound shape at once and must later look at all shapes underneath the knockouts to subtract them if they overlap.

I am currently parsing these files into QPainterPaths and adding respective QGraphicsPainterItems to a QGraphicsScene. When I get to the knockouts, I find all the colliding items with the knockout path using QGraphicsScene::collidingItems and subtract the knockout path from the solid paths using QPainterPath::operator-. I do this instead of drawing the background color over the solid shapes because I need to be able to see items on different board layers through the holes. It is extremely slow, however, to do many of these Boolean path operations, making it take an unreasonable amount of time to load some files into the graphics scene. I also considered just adding paths to create compound paths using the even-odd painter drawing mode, but that doesn't work when the knockout shape overlaps multiple paths or even extends outside the boundary of any intersecting path.

Basically what I want to do is very similar to path differences or object masks in popular vector editing software. Here is a very simple example of the sort of vector image I am rendering:
7538

Does anyone have any ideas about what I may be able to do here to increase performance or a different approach to consider?
Thanks

ChrisW67
28th March 2012, 09:22
Thanks for a well constructed question :)

I am not intimate with the Gerber File spec (http://www.ucamco.com/public/RS-274X_Extended_Gerber_Format_Specification_201201.p df).

The first observation is that knockout entries need only be compared against earlier entries in the same Gerber information layer. Perhaps you could cache an layer's QPainterPaths outside the scene until you see the knockouts (or end of layer) then deal with the in-memory structures without the overhead of the graphics view elements. At the end of the layer add all the painter paths to the scene.


I am sure someone with more experience of the graphics view will have more ideas.

wysota
28th March 2012, 11:41
If using bitmaps is an option then one could draw the paths on QPixmap, QImage or similar using QPainter and when the knockout data is available, change the composition mode to Clear and draw the knockouts. After a layer is complete, it can be added to the scene as a single pixmap item. This will result in improved speed at a cost of possible reduced quality while zooming.

bassPenguin
28th March 2012, 12:57
Chris, thanks for the quick reply. I don't know if QGraphicsScene uses BSP to calculate intersections, but if it does I'm worried that I may lose that advantage and it will actually be even slower. I'll try caching the paths first as you suggested and see if it helps.

Added after 19 minutes:

Thanks wysota. I considered this approach before, but I am concerned that it will cause too many problems later since the user needs to be able to manipulate the shapes dynamically and individually. Since the file format gives vector instructions, it is also nice to take advantage of that. Maybe these issues could be mitigated by a well-structured internal model of shapes. If you think it could work, I might consider this approach again since the user should only make one manipulation at a time and so regenerating part of the image is not a big deal. It may require more work on my side, however, since I won't have the advantage of using item transformations for my manipulations.

Added after 8 minutes:

Sorry, this is my first post and I tried to reply individually, but it looks like it grouped them together. Is this just a normal consolidation?