| 4881 | } |
| 4882 | |
| 4883 | GMT_LOCAL void gmtplot_circle_pen_poly (struct GMT_CTRL *GMT, double *A, double *B, bool longway, double rot, struct GMT_PEN *pen, struct GMT_SYMBOL *S, struct GMT_CIRCLE *C, double scale) { |
| 4884 | /* Given vectors A and B, return a small circle polygon path sampled every step that approximates a pen of given width |
| 4885 | * drawn on the map. Use small circle pole and its opening rot */ |
| 4886 | uint64_t k, n, n2; |
| 4887 | double Ai[3], Ao[3], Px[3], X[3], R[3][3], R0[3][3], w, step; |
| 4888 | struct GMT_DATASEGMENT *L = NULL; |
| 4889 | gmt_M_unused(B); |
| 4890 | |
| 4891 | gmt_cross3v (GMT, A, C->P, Px); /* Px is Pole to plane through A and P */ |
| 4892 | gmt_normalize3v (GMT, Px); /* Rotation pole unit vector */ |
| 4893 | /* Rotate A back/fore by rotation angle of +/- pen halfwidth about Px */ |
| 4894 | w = 0.5 * scale * pen->width * GMT->session.u2u[GMT_PT][GMT_INCH] * S->v.scale; /* Half-width of pen in degrees */ |
| 4895 | gmt_make_rot_matrix2 (GMT, Px, +w, R); /* Rotation of rot_v degrees about pole P */ |
| 4896 | gmt_matrix_vect_mult (GMT, 3U, R, A, Ai); /* Get Ai = R * A */ |
| 4897 | gmt_make_rot_matrix2 (GMT, Px, -w, R); /* Rotation of rot_v degrees about pole P */ |
| 4898 | gmt_matrix_vect_mult (GMT, 3U, R, A, Ao); /* Get Ao = R * A */ |
| 4899 | if (longway) rot = 360.0 - rot; |
| 4900 | |
| 4901 | step = GMT->current.map.path_step; /* Use default map-step if given as 0 */ |
| 4902 | n = lrint (ceil (fabs (rot) / step)) + 1; /* Number of segments needed for smooth curve from A to B inclusive */ |
| 4903 | step = D2R * rot / (n - 1); /* Adjust step for exact fit, convert to radians */ |
| 4904 | L = GMT_Alloc_Segment (GMT->parent, GMT_NO_STRINGS, 2*n+1, 2, NULL, NULL); /* Allocate polygon to draw filled path */ |
| 4905 | n2 = 2*n-1; |
| 4906 | gmtlib_init_rot_matrix (R0, C->P); /* Get partial rotation matrix since no actual angle is applied yet */ |
| 4907 | for (k = 0; k < n; k++) { /* March along the arc */ |
| 4908 | w = k * step; /* Opening angle from A to this point X */ |
| 4909 | gmt_M_memcpy (R, R0, 9U, double); /* Get a copy of the "0-angle" rotation matrix */ |
| 4910 | gmtlib_load_rot_matrix (w, R, C->P); /* Build the actual rotation matrix for this angle */ |
| 4911 | gmt_matrix_vect_mult (GMT, 3U, R, Ai, X); /* Rotate point Ai towards B and get X */ |
| 4912 | gmt_cart_to_geo (GMT, &L->data[GMT_Y][k], &L->data[GMT_X][k], X, true); /* Get lon/lat of this point along arc */ |
| 4913 | gmt_matrix_vect_mult (GMT, 3U, R, Ao, X); /* Rotate point Ai towards B and get X */ |
| 4914 | gmt_cart_to_geo (GMT, &L->data[GMT_Y][n2-k], &L->data[GMT_X][n2-k], X, true); /* Get lon/lat of this point along arc */ |
| 4915 | } |
| 4916 | L->data[GMT_X][2*n] = L->data[GMT_X][0]; /* Explicitly close the polygon */ |
| 4917 | L->data[GMT_Y][2*n] = L->data[GMT_Y][0]; |
| 4918 | |
| 4919 | /* Plot pen as a closed filled polygon without outline */ |
| 4920 | PSL_command (GMT->PSL, "V\n"); |
| 4921 | gmt_setpen (GMT, pen); /* Set pen width just so later setpen's will work */ |
| 4922 | PSL_setfill (GMT->PSL, pen->rgb, 0); /* Fill, no outline */ |
| 4923 | gmt_geo_polygons (GMT, L); /* "Draw" the line */ |
| 4924 | PSL_command (GMT->PSL, "U\n"); |
| 4925 | |
| 4926 | gmt_free_segment (GMT, &L); |
| 4927 | } |
| 4928 | |
| 4929 | GMT_LOCAL void gmtplot_gcircle_sub (struct GMT_CTRL *GMT, double lon0, double lat0, double azimuth, double length, struct GMT_SYMBOL *S, struct GMT_CIRCLE *C) { |
| 4930 | /* We must determine points A and B, whose great-circle connector is the arc we seek to draw */ |
no test coverage detected