2 Routine to convert cubic splines into quadratic ones.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This file is distributed under the GPL, see file COPYING for details */
10 /* At the moment, we convert non-recursively into at max. 6 quadratic splines,
11 trying to maintain the general structure of the curve, rather than it's
13 To accomplish this, we split each curve at it's X,Y extremas as well as
14 its deviation's X,Y extremas.
20 int solve(double a,double b,double c, double*dd)
24 if(det<0) return 0; // we don't do imaginary. not today.
25 if(det==0) { // unlikely, but we have to deal with it.
27 return (dd[0]>0 && dd[0]<1);
30 dd[pos]=(-b+sqrt(det))/(2*a);
31 if(dd[pos]>0 && dd[pos]<1)
33 dd[pos]=(-b-sqrt(det))/(2*a);
34 if(dd[pos]>0 && dd[pos]<1)
39 struct plotxy splinepos(struct plotxy p0, struct plotxy p1, struct plotxy p2, struct plotxy p3, double d) {
41 p.x = (p0.x * d*d*d + p1.x * 3*(1-d)*d*d + p2.x * 3*(1-d)*(1-d)*d + p3.x * (1-d)*(1-d)*(1-d));
42 p.y = (p0.y * d*d*d + p1.y * 3*(1-d)*d*d + p2.y * 3*(1-d)*(1-d)*d + p3.y * (1-d)*(1-d)*(1-d));
46 double distance(struct plotxy p0, struct plotxy p1)
50 return sqrt(xd*xd+yd*yd);
53 int wp(double p0,double p1,double p2,double p3,double*dd)
55 double div= (6*p0-18*p1+18*p2-6*p3);
57 dd[0] = -(6*p1-12*p2+6*p3)/div;
58 return (dd[0]>0 && dd[0]<1);
61 int approximate(struct plotxy p0, struct plotxy p1,
62 struct plotxy p2, struct plotxy p3, struct qspline*q)
67 struct plotxy myxy[12];
69 // the parameters for the solve function are the 1st deviation of a cubic spline
71 pos += solve(3*p0.x-9*p1.x+9*p2.x-3*p3.x, 6*p1.x-12*p2.x+6*p3.x,3*p2.x-3*p3.x, &roots[pos]);
72 pos += solve(3*p0.y-9*p1.y+9*p2.y-3*p3.y, 6*p1.y-12*p2.y+6*p3.y,3*p2.y-3*p3.y, &roots[pos]);
73 pos += wp(p0.x,p1.x,p2.x,p3.x,&roots[pos]);
74 pos += wp(p0.x,p1.x,p2.x,p3.x,&roots[pos]);
77 // bubblesort - fast enough for 4-6 parameters
87 myxy[t] = splinepos(p0,p1,p2,p3,roots[t]);
93 double dist=distance(myxy[t],last);
96 if(dist>0.01 || t==pos-1)
104 // try 1:curve through 3 points, using the middle of the cubic spline.
105 for(t=0;t<pos-1;t++) {
106 // circle(myxy[t].x,myxy[t].y,5);
107 struct plotxy control;
108 struct plotxy midpoint = splinepos(p0,p1,p2,p3,(roots[t]+roots[t+1])/2);
109 control.x = midpoint.x + (midpoint.x-(myxy[t].x+myxy[t+1].x)/2);
110 control.y = midpoint.y + (midpoint.y-(myxy[t].y+myxy[t+1].y)/2);
111 //qspline(myxy[t],control,myxy[t+1]);
113 q[t].control=control;
118 for(t=0;t<pos-1;t++) {
120 vga.setcolor(0xffffff);
121 circle(myxy[t].x,myxy[t].y,5);
123 //double lenmain = distance(p3,p0);
124 //double lenq = distance(myxy[0],myxy[1]);
125 //control.x = myxy[0].x + (p2.x-p3.x);// /lenmain*lenq;
126 //control.y = myxy[0].y + (p2.y-p3.y);// /lenmain*lenq;
127 plotxy midpoint = splinepos(p0,p1,p2,p3,(roots[t]+roots[t+1])/2);
128 control.x = midpoint.x + (midpoint.x-(myxy[t].x+myxy[t+1].x)/2);
129 control.y = midpoint.y + (midpoint.y-(myxy[t].y+myxy[t+1].y)/2);
130 qspline(myxy[0], control, myxy[1]);
132 control.x = 2*myxy[t].x - last.x;
133 control.y = 2*myxy[t].y - last.y;
134 qspline(myxy[t], control, myxy[t+1]);