8 * Copyright: (c) 1993, AIAI, University of Edinburgh
11 // Must be a comment as this file is #include\'d by wb_dc.cc
12 /* static const char sccsid[] = "@(#)xfspline.cc 1.3 5/9/94"; */
15 * FIG : Facility for Interactive Generation of figures
16 * Copyright (c) 1985 by Supoj Sutanthavibul
22 ////#define wx_round(a) (int)((a)+.5)
23 //#define wx_round(a) (a)
25 class wxSpline: public wxObject
31 wxSpline(wxList *list);
32 void DeletePoints(void);
34 // Doesn't delete points
38 void wx_draw_open_spline(wxDC *dc, wxSpline *spline);
41 void wx_draw_open_spline_ps(wxPostScriptDC *dc, wxSpline *s);
44 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
45 double a3, double b3, double a4, double b4);
46 void wx_clear_stack(void);
47 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
48 double *y3, double *x4, double *y4);
49 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
50 double x4, double y4);
51 static bool wx_spline_add_point(double x, double y);
52 static void wx_spline_draw_point_array(wxDC *dc);
53 wxSpline *wx_make_spline(int x1, int y1, int x2, int y2, int x3, int y3);
55 void wxDC::DrawSpline(int n, wxPoint points[])
59 for (i =0; i < n; i++)
60 list.Append((wxObject*)&points[i]);
61 DrawSpline((wxList *)&list);
64 void wxDC::DrawSpline(wxList *list)
66 wxSpline spline(list);
68 wx_draw_open_spline(this, &spline);
72 wxList wx_spline_point_list;
74 void wx_draw_open_spline(wxDC *dc, wxSpline *spline)
77 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
78 double x1, y1, x2, y2;
80 wxNode *node = spline->points->First();
81 p = (wxPoint *)node->Data();
87 p = (wxPoint *)node->Data();
91 cx1 = (double)((x1 + x2) / 2);
92 cy1 = (double)((y1 + y2) / 2);
93 cx2 = (double)((cx1 + x2) / 2);
94 cy2 = (double)((cy1 + y2) / 2);
96 wx_spline_add_point(x1, y1);
98 while ((node = node->Next()) != NULL)
100 p = (wxPoint *)node->Data();
105 cx4 = (double)(x1 + x2) / 2;
106 cy4 = (double)(y1 + y2) / 2;
107 cx3 = (double)(x1 + cx4) / 2;
108 cy3 = (double)(y1 + cy4) / 2;
110 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
114 cx2 = (double)(cx1 + x2) / 2;
115 cy2 = (double)(cy1 + y2) / 2;
118 wx_spline_add_point((double)wx_round(cx1), (double)wx_round(cy1));
119 wx_spline_add_point(x2, y2);
121 wx_spline_draw_point_array(dc);
126 void wx_draw_open_spline_ps(wxPostScriptDC *dc, wxSpline *s)
128 double a, b, c, d, x1, y1, x2, y2, x3, y3;
130 wxNode *node = s->points->First();
131 p = (wxPoint *)node->Data();
133 x1 = p->x; y1 = p->y;
136 p = (wxPoint *)node->Data();
138 x3 = a = (double)(x1 + c) / 2;
139 y3 = b = (double)(y1 + d) / 2;
141 *(dc->GetStream()) << "newpath " << x1 << " " << dc->GetYOrigin() - y1 << " moveto " << x3 << " " << dc->GetYOrigin() - y3;
142 *(dc->GetStream()) << " lineto\n";
143 dc->CalcBoundingBox((double)x1, (double)(dc->GetYOrigin() - y1));
144 dc->CalcBoundingBox((double)x3, (double)(dc->GetYOrigin() - y3));
146 while ((node = node->Next()) != NULL)
148 q = (wxPoint *)node->Data();
153 x3 = (double)(x2 + c) / 2;
154 y3 = (double)(y2 + d) / 2;
155 *(dc->GetStream()) << x1 << " " << dc->GetYOrigin() - y1 << " " << x2 << " " << dc->GetYOrigin() - y2 << " ";
156 *(dc->GetStream()) << x3 << " " << dc->GetYOrigin() - y3 << " DrawSplineSection\n";
158 dc->CalcBoundingBox((double)x1, (double)(dc->GetYOrigin() - y1));
159 dc->CalcBoundingBox((double)x3, (double)(dc->GetYOrigin() - y3));
162 * At this point, (x2,y2) and (c,d) are the position of the
163 * next-to-last and last point respectively, in the point list
165 *(dc->GetStream()) << c << " " << dc->GetYOrigin() - d << " lineto stroke\n";
169 /********************* CURVES FOR SPLINES *****************************
171 The following spline drawing routine is from
173 "An Algorithm for High-Speed Curve Generation"
174 by George Merrill Chaikin,
175 Computer Graphics and Image Processing, 3, Academic Press,
180 "On Chaikin's Algorithm" by R. F. Riesenfeld,
181 Computer Graphics and Image Processing, 4, Academic Press,
184 ***********************************************************************/
186 #define half(z1, z2) ((z1+z2)/2.0)
189 /* iterative version */
191 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
194 register double xmid, ymid;
195 double x1, y1, x2, y2, x3, y3, x4, y4;
198 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
200 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
201 xmid = (double)half(x2, x3);
202 ymid = (double)half(y2, y3);
203 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
204 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
205 wx_spline_add_point((double)wx_round(x1), (double)wx_round(y1));
206 wx_spline_add_point((double)wx_round(xmid), (double)wx_round(ymid));
208 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
209 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
210 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
211 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
217 /* utilities used by spline drawing routines */
220 typedef struct wx_spline_stack_struct {
221 double x1, y1, x2, y2, x3, y3, x4, y4;
225 #define SPLINE_STACK_DEPTH 20
226 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
227 static Stack *wx_stack_top;
228 static int wx_stack_count;
230 void wx_clear_stack(void)
232 wx_stack_top = wx_spline_stack;
236 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
238 wx_stack_top->x1 = x1;
239 wx_stack_top->y1 = y1;
240 wx_stack_top->x2 = x2;
241 wx_stack_top->y2 = y2;
242 wx_stack_top->x3 = x3;
243 wx_stack_top->y3 = y3;
244 wx_stack_top->x4 = x4;
245 wx_stack_top->y4 = y4;
250 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
251 double *x3, double *y3, double *x4, double *y4)
253 if (wx_stack_count == 0)
257 *x1 = wx_stack_top->x1;
258 *y1 = wx_stack_top->y1;
259 *x2 = wx_stack_top->x2;
260 *y2 = wx_stack_top->y2;
261 *x3 = wx_stack_top->x3;
262 *y3 = wx_stack_top->y3;
263 *x4 = wx_stack_top->x4;
264 *y4 = wx_stack_top->y4;
268 static bool wx_spline_add_point(double x, double y)
270 wxPoint *point = new wxPoint ;
273 wx_spline_point_list.Append((wxObject*)point);
277 static void wx_spline_draw_point_array(wxDC *dc)
279 dc->DrawLines(&wx_spline_point_list, (double)0.0, (double)0.0);
280 wxNode *node = wx_spline_point_list.First();
283 wxPoint *point = (wxPoint *)node->Data();
286 node = wx_spline_point_list.First();
290 wxSpline::wxSpline(wxList *list)
295 wxSpline::~wxSpline(void)
299 void wxSpline::DeletePoints(void)
301 for(wxNode *node = points->First(); node; node = points->First())
303 wxPoint *point = (wxPoint *)node->Data();
312 // Make a 3-point spline
313 void wxPostScriptDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3)
315 wxList *point_list = new wxList;
317 wxPoint *point1 = new wxPoint;
318 point1->x = x1; point1->y = y1;
319 point_list->Append((wxObject*)point1);
321 wxPoint *point2 = new wxPoint;
322 point2->x = x2; point2->y = y2;
323 point_list->Append((wxObject*)point2);
325 wxPoint *point3 = new wxPoint;
326 point3->x = x3; point3->y = y3;
327 point_list->Append((wxObject*)point3);
329 wxSpline spline(point_list);
331 wx_draw_open_spline_ps(this, &spline);
332 spline.DeletePoints();
335 void wxPostScriptDC::DrawSpline(wxList *list)
337 wxSpline spline(list);
339 wx_draw_open_spline_ps(this, &spline);
342 void wxPostScriptDC::DrawSpline(int n, wxPoint points[])
346 for (i =0; i < n; i++)
347 list.Append((wxObject*)&points[i]);
348 DrawSpline((wxList *)&list);
352 #endif // USE_POSTSCRIPT
354 #endif // USE_SPLINES