| 5395 | } |
| 5396 | |
| 5397 | GMT_LOCAL unsigned int gmtplot_geo_vector_greatcircle (struct GMT_CTRL *GMT, double lon0, double lat0, double azimuth, double length, struct GMT_PEN *ppen, struct GMT_SYMBOL *S) { |
| 5398 | /* Draws a great-circle vector with our without heads, etc. There are some complications to consider: |
| 5399 | * When there are no heads it is simple. If +n is on we may shrink the line thickness. |
| 5400 | * With heads there are these cases: |
| 5401 | * Head length is longer than 90% of the vector length. We then skip the head and return 1 |
| 5402 | * +n<norm> is in effect. We shrink vector pen and head length. Still, the shrunk head |
| 5403 | * may be longer than 90% of the vector length. We then shrink head (not pen) further and return 2 |
| 5404 | */ |
| 5405 | |
| 5406 | uint64_t n1, n2, n, add; |
| 5407 | int heads, side[2], outline = 0; |
| 5408 | unsigned int warn = 0; |
| 5409 | size_t n_alloc; |
| 5410 | bool perspective, pure; |
| 5411 | double tlon, tlat, mlon, mlat, P[3], Ax[3], Bx[3], h_length_limit; |
| 5412 | double dr[2] = {0.0, 0.0}, az[2] = {0.0, 0.0}, oaz[2] = {0.0, 0.0}, off[2] = {0.0, 0.0}; |
| 5413 | double da = 0.0, dshift[2] = {0.0, 0.0}, s = 1.0, s1 = 1.0, s2 = 1.0, olon[2], olat[2], head_length, arc_width, rot, scl[2]; |
| 5414 | double *xp = NULL, *yp = NULL, *xp2 = NULL, *yp2 = NULL; |
| 5415 | double *rgb = S->v.fill.rgb; |
| 5416 | struct GMT_CIRCLE C; |
| 5417 | |
| 5418 | /* We must determine points A and B, whose great-circle connector is the arc we seek to draw */ |
| 5419 | gmtplot_gcircle_sub (GMT, lon0, lat0, azimuth, length, S, &C); |
| 5420 | perspective = gmt_M_is_perspective (GMT); |
| 5421 | |
| 5422 | /* Here we have the endpoints A and B of the great (or small) circle arc */ |
| 5423 | |
| 5424 | /* If shrink-option (+n) is active we may have to scale down head attributes and pen width */ |
| 5425 | pure = (S->v.v_norm == -1.0f); /* True if no shrinking has been specified */ |
| 5426 | heads = PSL_vec_head (S->v.status); /* Return head selection as 0-3 */ |
| 5427 | h_length_limit = C.r0; /* Max length of arrow in degrees to ensure the stem is still showing */ |
| 5428 | if (heads == 3) h_length_limit *= 0.5; /* Split this length between the two heads */ |
| 5429 | if (heads && !pure) { /* Need to determine head length in degrees */ |
| 5430 | double max_length; |
| 5431 | az[0] = gmt_az_backaz (GMT, C.lon[0], C.lat[0], C.lon[1], C.lat[1], false); /* Compute the azimuth from A to B at A along great circle */ |
| 5432 | scl[0] = (perspective) ? S->v.scale : gmtplot_get_local_scale (GMT, C.lon[0], C.lat[0], 0.001 * C.r, az[0]); /* Get local deg/inch scale at A in az[0] direction */ |
| 5433 | dr[0] = scl[0] * S->size_x; /* This is arrow head length in degrees, approximately */ |
| 5434 | az[1] = gmt_az_backaz (GMT, C.lon[1], C.lat[1], C.lon[0], C.lat[0], false); /* Compute the azimuth from B to A at B along great circle */ |
| 5435 | scl[1] = (perspective) ? S->v.scale : gmtplot_get_local_scale (GMT, C.lon[1], C.lat[1], 0.01 * C.r, az[1]); /* Get local deg/inch scale */ |
| 5436 | dr[1] = scl[1] * S->size_x; /* This is arrow head length in degrees, approximately, adjusted for ~pen thickness to ensure no gap between head and line */ |
| 5437 | max_length = MAX (dr[0], dr[1]); |
| 5438 | if (max_length > h_length_limit) { |
| 5439 | s2 = h_length_limit / max_length; |
| 5440 | if (s2 < S->v.v_norm_limit) s2 = S->v.v_norm_limit; |
| 5441 | warn = 2; |
| 5442 | } |
| 5443 | } |
| 5444 | |
| 5445 | /* Might have to shrink things */ |
| 5446 | |
| 5447 | s1 = gmt_get_vector_shrinking (GMT, &(S->v), S->v.value, C.r0); /* Vector attribute shrinking factor or 1 */ |
| 5448 | |
| 5449 | if (s1 < s2) { /* Pick the smallest scale required for head shrinking */ |
| 5450 | s = s1; |
| 5451 | warn = 0; /* When requesting +n there is no warning unless s2 is the smaller scale */ |
| 5452 | } |
| 5453 | else |
| 5454 | s = s2; |
no test coverage detected