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 if (dc->GetAutoSetting())
131 dc->SetPen(* dc->GetPen());
133 wxNode *node = s->points->First();
134 p = (wxPoint *)node->Data();
136 x1 = p->x; y1 = p->y;
139 p = (wxPoint *)node->Data();
141 x3 = a = (double)(x1 + c) / 2;
142 y3 = b = (double)(y1 + d) / 2;
144 *(dc->GetStream()) << "newpath " << x1 << " " << dc->GetYOrigin() - y1 << " moveto " << x3 << " " << dc->GetYOrigin() - y3;
145 *(dc->GetStream()) << " lineto\n";
146 dc->CalcBoundingBox((double)x1, (double)(dc->GetYOrigin() - y1));
147 dc->CalcBoundingBox((double)x3, (double)(dc->GetYOrigin() - y3));
149 while ((node = node->Next()) != NULL)
151 q = (wxPoint *)node->Data();
156 x3 = (double)(x2 + c) / 2;
157 y3 = (double)(y2 + d) / 2;
158 *(dc->GetStream()) << x1 << " " << dc->GetYOrigin() - y1 << " " << x2 << " " << dc->GetYOrigin() - y2 << " ";
159 *(dc->GetStream()) << x3 << " " << dc->GetYOrigin() - y3 << " DrawSplineSection\n";
161 dc->CalcBoundingBox((double)x1, (double)(dc->GetYOrigin() - y1));
162 dc->CalcBoundingBox((double)x3, (double)(dc->GetYOrigin() - y3));
165 * At this point, (x2,y2) and (c,d) are the position of the
166 * next-to-last and last point respectively, in the point list
168 *(dc->GetStream()) << c << " " << dc->GetYOrigin() - d << " lineto stroke\n";
172 /********************* CURVES FOR SPLINES *****************************
174 The following spline drawing routine is from
176 "An Algorithm for High-Speed Curve Generation"
177 by George Merrill Chaikin,
178 Computer Graphics and Image Processing, 3, Academic Press,
183 "On Chaikin's Algorithm" by R. F. Riesenfeld,
184 Computer Graphics and Image Processing, 4, Academic Press,
187 ***********************************************************************/
189 #define half(z1, z2) ((z1+z2)/2.0)
192 /* iterative version */
194 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
197 register double xmid, ymid;
198 double x1, y1, x2, y2, x3, y3, x4, y4;
201 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
203 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
204 xmid = (double)half(x2, x3);
205 ymid = (double)half(y2, y3);
206 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
207 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
208 wx_spline_add_point((double)wx_round(x1), (double)wx_round(y1));
209 wx_spline_add_point((double)wx_round(xmid), (double)wx_round(ymid));
211 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
212 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
213 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
214 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
220 /* utilities used by spline drawing routines */
223 typedef struct wx_spline_stack_struct {
224 double x1, y1, x2, y2, x3, y3, x4, y4;
228 #define SPLINE_STACK_DEPTH 20
229 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
230 static Stack *wx_stack_top;
231 static int wx_stack_count;
233 void wx_clear_stack(void)
235 wx_stack_top = wx_spline_stack;
239 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
241 wx_stack_top->x1 = x1;
242 wx_stack_top->y1 = y1;
243 wx_stack_top->x2 = x2;
244 wx_stack_top->y2 = y2;
245 wx_stack_top->x3 = x3;
246 wx_stack_top->y3 = y3;
247 wx_stack_top->x4 = x4;
248 wx_stack_top->y4 = y4;
253 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
254 double *x3, double *y3, double *x4, double *y4)
256 if (wx_stack_count == 0)
260 *x1 = wx_stack_top->x1;
261 *y1 = wx_stack_top->y1;
262 *x2 = wx_stack_top->x2;
263 *y2 = wx_stack_top->y2;
264 *x3 = wx_stack_top->x3;
265 *y3 = wx_stack_top->y3;
266 *x4 = wx_stack_top->x4;
267 *y4 = wx_stack_top->y4;
271 static bool wx_spline_add_point(double x, double y)
273 wxPoint *point = new wxPoint ;
276 wx_spline_point_list.Append((wxObject*)point);
280 static void wx_spline_draw_point_array(wxDC *dc)
282 dc->DrawLines(&wx_spline_point_list, (double)0.0, (double)0.0);
283 wxNode *node = wx_spline_point_list.First();
286 wxPoint *point = (wxPoint *)node->Data();
289 node = wx_spline_point_list.First();
293 wxSpline::wxSpline(wxList *list)
298 wxSpline::~wxSpline(void)
302 void wxSpline::DeletePoints(void)
304 for(wxNode *node = points->First(); node; node = points->First())
306 wxPoint *point = (wxPoint *)node->Data();
315 // Make a 3-point spline
316 void wxPostScriptDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3)
318 wxList *point_list = new wxList;
320 wxPoint *point1 = new wxPoint;
321 point1->x = x1; point1->y = y1;
322 point_list->Append((wxObject*)point1);
324 wxPoint *point2 = new wxPoint;
325 point2->x = x2; point2->y = y2;
326 point_list->Append((wxObject*)point2);
328 wxPoint *point3 = new wxPoint;
329 point3->x = x3; point3->y = y3;
330 point_list->Append((wxObject*)point3);
332 wxSpline spline(point_list);
334 wx_draw_open_spline_ps(this, &spline);
335 spline.DeletePoints();
338 void wxPostScriptDC::DrawSpline(wxList *list)
340 wxSpline spline(list);
342 wx_draw_open_spline_ps(this, &spline);
345 void wxPostScriptDC::DrawSpline(int n, wxPoint points[])
349 for (i =0; i < n; i++)
350 list.Append((wxObject*)&points[i]);
351 DrawSpline((wxList *)&list);
355 #endif // USE_POSTSCRIPT
357 #endif // USE_SPLINES