123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- #include <math.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/display.h>
- #include <grass/glocale.h>
- #include "driver.h"
- #include "path.h"
- #include "clip.h"
- struct vector
- {
- double x, y;
- };
- /******************************************************************************/
- static struct path path;
- static int clip_mode = M_NONE;
- static double epsilon = 0.0;
- static struct path ll_path, clip_path, raw_path, eps_path;
- static struct vector cur;
- static struct rectangle clip;
- static int window_set;
- #define min(x,y) ((x) < (y) ? (x) : (y))
- #define max(x,y) ((x) > (y) ? (x) : (y))
- /******************************************************************************/
- static int shift_count(double dx)
- {
- return (int)floor(dx / 360);
- }
- static double shift_angle(double dx)
- {
- return shift_count(dx) * 360;
- }
- static double coerce(double x)
- {
- x += 180;
- x -= shift_angle(x);
- x -= 180;
- return x;
- }
- static int euclidify(struct path *p, int no_pole)
- {
- double ux0 = clip.left;
- double ux1 = clip.rite;
- double x0, x1;
- int lo, hi, count;
- int i;
- x0 = x1 = p->vertices[0].x;
- for (i = 1; i < p->count; i++) {
- if (fabs(p->vertices[i].y) < 89.9)
- p->vertices[i].x = p->vertices[i-1].x + coerce(p->vertices[i].x - p->vertices[i-1].x);
- x0 = min(x0, p->vertices[i].x);
- x1 = max(x1, p->vertices[i].x);
- }
- if (no_pole && fabs(p->vertices[p->count-1].x - p->vertices[0].x) > 180)
- return 0;
- lo = -shift_count(ux1 - x0);
- hi = shift_count(x1 - ux0);
- count = hi - lo + 1;
- for (i = 0; i < p->count; i++)
- p->vertices[i].x -= lo * 360;
- return count;
- }
- static void ll_wrap_path(struct path *dst, const struct path *src, int no_pole)
- {
- int count, i, j;
- path_copy(dst, src);
- count = euclidify(dst, no_pole);
- for (i = 0; i < count; i++) {
- for (j = 0; j < src->count; j++) {
- struct vertex *v = &dst->vertices[j];
- path_append(dst, v->x - i * 360, v->y, v->mode);
- }
- }
- }
- static void conv_path(struct path *dst, const struct path *src)
- {
- int i;
- path_copy(dst, src);
- for (i = 0; i < dst->count; i++) {
- struct vertex *v = &dst->vertices[i];
- v->x = D_u_to_d_col(v->x);
- v->y = D_u_to_d_row(v->y);
- }
- }
- static void reduce_path(struct path *dst, const struct path *src, double eps)
- {
- struct vertex *v = &src->vertices[0];
- int i;
- path_reset(dst);
- path_append(dst, v->x, v->y, v->mode);
- for (i = 1; i < src->count - 1; i++) {
- struct vertex *v0 = &dst->vertices[dst->count-1];
- struct vertex *v1 = &src->vertices[i];
- struct vertex *v2 = &src->vertices[i+1];
- if (fabs(v1->x - v0->x) < eps && fabs(v1->y - v0->y) < eps &&
- fabs(v1->x - v2->x) < eps && fabs(v1->y - v2->y) < eps &&
- v0->mode != P_MOVE && v1->mode != P_MOVE && (!v2->mode) != P_MOVE)
- continue;
- path_append(dst, v1->x, v1->y, v1->mode);
- }
- v = &src->vertices[src->count - 1];
- path_append(dst, v->x, v->y, v->mode);
- }
- /******************************************************************************/
- /*!
- * \brief set clipping window
- *
- * Sets the clipping window to the pixel window that corresponds
- * to the current database region. This is the default.
- *
- * \param t top
- * \param b bottom
- * \param l left
- * \param r right
- */
- void D_set_clip(double t, double b, double l, double r)
- {
- clip.left = min(l, r);
- clip.rite = max(l, r);
- clip.bot = min(b, t);
- clip.top = max(b, t);
- window_set = 1;
- }
- /*!
- * \brief set clipping window to map window
- *
- * Sets the clipping window to the pixel window that corresponds to the
- * current database region. This is the default.
- *
- * \param ~
- */
- void D_clip_to_map(void)
- {
- double t, b, l, r;
- D_get_src(&t, &b, &l, &r);
- D_set_clip(t, b, l, r);
- }
- void D_set_clip_mode(int mode)
- {
- clip_mode = mode;
- }
- void D_set_reduction(double e)
- {
- epsilon = e;
- }
- void D_line_width(double d)
- {
- COM_Line_width(d > 0 ? d : 0);
- }
- void D_get_text_box(const char *text, double *t, double *b, double *l, double *r)
- {
- double T, B, L, R;
- COM_Get_text_box(text, &T, &B, &L, &R);
- *t = D_d_to_u_row(T);
- *b = D_d_to_u_row(B);
- *l = D_d_to_u_col(L);
- *r = D_d_to_u_col(R);
- if (*t < *b) {
- double tmp = *t; *t = *b; *b = tmp;
- }
- if (*r < *l) {
- double tmp = *r; *r = *l; *l = tmp;
- }
- }
- /******************************************************************************/
- /* D_pos_abs(easting, northing): move to an absolute position
- on the display using map coordinates */
- void D_pos_abs(double x, double y)
- {
- cur.x = x;
- cur.y = y;
- x = D_u_to_d_col(x);
- y = D_u_to_d_row(y);
- COM_Pos_abs(x, y);
- }
- void D_pos_rel(double x, double y)
- {
- D_pos_abs(cur.x + x, cur.y + y);
- }
- /******************************************************************************/
- static void do_path(int no_pole)
- {
- struct path *p = &path;
- struct clip planes;
- int i;
- if (!window_set)
- D_clip_to_map();
- if (D_is_lat_lon()) {
- ll_wrap_path(&ll_path, p, no_pole);
- p = &ll_path;
- }
- switch (clip_mode) {
- case M_NONE:
- break;
- case M_CULL:
- D__set_clip_planes(&planes, &clip);
- D__cull_path(&clip_path, p, &planes);
- p = &clip_path;
- break;
- case M_CLIP:
- D__set_clip_planes(&planes, &clip);
- D__clip_path(&clip_path, p, &planes);
- p = &clip_path;
- break;
- }
- conv_path(&raw_path, p);
- p = &raw_path;
- if (epsilon > 0) {
- reduce_path(&eps_path, p, epsilon);
- p = &eps_path;
- }
- COM_Begin();
- for (i = 0; i < p->count; i++) {
- struct vertex *v = &p->vertices[i];
- switch (v->mode)
- {
- case P_MOVE:
- COM_Move(v->x, v->y);
- break;
- case P_CONT:
- COM_Cont(v->x, v->y);
- break;
- case P_CLOSE:
- COM_Close();
- break;
- }
- }
- }
- void D_begin(void)
- {
- path_begin(&path);
- }
- void D_end(void)
- {
- }
- /* D_move_abs(x,y): move to an absolute position on the display using
- display pixel coordinates */
- void D_move_abs(double x, double y)
- {
- path_move(&path, x, y);
- cur.x = x;
- cur.y = y;
- }
- void D_cont_abs(double x, double y)
- {
- path_cont(&path, x, y);
- cur.x = x;
- cur.y = y;
- }
- void D_close(void)
- {
- path_close(&path);
- }
- void D_stroke(void)
- {
- do_path(0);
- COM_Stroke();
- }
- void D_fill(void)
- {
- do_path(1);
- COM_Fill();
- }
- void D_dots(void)
- {
- struct path *p = &path;
- int i;
- if (!window_set)
- D_clip_to_map();
- for (i = 0; i < p->count; i++) {
- struct vertex *v = &p->vertices[i];
- double x = v->x;
- double y = v->y;
- if (D_is_lat_lon())
- x = coerce(x);
- if (clip_mode != M_NONE) {
- if (x < clip.left || x > clip.rite)
- continue;
- if (y < clip.bot || y > clip.top)
- continue;
- }
- x = D_u_to_d_col(x);
- y = D_u_to_d_row(y);
- COM_Point(x, y);
- }
- }
- /******************************************************************************/
- static void poly_abs(const double *x, const double *y, int n)
- {
- int i;
- if (n < 2)
- return;
- D_begin();
- D_move_abs(x[0], y[0]);
- for (i = 1; i < n; i++)
- D_cont_abs(x[i], y[i]);
- }
- void D_polyline_abs(const double *x, const double *y, int n)
- {
- poly_abs(x, y, n);
- D_stroke();
- }
- void D_polygon_abs(const double *x, const double *y, int n)
- {
- poly_abs(x, y, n);
- D_close();
- D_fill();
- }
- void D_polydots_abs(const double *x, const double *y, int n)
- {
- poly_abs(x, y, n);
- D_dots();
- }
- void D_line_abs(double x1, double y1, double x2, double y2)
- {
- D_begin();
- D_move_abs(x1, y1);
- D_cont_abs(x2, y2);
- D_end();
- D_stroke();
- }
- void D_box_abs(double x1, double y1, double x2, double y2)
- {
- struct vector save = cur;
- D_begin();
- D_move_abs(x1, y1);
- D_cont_abs(x2, y1);
- D_cont_abs(x2, y2);
- D_cont_abs(x1, y2);
- D_close();
- D_end();
- D_fill();
- cur = save;
- }
- /******************************************************************************/
- static void poly_rel(const double *x, const double *y, int n)
- {
- int i;
- if (n < 2)
- return;
- D_begin();
- D_move_rel(x[0], y[0]);
- for (i = 1; i < n; i++)
- D_cont_rel(x[i], y[i]);
- }
- void D_move_rel(double x, double y)
- {
- D_move_abs(cur.x + x, cur.y + y);
- }
- void D_cont_rel(double x, double y)
- {
- D_cont_abs(cur.x + x, cur.y + y);
- }
- void D_polydots_rel(const double *x, const double *y, int n)
- {
- poly_rel(x, y, n);
- D_dots();
- }
- void D_polyline_rel(const double *x, const double *y, int n)
- {
- poly_rel(x, y, n);
- D_stroke();
- }
- void D_polygon_rel(const double *x, const double *y, int n)
- {
- poly_rel(x, y, n);
- D_close();
- D_fill();
- }
- void D_line_rel(double x1, double y1, double x2, double y2)
- {
- cur.x += x1;
- cur.y += y1;
- x1 = cur.x;
- y1 = cur.y;
- cur.x += x2;
- cur.y += y2;
- x2 = cur.x;
- y2 = cur.y;
- D_line_abs(x1, y1, x2, y2);
- }
- void D_box_rel(double x2, double y2)
- {
- D_box_abs(cur.x, cur.y, cur.x + x2, cur.y + y2);
- }
- /******************************************************************************/
|