Skip to content

text: Honor vector heads on the -D+v leader line pen - #9263

Merged
Esteban82 merged 7 commits into
masterfrom
text-leader-arrow
Oct 16, 2026
Merged

Esteban82 merged 7 commits into
masterfrom
text-leader-arrow

Conversation

@Esteban82

Copy link
Copy Markdown
Member

text -D...+v<pen> accepted the pen's +v modifiers but silently ignored them. This PR makes +vb<specs> draw a vector head at the data point, as plot -W does. psxy's end-vector helper moves to gmt_plot.c as gmt_plot_end_vectors so both modules share it (no change to plot output).

Vector head at the data point

The leader is shortened by the head length so the tip lands on the point. It works with a text box (-W/-G), rotated text and paragraph mode (-M); a head longer than the leader is skipped.

Tested with:

gmt begin leader png
	gmt basemap -R0/10/-1/1 -JX12c/6c -B
	printf "5 0\n2 -0.5\n8 0.5\n8 -0.5\n" | gmt plot -Sc0.15c -Gblack
	echo "5 0 Label" | gmt text -D2c/1c+v1p,red+vb0.4c+gred -F+f12p
	echo "2 -0.5 Box" | gmt text -D1.5c/-1.2c+v0.5p+vb0.3c+a50+gblue -F+f12p -W0.5p -Gyellow -C0.2c
	echo "8 0.5 Rotated" | gmt text -DJ1c+v1p,darkgreen+vb0.3c+gdarkgreen -F+f12p+a30+jML
	echo "8 -0.5 No head" | gmt text -D-1.5c/-0.6c+v1p -F+f12p
gmt end
leader

Head at the text end: not supported (error)

A head at the text end (+ve, or plain +v for both ends) is rejected with an error:

echo "5 0 X" | gmt text -R0/10/-1/1 -JX10c -D1c+v1p+ve0.3c -ps err
text [ERROR]: Option -D: A vector head can only be placed at the data point end of the line; use pen modifier +vb<specs>

The leader is clipped against the text box in PostScript (PSL_plotline_clipped_by_textbox), so C does not know where the line meets the box. Supporting it would need that intersection computed in C (e.g. a PSL function returning the text dimensions) or the head drawn in PostScript. Happy to follow up if wanted.

Written with Claude Opus 5.5 (implementation and local review); draft by Claude Sonnet 5.5.

The pen given to -D...+v<pen> accepted the +v line-end modifiers but
silently ignored them.  Now +vb<vspecs> places a vector head at the
data point, shortening the leader so the tip lands on the point.  The
text end is clipped in PostScript so its end point is unknown in C;
+ve (or plain +v) is therefore rejected with an error.  The head is
skipped when longer than the leader.  psxy's end-vector helper moves
to gmt_plot.c as gmt_plot_end_vectors so both modules share it.

Also stop the paragraph (-M) box from inheriting a stale fill/outline
when only a leader line is requested, and do not share (then free) the
default pen's vector heads in the -D pen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Esteban82
Esteban82 requested review from joa-quim and seisman October 13, 2026 21:57
@Esteban82 Esteban82 added enhancement Improving an existing feature add-changelog Add PR to the changelog labels Oct 13, 2026
@joa-quim

Copy link
Copy Markdown
Member

Didn't we have nothing that does this already? And I think the arrow head should stop at circle's edge, not its center.

@Esteban82

Copy link
Copy Markdown
Member Author

Didn't we have nothing that does this already?

On whether something already does this: plot -W...+vb draws a line with a head, and text -D...+v<pen> already drew the leader line but dropped the head modifiers silently. This PR only makes text honor what its pen already accepted, so one command gives the label, the leader (clipped at the text box) and the head. I'm not aware of another option that combines them; if you had a specific one in mind, point me to it.

And I think the arrow head should stop at circle's edge, not its center.

On the head stopping at the circle's edge: the black dots in the figure are drawn separately (with printf "5 0\n2 -0.5\n8 0.5\n8 -0.5\n" | gmt plot -Sc0.15c -Gblack) with plot -Sc, so text does not know a symbol is there or how big it is, and today the tip lands exactly on the data point. Here is the same figure without the circles:

leader

If you want, I could add a suppor for +o<offset> at the data end (as plot -W does), so the user sets the gap for their symbol, e.g. -D2c/1c+v1p,red+o0.1c+vb0.4c+gred. Default stays 0.

@joa-quim

joa-quim commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Yes, I think a +o<offset> is important too.

I have this implemented in GMT.jl (https://www.generic-mapping-tools.org/GMTjl_doc/documentation/utilities/annotate.html#vector-lines) but likely I implemented the arrow part separately.

@joa-quim

Copy link
Copy Markdown
Member

In these type of changes we must strictly insist with Claude that it is not allowed to reinvent solutions that GMT already has. I am thinking for example in +o<offset>. It will insist it won't do it but that thing is a big liar.

Esteban82 and others added 5 commits October 16, 2026 09:16
+o<offset> (c|i|p) stops the leader, and its +vb head, that distance
short of the data point, e.g. to clear a symbol plotted there, as
plot -W does.  Only the data-point end is affected (a single value
also sets the text end, which is ignored), other units and negative
offsets are rejected, and nothing is drawn if the offset reaches the
text.  Without +o the output is unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…er pen

The -D pen starts as a copy of MAP_DEFAULT_PEN, so a +o or +v in that
default leaked into the leader and could even trigger the new -D errors
(e.g. MAP_DEFAULT_PEN=1p+o100k).  Clear all line-end settings instead of
only the head pointers; master never applied them to the leader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the hand-made +o handling with the existing gmt_trim_line, so
+o accepts the same offsets as plot -W (plot units and map distances)
and the head-length trim follows the same rules.  The leader is
sampled at 101 vertices because gmt_trim_line treats reaching the last
vertex as trimming away the whole line.  The text end is never trimmed
since the box clipping is relative to it.  A leader shorter than the
offset plus head is not drawn, as in plot.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
With -F+c corner anchoring on maps whose bounding-box corners fall
outside the projection domain (e.g. -JG), the NaN coordinates made
gmt_trim_line collapse the leader to nothing.  Skip the trim in that
case.  Also document that +o goes before +vb and which line attributes
it follows.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Esteban82

Copy link
Copy Markdown
Member Author

Thanks @joa-quim. Added +o<offset>, handled by the same gmt_trim_line that plot -W uses, so it takes the same offsets and rules (c|i|p or map distances; put it before +vb). Only the data-point end is trimmed, and the default stays 0.

Tested with:

gmt begin leader_offset png
	gmt basemap -R0/10/-1/1 -JX12c/6c -B
	printf "5 0\n2 -0.5\n8 0.5\n8 -0.5\n" | gmt plot -Sc0.15c -Gblack
	echo "5 0 Label" | gmt text -D2c/1c+v1p,red+o0.15c+vb0.4c+gred -F+f12p
	echo "2 -0.5 Box" | gmt text -D1.5c/-1.2c+v0.5p+o0.25c+vb0.3c+a50+gblue -F+f12p -W0.5p -Gyellow -C0.2c
	echo "8 0.5 Rotated" | gmt text -DJ1c+v1p,darkgreen+o0.25c+vb0.3c+gdarkgreen -F+f12p+a30+jML
	echo "8 -0.5 Offset only" | gmt text -D-1.5c/-0.6c+v1p,orange+o0.2c -F+f12p
gmt end
leader_offset

@seisman

seisman commented Oct 16, 2026

Copy link
Copy Markdown
Member

In these type of changes we must strictly insist with Claude that it is not allowed to reinvent solutions that GMT already has. I am thinking for example in +o<offset>. It will insist it won't do it but that thing is a big liar.

I feel we need an AGENTS.md file (https://agents.md/) to give AI agents clear instructions what to do and not to do.

@Esteban82

Copy link
Copy Markdown
Member Author

In these type of changes we must strictly insist with Claude that it is not allowed to reinvent solutions that GMT already has. I am thinking for example in +o<offset>. It will insist it won't do it but that thing is a big liar.

I feel we need an AGENTS.md file (https://agents.md/) to give AI agents clear instructions what to do and not to do.

I'm about to make a PR about that.

@joa-quim joa-quim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, seems not very intrusive with regard to what we already have.

@Esteban82
Esteban82 merged commit 7a50908 into master Oct 16, 2026
17 of 18 checks passed
@Esteban82
Esteban82 deleted the text-leader-arrow branch October 16, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

add-changelog Add PR to the changelog enhancement Improving an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants