Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

RegionPlot will usually generate a large number of tiny polygons for filling the region:

RegionPlot[-1 < x < 1 && -1 < y < 1 && x^2 + y^2 > 4/5, {x, -1.2, 
  1.2}, {y, -1.2, 1.2}, Mesh -> All]

Mathematica graphics

When exported to PDF, these are often not very fast to render.

It is clear that theoretically these polygons could be joined into a single FilledCurve, defined by the outlines only. This should be much faster to render.

How can we do this in a robust way?


Note: the reason we need a FilledCurve and that a plain Polygon will not work is that a FilledCurve can have a hole in it (it may be multiply connected), like in the image above. Alternatively I will accept a solution which uses more than one Polygon, but still reduces the number of Polygonss as much as possible (in the example above two polygons will suffice).


Here's a complex RegionPlot to test on:

a = 36;
g = RegionPlot[
  Mod[Sqrt[x^2 + y^2] - 7/2 ArcTan[x, y] + Sin[x] + 
     Cos[y], \[Pi]] < \[Pi]/2, {x, -a, a}, {y, -a, a}, 
  PlotPoints -> 100]

The equation is from here.

share|improve this question
    
Wow, that last code gives beautiful graphics. Was it made up or does it have a story? –  Vitaliy Kaurov Jan 25 '12 at 0:45
    
@Vitaliy It's a GrafEq demo. See the very last link in my question. –  Szabolcs Jan 25 '12 at 9:41
add comment

1 Answer 1

up vote 22 down vote accepted

You could start by extracting the Line primitives from the normalized GraphicsComplex:

a=36;

g=RegionPlot[Mod[Sqrt[x^2+y^2]-7/2 ArcTan[x,y]+Sin[x]+Cos[y],Pi]<Pi/2,
 {x,-a,a},{y,-a,a},PlotPoints->100];

lines=Cases[Normal[g], _Line, Infinity];

The lines can then be directly included in a FilledCurve:

Graphics[{
  EdgeForm@Directive[Black, Thickness[Medium]], 
  FaceForm@Directive[Opacity[1/2], Orange], 
  FilledCurve[List /@ lines]
}]

Mathematica graphics

This renders noticeably faster even within Mathematica (for example during resizing).

The structure of the FilledCurve must follow the FilledCurve[{{Line[...]}, {Line[...]}, ...}] pattern in order for the holes to show correctly. Each line must be included in a separate sublist.


If each Line is included in a separate FilledCurve, then the holes will be missing:

Graphics[FilledCurve/@lines]

Mathematica graphics

If we use the FilledCurve[{Line[...], Line[...], ...}] structure, the lines will be effectively concatenated into one continuous line, causing artefacts:

Graphics[FilledCurve[lines]]

Mathematica graphics

share|improve this answer
    
I used this directly on @Szabolcs plot, and all I got was a blank image. –  rcollyer Jan 25 '12 at 3:43
    
@rcollyer - Was that with the Mesh->All setting? Because there are no Line primitives with that setting. –  Arnoud Buzing Jan 25 '12 at 3:56
    
Removed Mesh -> All got a black rectangle. –  rcollyer Jan 25 '12 at 3:58
    
@rcollyer - In the simpler case this seems to work (but it breaks the more complicated case): Graphics[FilledCurve[lines]] –  Arnoud Buzing Jan 25 '12 at 4:05
3  
I got it, the solution is FilledCurve[List /@ lines]. Since you're probably sleeping now, I'll edit your answer. Please review the edit, proofread it, and I'll accept afterwards! –  Szabolcs Jan 25 '12 at 10:07
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.