| 4720 | } |
| 4721 | |
| 4722 | GMT_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]; |
no test coverage detected