Context Free Art

Forums

Bug/Feature in tiling code (probably in agg)

Moderators: chris, MtnViewMark, MtnViewJohn

<<

kipling

User avatar

Posts: 73

Joined: Wed Jun 18, 2008 2:36 am

Post Tue Dec 09, 2008 9:05 pm

Bug/Feature in tiling code (probably in agg)

I have been using a "stack of smoked glass" in a few places for the illusion of depth. e.g. this
  Code:
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:
   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:
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.
<<

MtnViewJohn

User avatar

Site Admin

Posts: 743

Joined: Fri May 06, 2005 2:26 pm

Location: Mountain View, California

Post Wed Dec 10, 2008 12:58 am

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.
<<

kipling

User avatar

Posts: 73

Joined: Wed Jun 18, 2008 2:36 am

Post Thu Dec 11, 2008 4:36 pm

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:
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:
   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

Return to Feature Suggestions and Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron
Forum Tools
Search
User
  • Register
  • Username:
  • Password:
  • Remember login
book coverSee our book:
Community of Variation