Bug/Feature in tiling code (probably in agg)

Let the developers know what you think of the software and what can be done to either improve the CFDG language or the Context Free program.

Moderators: MtnViewJohn, chris, mtnviewmark

Post Reply
User avatar
kipling
Posts: 91
Joined: Wed Jun 18, 2008 2:36 am

Bug/Feature in tiling code (probably in agg)

Post by kipling »

I have been using a "stack of smoked glass" in a few places for the illusion of depth. e.g. this

Code: Select all

tile{}
background {  b -1 }
 
rule START {
    42* { hue +60 }  CRYSTAL {  sat 0.1 b 0.7 } 
    200 * { z -0.02 } SQUARE { a -0.997 b 0 z 0.5 }
    }
appears in my "crystals" design http://www.contextfreeart.org/gallery/view.php?id=1447)
One thing that was bugging me is that the design didn't tile nicely, and that there were dark "seams" at the tiling joins. These are not visible on the uploaded images, as they appear at the edge of the image, but if you tile them (e.g. set to desktop) then they are quite obvious.

It turns out that this is not a problem with the tiling code missing polygons that span the tile join, as I first thought (the crystals code generates 10 000 000 's of polygons, so I thought that some were only being rendered on one side of the seam). Instead, it seems (seams?) to be a problem with polygons such as the SQUAREs above that have two sides that meet perfectly once wrapped around the torus. If you offset each square in the above code like this:

Code: Select all

   200 * { z -0.02 } SQUARE { a -0.997 b 0 z 0.5 x 0.5 y 0.5 }
then the joins appear across the middle of the image.

My workaround is to fudge things around so that the seams don't end up on top of each other, but are successively offset by some irrational(ish) numbers:

Code: Select all

200 * { x 0.6180339 y 0.4142136 z -0.02 } SQUARE { a -0.997 b 0 z 0.5 }
I don't know whether this gets filed as a feature or a bug, and if it is a bug, whether it is easily fixed - it is likely to be a result of agg trying to do sub-pixel resolution at the boundary, and picking up both edges.

User avatar
MtnViewJohn
Site Admin
Posts: 875
Joined: Fri May 06, 2005 2:26 pm
Location: Mountain View, California
Contact:

Post by MtnViewJohn »

The seams are caused because the tiling code is drawing each of your SQUAREs 9 times. One square centered on the canvas and 8 more directly adjacent to that square. The 8 other square should all be drawn outside of the actual canvas, but due to anti-aliasing and sub-pixel rendering they smear a little bit onto the canvas. So the pixels at the edge are drawn over 9 times as much as the center pixels.

This is an example of the general problem with drawing polygons with edges that are adjacent. You can get results that look OK if the polygons are solid and the same color. But once the alpha goes less than 1 there is no real way to prevent boundary fringes. You would have to determine which pairs of polygons have exactly touching edges and replace those with a single polygon that is the union of the two polygons. If a design has 100,000 polygons then there are 10,000,000,000 polygon pairs to check for adjacency.

The only realistic solution that would work for you is to put in code to recognize SQUAREs that exactly fill the canvas and replace the polygon draw operation with a simple buffer fill operation.

User avatar
kipling
Posts: 91
Joined: Wed Jun 18, 2008 2:36 am

Post by kipling »

Hi John

Yes thanks. I thought it would be something like this - feature rather than bug. As well as the O(n^2) complexity there is the question of what to do about adjacent polygons of different colour or transparency... ...and 2.2b has splines.

Given the implementation of tiling you describe, I came up with another solution:

Code: Select all

tile {}
...
	200 * { z -0.02 } SQUARE { s 4 a -0.9997 b 0 z 0.5  } 
It looks cleaner than irrational offsets, but is dependent on the internal implementation. Logic says this should be 16* less transparent, and have seams through the centre, but due to the implementation it is 9* less transparent and has no seams.

If there was a generalised "background" object that had finite z-coord then a more elegant approach would be something like

Code: Select all

	200 * { z -0.02 } background { a -0.9997 b 0 z 0.5  } 
and this would also work in non-tiled designs. But this breaks CFs freeness of context - i.e. we want planes at z = k, not z = -infinity + k. If a PLANE primitive were introduced, then background {} could be an instance of PLANE at z = -infinity.

But this would only to get my "flavour of the month" code to work, so I wouldn't bother making this any sort of priority.

Cheers, AK

Post Reply