MCPcopy Create free account
hub / github.com/GenericMappingTools/gmt / gmt_plot_line

Function gmt_plot_line

src/gmt_plot.c:6169–6316  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

6167}
6168
6169void gmt_plot_line (struct GMT_CTRL *GMT, double *x, double *y, unsigned int *pen, uint64_t n, unsigned int mode) {
6170 /* Mode = PSL_LINEAR [0] or PSL_BEZIER [1] */
6171 /* Drawing lines of finite thickness that cross map boundaries is tricky because the exit or entry point
6172 * refers to the center line of a finite thickness line but the wider part of the line do not share those
6173 * coordinates. To avoid ugly line gaps we must extend such lines a bit beyond the border and clip so that
6174 * things look pretty. For now we only do this for a few situations:
6175 * 1) The map border must be rectangular
6176 * 2) The line must be a linear spline and not the Bezier spline
6177 * Hopefully we can work to avoid the first case soon */
6178
6179 uint64_t i, j, im1, ip1, k;
6180 int way;
6181 bool close, stop;
6182 double x_cross[2], y_cross[2];
6183 double x_ext, y_ext; /* Coordinates of the external helper point */
6184 unsigned int start_pen = PSL_MOVE, end_pen = PSL_STROKE; /* Default pen code of given line endings */
6185 struct PSL_CTRL *PSL= GMT->PSL;
6186
6187 if (n < 2) return;
6188
6189 gmtplot_NaN_pen_up (x, y, pen, n); /* Ensure we don't have NaNs in the coordinates */
6190
6191 /* First skip any repeating PSL_MOVE in the beginning since only the last one will matter */
6192 i = 0;
6193 while (i < (n-1) && (pen[i+1] & PSL_MOVE)) i++; /* Skip repeating pen & PSL_MOVE in beginning */
6194 if ((n-i) < 2) return; /* Less than 2 points is not a line */
6195 j = i; /* j is now the first valid point with a PSL_MOVE */
6196 /* Then we want to prevent duplicate points since the first point may have a different pen (e.g., include PSL_CLIP) */
6197 while (i < (n-1) && gmtplot_these_are_duplicates (x[j], y[j], x[i+1], y[i+1])) i++; /* Skip duplicate points in beginning */
6198 if ((n-i) < 2) return; /* Less than 2 points is not a line */
6199 if (i > j) pen[i] = pen[j]; /* Skipped initial duplicates but must maintain the initial pen code */
6200 /* Likewise, skip any repeating PSL_MOVE at the end */
6201 while (n > 1 && (pen[n-1] & PSL_MOVE)) n--; /* Cut off repeating pen & PSL_MOVE at end */
6202 if ((n-i) < 2) return; /* Less than 2 points is not a line */
6203 /* Then we want to prevent duplicate points at end since the last valid point may have a different pen (e.g., include PSL_CLIP) */
6204 j = n - 1; /* j is now last point after initial skip test */
6205 while (n > 1 && gmtplot_these_are_duplicates (x[j], y[j], x[n-2], y[n-2])) n--; /* Skip duplicate points at end */
6206 if ((n-i) < 2) return; /* Less than 2 points is not a line */
6207 if (n <= j) { /* Got a duplicate at the end */
6208 if ((pen[n-1] & PSL_CLIP) == 0) pen[n-1] = pen[j]; /* Skipped trailing duplicates but must maintain initial pen code of last valid point unless has clip information */
6209 while (n > 1 && (pen[n-1] & PSL_MOVE)) n--; /* Cut off repeating pen & PSL_MOVE at end that might result after removing that duplicate */
6210 }
6211 for (j = i + 1; j < n && !(pen[j] & PSL_MOVE); j++); /* j == n means no PSL_MOVEs present */
6212 close = (j == n) ? (hypot (x[n-1] - x[i], y[n-1] - y[i]) < GMT_CONV4_LIMIT) : false;
6213
6214 /* First see if we can use the PSL_plotline call directly to save points */
6215
6216 for (j = i + 1, stop = false; !stop && j < n; j++) stop = (pen[j] & PSL_MOVE || (*GMT->current.map.jump) (GMT, x[j-1], y[j-1], x[j], y[j]));
6217 if (!stop) { /* Safe to draw single line directly since no jumping around */
6218 if (mode == PSL_BEZIER)
6219 PSL_plotcurve (PSL, &x[i], &y[i], (int)(n - i), PSL_MOVE + PSL_STROKE + close * PSL_CLOSE);
6220 else { /* Pay more attention here since exiting lines of finite thickness may need some corrections */
6221 //bool rect = gmt_M_is_rect_graticule (GMT) || GMT->common.R.oblique; /* We have a rectangular map boundary */
6222 bool rect = !(gmt_M_is_azimuthal (GMT) && !GMT->current.proj.polar);
6223 for (j = i + 1, stop = false; !stop && j < n; j++) stop = (pen[j] & PSL_CLIP); /* Look for clipped end points */
6224 if (!rect || !stop) /* No troubled clip points or it is not a rectangular border */
6225 //if (!stop) /* No troubled clip points or it is not a rectangular border */
6226 PSL_plotline (PSL, &x[i], &y[i], (int)(n - i), PSL_MOVE + PSL_STROKE + close * PSL_CLOSE);

Callers 15

gmtplot_map_latlineFunction · 0.85
gmtplot_map_lonlineFunction · 0.85
gmtplot_linearx_oblgridFunction · 0.85
gmtplot_lineary_oblgridFunction · 0.85
gmtplot_contlabel_debugFunction · 0.85
gmt_geo_lineFunction · 0.85
gmt_geo_polygonsFunction · 0.85
gmtplot_geo_spiderFunction · 0.85
gmtplot_geo_wedge_fillFunction · 0.85
gmt_two_curve_fillFunction · 0.85

Calls 10

gmtplot_NaN_pen_upFunction · 0.85
hypotFunction · 0.85
PSL_plotcurveFunction · 0.85
PSL_plotlineFunction · 0.85
PSL_plotpointFunction · 0.85
gmt_half_map_widthFunction · 0.85
GMT_ReportFunction · 0.85
PSL_commandFunction · 0.85

Tested by

no test coverage detected