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

Function gmtplot_geo_polygon_segment

src/gmt_plot.c:4722–4797  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

4720}
4721
4722GMT_LOCAL uint64_t gmtplot_geo_polygon_segment (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S, bool add_pole, bool first, const char *comment) {
4723 /* Handles the laying down of polygons suitable for filling only; outlines are done separately later.
4724 * Polar caps need special treatment in that we must add a detour to the pole.
4725 * That detour will not be drawn, only used for fill. However, due to the insanity that is called GIS,
4726 * some user polygons may already have artificial lines drawn to the pole in order to work in GIS.
4727 * Thus, if we detect such a pole as part of the line then we do NOT add yet another detour. */
4728
4729 uint64_t n = S->n_rows, k;
4730 double *plon = S->data[GMT_X], *plat = S->data[GMT_Y], t_lat; /* Default is to plot incoming array as is via plon,plat pointers */
4731 bool ap = gmtplot_at_pole (plat, n); /* Is the first and last point exactly at the pole? */
4732 bool free_memory = false;
4733 struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (S);
4734 if (ap) plon[n-1] = plon[0]; /* Just enforce the same longitude at the pole point */
4735 GMT_Report (GMT->parent, GMT_MSG_DEBUG, "Polar cap: %d\n", (int)add_pole);
4736 if (add_pole) { /* Make sure there is not already a detour in the data as given */
4737 double p_lat = SH->pole * 90.0; /* Latitude of the pole in question */
4738 bool need_detour = true; /* Until proven otherwise we assume we must add a detour */
4739 if (GMT->common.R.oblique) { /* Determine if any of the 4 map corners are inside this polygon */
4740 double X, Y;
4741 gmt_set_inside_mode (GMT, NULL, GMT_IOO_SPHERICAL);
4742 gmt_xy_to_geo (GMT, &X, &Y, GMT->current.proj.rect[XLO], GMT->current.proj.rect[YLO]);
4743 GMT->current.proj.corner[0] = gmt_inonout (GMT, X, Y, S);
4744 gmt_xy_to_geo (GMT, &X, &Y, GMT->current.proj.rect[XHI], GMT->current.proj.rect[YLO]);
4745 GMT->current.proj.corner[1] = gmt_inonout (GMT, X, Y, S);
4746 gmt_xy_to_geo (GMT, &X, &Y, GMT->current.proj.rect[XHI], GMT->current.proj.rect[YHI]);
4747 GMT->current.proj.corner[2] = gmt_inonout (GMT, X, Y, S);
4748 gmt_xy_to_geo (GMT, &X, &Y, GMT->current.proj.rect[XLO], GMT->current.proj.rect[YHI]);
4749 GMT->current.proj.corner[3] = gmt_inonout (GMT, X, Y, S);
4750 need_detour = false; /* Trying a different tack for these cases */
4751 }
4752 for (k = 0; need_detour && k < S->n_rows; k++) { /* Check every point */
4753 if (doubleAlmostEqual (S->data[GMT_Y][k], p_lat)) { /* Point is exactly at the pole in question */
4754 /* We want to distinguish between a path that gently touches the pole and one that has a fake straight detour to the pole.
4755 * We assume a fake detour will have the same longitudes for this point and the previous and that they are both either +/-180 or 0. */
4756 if (k && doubleAlmostEqual (S->data[GMT_X][k], S->data[GMT_X][k-1]) && (doubleAlmostEqual (fabs (S->data[GMT_X][k]), 180.0) || gmt_M_is_zero (S->data[GMT_X][k])))
4757 need_detour = false; /* Well, what do you know. Probably arcGIS or some other handicapped program */
4758 }
4759 }
4760 if (!need_detour) { /* Do not add another detour but process via gmt_geo_polarcap_segment to handle jumps in our polygon */
4761 GMT_Report (GMT->parent, GMT_MSG_DEBUG, "Path already had a detour to the pole, skip adding another detour\n");
4762 add_pole = false;
4763 n = gmt_geo_polarcap_segment (GMT, S, &plon, &plat);
4764 if (plon != S->data[GMT_X]) /* Pointer changed so we allocated, must delete below */
4765 free_memory = true;
4766 }
4767 }
4768 if (add_pole) { /* If we get here then a detour will be needed */
4769 if ((n = gmt_geo_polarcap_segment (GMT, S, &plon, &plat)) == 0) { /* Not a global map */
4770 /* Here we must detour to the N or S pole, then resample the path */
4771 n = S->n_rows + 2; /* Add new first and last point to connect to the pole */
4772 plon = gmt_M_memory (GMT, NULL, n, double); /* This memory must be freed below */
4773 plat = gmt_M_memory (GMT, NULL, n, double);
4774 free_memory = true;
4775 t_lat = SH->pole * 90.0; /* This is presumably the correct pole, but could fail if just touching the pole */
4776 if (S->data[GMT_Y][0] * t_lat < 0.0) t_lat = -t_lat; /* Well, I'll be damned... */
4777 plat[0] = plat[n-1] = t_lat;
4778 plon[0] = S->data[GMT_X][0];
4779 plon[n-1] = S->data[GMT_X][S->n_rows-1];

Callers 1

gmt_geo_polygonsFunction · 0.85

Calls 9

gmtplot_at_poleFunction · 0.85
gmt_get_DS_hiddenFunction · 0.85
GMT_ReportFunction · 0.85
gmt_set_inside_modeFunction · 0.85
gmt_xy_to_geoFunction · 0.85
gmt_inonoutFunction · 0.85
gmt_geo_polarcap_segmentFunction · 0.85
gmt_fix_up_pathFunction · 0.85
gmtplot_geo_polygonFunction · 0.85

Tested by

no test coverage detected