1 /*****************************************************************************
4 ** Name: sgp.c Simple Graphics Package
5 ** Programmer: Kevin Rosenberg
7 ** This is part of the CTSim program
8 ** Copyright (C) 1983-2000 Kevin Rosenberg
10 ** $Id: sgp.cpp,v 1.3 2000/06/19 19:16:17 kevin Exp $
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License (version 2) as
14 ** published by the Free Software Foundation.
16 ** This program is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ** GNU General Public License for more details.
21 ** You should have received a copy of the GNU General Public License
22 ** along with this program; if not, write to the Free Software
23 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ******************************************************************************/
28 #include "ctsupport.h"
32 static SGP_ID _sgp2_cwin = NULL;
34 extern CHARSPEC cspec;
38 * sgp2_init Initialize 2 graphics system
45 sgp2_init (int xsize, int ysize, const char *win_title )
57 gid->pw_xsize = xsize;
58 gid->pw_ysize = ysize;
59 strncpy(gid->title, win_title, sizeof(gid->title));
61 gid->recalc_mc_to_ndc = TRUE;
62 gid->recalc_ndc_to_mc = TRUE;
63 ident_gmtx_2 (gid->wc_to_ndc_x);
64 ident_gmtx_2 (gid->mc_to_ndc_x);
65 ident_gmtx_2 (gid->ndc_to_mc_x);
66 ident_gmtx_2 (gid->ctm_2_x);
68 sgp2_window (0., 0., 1., 1.);
69 sgp2_viewport (0., 0., 1., 1.);
71 sgp2_move_abs (0., 0.);
74 gid->g2_id = g2_open_X11X (gid->pw_xsize, gid->pw_ysize, 10, 10, gid->title, gid->title, NULL, -1, -1);
77 _sgp2_init_dev (_sgp2_cwin);
84 sgp2_close (SGP_ID gid)
87 g2_close (gid->g2_id);
89 if (gid == _sgp2_cwin)
96 sgp2_set_active_win (SGP_ID gid)
102 sgp2_get_active_win (void)
109 * sgp2_clear Clear window
116 if (_sgp_cwin != NULL)
117 g2_clear (gid->g2_id);
122 * sgp2_window Set window in world coordinates
126 sgp2_window (double xmin, double ymin, double xmax, double ymax)
128 if (_sgp2_cwin == NULL)
131 if (xmin >= xmax || ymin >= ymax) {
132 sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_window]");
136 _sgp2_cwin->xw_min = xmin;
137 _sgp2_cwin->yw_min = ymin;
138 _sgp2_cwin->xw_max = xmax;
139 _sgp2_cwin->yw_max = ymax;
145 * sgp2_viewport Set viewport in NDC
149 sgp2_viewport (double xmin, double ymin, double xmax, double ymax)
151 if (_sgp2_cwin == NULL)
154 if (xmin >= xmax || ymin >= ymax) {
155 sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_viewport]");
159 _sgp2_cwin->xv_min = xmin;
160 _sgp2_cwin->yv_min = ymin;
161 _sgp2_cwin->xv_max = xmax;
162 _sgp2_cwin->yv_max = ymax;
165 _sgp2_cwin->view[0] = xmin; /* Array for clip_rect() */
166 _sgp2_cwin->view[1] = ymin;
167 _sgp2_cwin->view[2] = xmax;
168 _sgp2_cwin->view[3] = ymax;
173 * sgp2_frame_vpt draw box around viewport
177 sgp2_frame_vpt (void)
179 if (_sgp2_cwin == NULL)
182 _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 0);
183 _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_min, 1);
184 _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_max, 1);
185 _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_max, 1);
186 _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 1);
191 * calc_wc_to_ndc Calculate transform matrix
195 calc_wc_to_ndc (void)
199 if (_sgp2_cwin == NULL)
202 sx = (_sgp2_cwin->xv_max - _sgp2_cwin->xv_min) / (_sgp2_cwin->xw_max - _sgp2_cwin->xw_min);
203 sy = (_sgp2_cwin->yv_max - _sgp2_cwin->yv_min) / (_sgp2_cwin->yw_max - _sgp2_cwin->yw_min);
205 ident_gmtx_2 (_sgp2_cwin->wc_to_ndc_x);
206 _sgp2_cwin->wc_to_ndc_x[0][0] = sx;
207 _sgp2_cwin->wc_to_ndc_x[2][0] = _sgp2_cwin->xv_min - sx * _sgp2_cwin->xw_min;
208 _sgp2_cwin->wc_to_ndc_x[1][1] = sy;
209 _sgp2_cwin->wc_to_ndc_x[2][1] = _sgp2_cwin->yv_min - sy * _sgp2_cwin->yw_min;
211 _sgp2_cwin->recalc_mc_to_ndc = TRUE;
212 _sgp2_cwin->recalc_ndc_to_mc = TRUE;
217 calc_ndc_to_mc (void)
219 if (_sgp2_cwin == NULL)
222 if (_sgp2_cwin->recalc_mc_to_ndc) {
223 mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
224 _sgp2_cwin->recalc_mc_to_ndc = FALSE;
227 invert_gmtx_2 (_sgp2_cwin->mc_to_ndc_x, _sgp2_cwin->ndc_to_mc_x);
228 _sgp2_cwin->recalc_ndc_to_mc = FALSE;
233 * wc_to_ndc Map from world coordinates to NDC
237 wc_to_ndc (double xw, double yw, double *xn, double *yn)
239 if (_sgp2_cwin == NULL)
242 if (_sgp2_cwin->recalc_mc_to_ndc) {
243 mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
244 _sgp2_cwin->recalc_mc_to_ndc = FALSE;
247 *xn = xw * _sgp2_cwin->mc_to_ndc_x[0][0] + yw * _sgp2_cwin->mc_to_ndc_x[1][0] + _sgp2_cwin->mc_to_ndc_x[2][0];
248 *yn = xw * _sgp2_cwin->mc_to_ndc_x[0][1] + yw * _sgp2_cwin->mc_to_ndc_x[1][1] + _sgp2_cwin->mc_to_ndc_x[2][1];
252 /*==============================================================*/
253 /* map from normalized device coords. to world coordinates */
254 /*==============================================================*/
256 ndc_to_wc (double xn, double yn, double *xw, double *yw)
258 if (_sgp2_cwin == NULL)
261 if (_sgp2_cwin->recalc_ndc_to_mc) {
263 _sgp2_cwin->recalc_ndc_to_mc = FALSE;
266 *xw = xn * _sgp2_cwin->ndc_to_mc_x[0][0] + yn * _sgp2_cwin->ndc_to_mc_x[1][0] + _sgp2_cwin->ndc_to_mc_x[2][0];
267 *yw = xn * _sgp2_cwin->ndc_to_mc_x[0][1] + yn * _sgp2_cwin->ndc_to_mc_x[1][1] + _sgp2_cwin->ndc_to_mc_x[2][1];
271 /*==============================================================*/
273 /*==============================================================*/
275 sgp2_color (int icol)
280 /*==============================================================*/
281 /* set line style. Pass 16 bit repeating pattern */
282 /*==============================================================*/
284 sgp2_line_style (int style)
289 /*==============================================================*/
290 /* absolute draw to */
291 /*==============================================================*/
293 sgp2_line_abs (double x, double y)
295 double x1, y1, x2, y2;
297 if (_sgp2_cwin == NULL)
300 wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &x1, &y1);
301 wc_to_ndc (x, y, &x2, &y2);
303 if (clip_rect (x1, y1, x2, y2, _sgp2_cwin->view) == TRUE) { /* clip to viewport */
304 _sgp2_stylus (_sgp2_cwin, x1, y1, 0); /* move to first point */
305 _sgp2_stylus (_sgp2_cwin, x2, y2, 1); /* draw to second point */
308 _sgp2_cwin->curx = x;
309 _sgp2_cwin->cury = y;
312 /*==============================================================*/
313 /* absolute move to */
314 /*==============================================================*/
316 sgp2_move_abs (double x, double y)
318 if (_sgp2_cwin == NULL)
321 _sgp2_cwin->curx = x;
322 _sgp2_cwin->cury = y; /* moves are not clipped */
325 /*==============================================================*/
327 /*==============================================================*/
329 sgp2_line_rel (double x, double y)
331 if (_sgp2_cwin != NULL)
332 sgp2_line_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
335 /*==============================================================*/
337 /*==============================================================*/
339 sgp2_move_rel (double x, double y)
341 if (_sgp2_cwin != NULL)
342 sgp2_move_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
345 /*==============================================================*/
347 /*==============================================================*/
349 sgp2_draw_text (char *message)
352 if (_sgp2_cwin == NULL)
355 wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &sx, &sy);
356 _sgp2_stylus (_sgp2_cwin, sx, sy, 0); /* move to location */
357 _sgp2_dev_text (_sgp2_cwin, message);
361 charsize (double wid, double height)
363 _sgp2_set_text (_sgp2_cwin, wid, height, cspec.textangle, cspec.font);
367 textangle (double angle)
369 _sgp2_set_text (_sgp2_cwin, cspec.width, cspec.height, angle, cspec.font);
373 sgp2_polyline_abs (double x[], double y[], int n)
375 double x1, y1, x2, y2;
379 if (_sgp2_cwin == NULL || n < 2)
382 wc_to_ndc (x[0], y[0], &x1, &y1);
383 wc_to_ndc (x[1], y[1], &x2, &y2);
385 xt = x2; /* don't pass (x2,y2) to clip, we need them */
386 yt = y2; /* as the beginning point of the next line */
388 if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
389 _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
390 _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
393 for (i = 2; i < n; i++) {
394 x1 = x2; /* NDC endpoint of last line */
396 wc_to_ndc (x[i], y[i], &x2, &y2);
399 if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
400 _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
401 _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
408 sgp2_mark_abs (double x, double y)
412 if (_sgp2_cwin == NULL)
415 wc_to_ndc (x, y, &xndc, &yndc);
416 markndc (_sgp2_cwin, xndc, yndc);
417 _sgp2_cwin->curx = x;
418 _sgp2_cwin->cury = y;
423 sgp2_mark_rel (double x, double y)
425 sgp2_mark_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
430 sgp2_point_abs (double x, double y)
434 if (_sgp2_cwin == NULL)
437 wc_to_ndc (x, y, &xndc, &yndc);
438 pntndc (_sgp2_cwin, xndc, yndc);
439 _sgp2_cwin->curx = x;
440 _sgp2_cwin->cury = y;
445 sgp2_point_rel (double x, double y)
447 sgp2_point_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
452 * sgp2_draw_rect Draw box in graphics mode
455 * drawbox (xmin, ymin, xmax, ymax)
456 * double xmin, ymin Lower left corner of box
457 * double xmax, ymax Upper left corner of box
460 * This routine leaves the current position of graphic cursor at lower
461 * left corner of box.
465 sgp2_draw_rect(double xmin, double ymin, double xmax, double ymax)
467 sgp2_move_abs (xmin, ymin);
468 sgp2_line_abs (xmax, ymin);
469 sgp2_line_abs (xmax, ymax);
470 sgp2_line_abs (xmin, ymax);
471 sgp2_line_abs (xmin, ymin);
475 * sgp2_circle - draw circle of radius r at current center
479 sgp2_draw_circle (const double r)
481 sgp2_draw_arc (0.0, 7.0, r);
484 /*==============================================================*/
485 /* draw arc around current center. pass angles and radius */
486 /*==============================================================*/
489 sgp2_draw_arc (double start, double stop, const double r)
491 double c, s, theta, angle;
494 if ((stop-start) > 2 * PI)
495 stop = start + 2 * PI;
496 if ((start-stop) > 2 * PI)
497 stop = start + 2 * PI;
498 while (start >= stop)
501 x = r * cos ((double) start);
502 y = r * sin ((double) start);
503 sgp2_move_rel (x, y); /* move from center to start of arc */
505 theta = 5 * PI / 180;
509 for (angle = start; angle < stop - theta; angle += theta) {
512 sgp2_line_rel (xp - x, yp - y);
516 c = cos (stop - angle);
517 s = sin (stop - angle);
520 sgp2_line_rel (xp - x, yp - y);
522 x = r * cos ((double) stop);
523 y = r * sin ((double) stop);
524 sgp2_move_rel (-x, -y); /* move back to center of circle */
528 /*----------------------------------------------------------------------*/
529 /* Current Transformation Matrix Routine */
530 /*----------------------------------------------------------------------*/
534 * ctm_clr_2 Clear current transformation matrix
555 * OUT GRFMTX_2D m Copy of ctm
559 ctm_get_2 (GRFMTX_2D m)
563 if (_sgp2_cwin == NULL)
566 for (x = 0; x < 3; x++)
567 for (y = 0; y < 3; y++)
568 m[x][y] = _sgp2_cwin->ctm_2_x[x][y];
573 * ctm_set_2 Set ctm to a matrix
577 * IN GRFMTX m New ctm
581 ctm_set_2 (GRFMTX_2D m)
584 if (_sgp2_cwin == NULL)
587 for (x = 0; x < 3; x++)
588 for (y = 0; y < 3; y++)
589 _sgp2_cwin->ctm_2_x[x][y] = m[x][y];
591 _sgp2_cwin->recalc_ndc_to_mc = TRUE;
592 _sgp2_cwin->recalc_mc_to_ndc = TRUE;
597 ctm_pre_mult_2 (GRFMTX_2D m)
601 mult_gmtx_2 (m, _sgp2_cwin->ctm_2_x, new_ctm);
607 ctm_post_mult_2 (GRFMTX_2D m)
611 mult_gmtx_2 (_sgp2_cwin->ctm_2_x, m, new_ctm);