Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating Custom Pens #3929

Open
PaulWessel opened this issue Aug 11, 2020 · 3 comments
Open

Creating Custom Pens #3929

PaulWessel opened this issue Aug 11, 2020 · 3 comments
Assignees
Labels
feature request Request a new feature

Comments

@PaulWessel
Copy link
Member

Rationale

For symbols we have custom symbols which allows users to create macros that produce any symbol imaginable, with one or more extra data parameters affecting the symbol. We do not have a similar mechanism for lines. One idea therefore is to create a custom pen. The information would be stored in name.pen files, similar to symbol.def files for symbols, and name will be used as the style argument in pen specifications.

custompen

Syntax

In GMT, a pen is specified via the syntax

[width][,color][,style]

where commas are only used to separate items if more than one is given. All items are optional and have GMT defaults: 0.25p,black,solid. A custom pen will be requested via the style argument in a pen assignment. All custom pens inherit the above defaults if width or color are not set (the style cannot be overridden since it is the name of the custom pen). A given pen width will be distributed proportionally since custom pens must use nondimensional widths (and dash lengths). To override custom pen colors a series of colors may be provided to change them all, separated by + characters. A missing color means keep the default color.

User-level examples

Here is a set of syntax examples as to how users may specify such custom pens:

-Wrailroad
-W4p,ridge
-Wred+green,border
-W6p,black+red+yellow,route
-W1p,@path

The last example gets the custom pen path from the GMT cache server and scales it to 1p.

Implementation

The name.pen file format consists of an optional header with comments, followed by two or more nondimensional pen specifications. The pens will be applied in the order given, hence the order is important. Here is an example of a custom pen used to draw railroad tracks:

# Name: railroad
# Purpose: Draw a line that looks like a checkered railroad line.
# Lay down a black solid line of unit width
1,black,solid
# Overlay a white thinner dashed line
0.6666666666,white,5_5:0

Note the following:

  1. The actual pens are given in multiples of unit pen widths and are normally scaled by the width given on the command line [0.25p].
  2. The assigned color of the pens may be overridden on the command line [black]
  3. Any dashes, gaps, offsets must all be given in nondimensional and scaled up accordingly.
  4. To simplify parsing we specify all of width,color,style even if black and solid.

To use this custom pen but replace black with red, one would say -Wred,railroad, while a black and yellow railroad would need -W+yellow,railroad or -Wblack+yellow,railroad. Internally, reading a custom pen means we create an array of pens where the widths and colors and styles may be adjusted given the users choices (or else take the defaults). Hence, the problem of further implementation is how to repeatedly draw lines using an array of pens.

Module implementation

Initially designed for use in plot (psxy), it will require either a new plot-line function that takes the line to plot plus an array of pens resulting from a custom pen (or a single item if classic pen) and then repeatedly draws the same line while cycling over the available pens. Alternatively, the module could implement an outer loop over pens around the remaining line-drawing machinery. The main difference will be when we switch between pens (for each line or for each set of lines).

Modules affected

A test implementation would probably just target plot (psxy) and legend (pslegend). If successful we may extend to plot3d (psxyz) and wiggle. We can discuss if this effect is also useful for contours. See attached plot for some examples that could be implemented as custom pens (here they are just combinations of 2 or 3 pens). Note that what may appear as symbols (circles and squares) are just line property manipulations. I have given some of the basic pens a name.

[Moved from old GMT wiki Developer page]

@PaulWessel PaulWessel added the feature request Request a new feature label Aug 11, 2020
@PaulWessel PaulWessel self-assigned this Aug 11, 2020
@KristofKoch
Copy link
Contributor

Hi @PaulWessel is it possible to widen the scope a bit?

I'd really could use a dashed line with arrowheads every n-th dash (indicating direction of movement) Currently I help myself by combining a dashed line and a line with symbols on it and some wild offset-fu to get the desired effect but it is rather fragile: Can't cross plot borders or it'll break. Can only move up or the symbol used as arrowhead is oriented in the wrong direction etc. See example below.

If this could be implemented as custom pen this would be really awesome. Shaded lines come to mind as well (to indicate the inside of a polygon and not just done with masks which require a closed polygon). And while I'm dreaming … have "true" splines-on-a-sphere … and have it work with all kinds of lines (with or without symbols) … Your thoughts?

last_pos_radar

@PaulWessel
Copy link
Member Author

Those are cool lines, @KristofKoch. However, they cannot be done as simple pens that just rely on the PostScript operators - they would have to be something in C that replicates all the machinery in PostScript for dash/dots except drawing polygons. Since we convert a line internally to (x,y) arrays in inches we could draw a dashed line, but then the issue is the vector head. If we were to build this using the GMT primitives it would be a dashed line (-W) combined with a Sv specification and some flag that says "place arrow at end of every n'th dash. We already have +e +b for controlling which side to place the error (or both).

@KristofKoch
Copy link
Contributor

Ah, ok I see – thank you for explaining it. So my wishes are outside of the scope of this issue.

Currently I achieve the desired effect with

gmt plot track.txt -S~d96p:+st12p+an+p1p,black+i -W0p,white+o32p/0
gmt plot track.txt -W5p,black,28_20+o2p --PS_LINE_CAP=square

but as said, it is a very fragile way to do it. Maybe I can entertain you guys that it might be a worthwhile development?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Request a new feature
Projects
None yet
Development

No branches or pull requests

2 participants