Symbol and polygon clipping in GMT

Added by Paul about 4 years ago

Currently, GMT is not doing the right thing when it comes to clipping some symbols and polygons. This message discusses some of the shortcomings and possible solutions. I am requesting your feedback. Please refer to the attached plot which is clipping5 in the test. It has 4 sub-panels A-D; I will jump around a bit in discussing them.

A) Plotting standard symbols (Cartesian circles, triangles, stars, etc). This works exactly as we want: Symbols are clipped properly at map boundaries since the symbols are fully plotted but clipped by the map boundary clip polygon.
C) Polygons are failing. When they are clipped by the map boundary the polygon is altered to follow the map boundary. We then paint and draw that polygon. The result is an undesired outline along the map boundary. You can contrast that with pscoast which explicitly paints polygon chunks but only draws the actual coastline and not the polygon path.
D) Plotting geo-symbol ellipse. This is also failing. Like in C, ellipses are actually polygons and suffers the same problem. Notice the lower left version with no fill. In case of no fill we go through a separate code-section and the clipped line (not polygon; so it does not get closed) is plotted as a line. Correct, but look closely at the ends of the line. Because the line stops at lat = -60 the line actually does not exit the plot with nice clipping but truncates. This is only really visible for fatter pens.
B) Vector heads: Vectors were completely rewritten in GMT 5 so there are some growing pains (I spent most of yesterdays on this...). To ensure that the length of a vector with 1-2 heads is independent of the pen thickness chosen, we plot the heads in this way: (a) determine the polygon path of the head and set it as a clip path. (b) Optionally fill that path, (c) Optionally draw the path while clipping is on. Head outline pen is thus half of pen specified. We should compensate for this by using 2 x width selected by user. However, we share the same problems as in C with these polygons. I am not sure why the head clipped at east and north is OK while the ones at west and south is not. That is probably more of a "local" bug. Heads that cross a repeating map boundary has some of the same issues as polygons (see test/grdvector/wrapped). One more thing about geo-vectors: their vector line is NOT plotted as a line but as a filled skinny polygon. This is the only way to draw lines of correct projected thickness, so as a benefit it does not suffer from the clipping issues since its outline is never drawn (it is just filled, with pen color).

Solutions to C,D and maybe B:

  1. A dirty fix to C and D is to plot filled polygons with no outline first, then draw outlines as lines. It will avoid the unwanted lines along the boundary, but suffer from the line truncation in D (lower left ellipse). Again, the problem is only visible for fatter pens so in most practical cases this might be almost acceptable. The problem can be reduced further by selecting PS_LINE_CAP = SQUARE which extends the line ending by 0.5pen-width (see upper-right clipped ellipse in D). This works perfectly if exit angle < 45 degrees.
  2. For Cartesian projections and most/all rectangular map projections without repeating boundary: We may be able to use an enlarged clipping domain so that those cuts actually happens outside the area. E.g., say you plot from 10/30/5/25 but under the hood we clip data from 9/31/4/26 and handle the plot offset. Now, lines exiting the chosen domain will look like lines in A since their actual termination is outside the box. Problems: Selecting the enlarged area depends on max pen thickness to be used, which will be unknown during overlays. Clearly, as long as the region is enlarged by the equivalent of 0.5*largest-pen-thickness we are OK. We could decide on an upper limit, say 100p, but it is clearly arbitrary. Finally, this solution will not work with geographic maps with periodic boundaries (e.g. Mercator 0/360) as in C,D.
  3. Another solution is to follow the lead from B and plot any line thicker than x points as a filled polygon. This will give correct results every time for any projection and region. A question is do we do this for all lines, even 0.5p and faint, or only for lines > x points (MAP_MAX_PEN = 1p)? Note that this solution should extend to any line plotted on a map. THink of a fat ship track plotted on a -JG map with the line going close to the horizon: The effective pen thickness should change with the projection, and that means a polygon, not a line.
  4. New special handling when lines are clipped at boundary: Given the crossing point and the previous inside point, extend the crossing point outward along the line until the y coordinate is 0.5*pen-thickness outside the box.

I do think we want to aim for perfection; after all a key strong point for GMT is its plot quality, so compromising on that is not a good thing. Clearly, perfection would be 3 for perspective projections and 4 otherwise?

Comments, suggestions welcome.

clipping5.pdf - Clipping issue referred to in this message (75.1 KB)


Replies (12)

RE: Symbol and polygon clipping in GMT - Added by Florian almost 4 years ago

Since many people post-process GMT generated PS files, I would opt for 4 always because touching up the PS files in a DTP program later would be more difficult with 3. Along comes a feature request: GMT should draw proper filled and outlined polygons instead of drawing a separate frame above and around a polygon without outlines.

RE: Symbol and polygon clipping in GMT - Added by Paul almost 4 years ago

Option 4 is good, except for perspective projections when 3 must be applied (you cannot shrink a pen thickness as function of view angle so it has to be done that way). As for the feature request: This is a statement saying we should do the above? if not then I don't know exactly what you mean.

RE: Symbol and polygon clipping in GMT - Added by Florian almost 4 years ago

Yes, this is was a feature request. It is not so practical to have two ungrouped objects per framed polygon. Why not plot a polygon with the outline property in the first place instead of plotting two unrelated objects on top of each other?

RE: Symbol and polygon clipping in GMT - Added by Remko almost 4 years ago

Florian, as for your feature request: that is exactly what we're doing now.
The PS code is a single set of vertices and then the information that the polygon must be filled and stroked.
In other words, they are not "ungrouped".
Can you maybe show a PS example of what you mean?

RE: Symbol and polygon clipping in GMT - Added by Paul almost 4 years ago

To do that the polygon must be clipped in the way described above (sticking out beyond the actual map border) so that the outline is clipped beyond the frame. If the polygon is clipped to the frame then only some portions of the outline should be drawn with a pen, hence you canned do both at once.

RE: Symbol and polygon clipping in GMT - Added by Paul almost 4 years ago

Remko, what you say is true but because of frame clipping for geo-symbols and polygons we end up with outlines along the frames that should not be there.

RE: Symbol and polygon clipping in GMT - Added by Florian almost 4 years ago

Here is an example of a polygon without stroke:

pscoast -A0/0/1 -JX10c/0 -R16/18/38/41 -B30m -Dl -Ggray -Wblack > polyNoStroke.ps

In the screenshot you see there are two features for each polygon. The outline of the top tile is currently hidden.

polyNoStroke.png (68.2 KB)

RE: Symbol and polygon clipping in GMT - Added by Paul almost 4 years ago

What we have is one polygon (gray; not stroked) and three line segments (stroked). As you can see with a fat pen, these are forcefully clipped at the border and has ugly endings.

polyNoStroke.pdf (4.83 KB)

RE: Symbol and polygon clipping in GMT - Added by Florian almost 4 years ago

Right and we want one polygon (not tiles) with stroke, which is expanded as clipped to the frame.

RE: Symbol and polygon clipping in GMT - Added by Remko almost 4 years ago

Florian and Paul,
You have to be careful when you use the generic term "polygons". GMT normally uses stroked and filled polygons as one item. Not so for pscoast, for obvious reasons because the land is built up of tiles.
I've once tried to build single PS objects that could be filled and partially stroked, but I was not successful.

RE: Symbol and polygon clipping in GMT - Added by Paul almost 4 years ago

Also: Let us not mix this up with a total rewrite of GSHHG and pscoast, etc. That is a slightly longer/bigger project. After all, pscoast works correctly even if you don't like the tiling approach which was cleverly designed back in the late 1980s when men were men, Regan was president and memory was something that came in kB....
So at the moment I am looking for an upgrade to how we do polygons (and by extension the geo-symbols).

RE: Symbol and polygon clipping in GMT - Added by Florian almost 4 years ago

Fine, no mixing anymore. Here is an example that shows, that psxy does exactly the same thing as pscoast: Instead of plotting one single object, it generates a polygon without stroke and the stroke is a different object. I would expect one stroked object per segment which is clipped as proposed in solution 4 above.

psxy -JX10c/0 -R0/1/0/1 -B0.2 -W15p -Ggray << EOF > poly.ps
> 1
0.5 0.5
1.5 1
1.5 0
0.5 0.5
> 2
-1 0.6
0.4 0.6
0.4 2
-1 2
-1 0.6
EOF
PS: what you also see in this example is that the frame is composed of 4 individual lines instead of one single rectangle.

polyNoStroke2.png (69.6 KB)

(1-12/12)