31 #include <config-kig.h>
43 double p = polardata.
pdimen;
54 f += a*fx*fx + b*fy*fy + c*fx*fy - d*fx - e*fy;
68 double a = cartdata.
coeffs[0];
69 double b = cartdata.
coeffs[1];
70 double c = cartdata.
coeffs[2];
71 double d = cartdata.
coeffs[3];
72 double e = cartdata.
coeffs[4];
73 double f = cartdata.
coeffs[5];
76 double theta = std::atan2(c, b - a)/2;
79 double costheta = std::cos(theta);
80 double sintheta = std::sin(theta);
82 double aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
83 double bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
86 double dd = d*costheta - e*sintheta;
87 double ee = d*sintheta + e*costheta;
88 double xc = - dd / ( 2*aa );
89 double yc = - ee / ( 2*bb );
90 double ff = f + aa*xc*xc + bb*yc*yc + dd*xc + ee*yc;
93 if (theta > 0) theta -= M_PI/2;
95 costheta = cos(theta);
96 sintheta = sin(theta);
97 aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
98 bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
103 if ( std::fabs (bb) < std::fabs (aa) )
105 if (theta > 0) theta -= M_PI/2;
106 else theta += M_PI/2;
107 costheta = cos(theta);
108 sintheta = sin(theta);
109 aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
110 bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
114 double cc = 2*(a - b)*sintheta*costheta +
115 c*(costheta*costheta - sintheta*sintheta);
117 double dd = d*costheta - e*sintheta;
118 double ee = d*sintheta + e*costheta;
146 double eccentricity = sqrt(1.0 - a);
148 double sqrtdiscrim = sqrt(d*d - 4*a*f);
149 if (d < 0.0) sqrtdiscrim = -sqrtdiscrim;
150 double xf = (4*a*f - 4*f - d*d)/(d + eccentricity*sqrtdiscrim) / 2;
153 focus1.
x = xf*costheta + yf*sintheta;
154 focus1.
y = -xf*sintheta + yf*costheta;
170 const std::vector<Coordinate>& points,
177 assert( 0 < points.size() && points.size() <= 5 );
196 double *matrix[5] = {row0, row1, row2, row3, row4};
201 int numpoints = points.size();
202 int numconstraints = 5;
205 for (
int i = 0; i < numpoints; ++i )
207 double xi = points[i].x;
208 double yi = points[i].y;
209 matrix[i][0] = xi*xi;
210 matrix[i][1] = yi*yi;
211 matrix[i][2] = xi*yi;
217 for (
int i = 0; i < numconstraints; i++ )
219 if (numpoints >= 5)
break;
220 for (
int j = 0; j < 6; ++j) matrix[numpoints][j] = 0.0;
223 if (constraints[i] ==
zerotilt) matrix[numpoints][2] = 1.0;
225 if (constraints[i] ==
parabolaifzt) matrix[numpoints][1] = 1.0;
228 matrix[numpoints][0] = 1.0;
229 matrix[numpoints][1] = -1.0; }
232 matrix[numpoints][0] = 1.0;
233 matrix[numpoints][1] = 1.0; }
235 if (constraints[i] ==
ysymmetry) matrix[numpoints][3] = 1.0;
237 if (constraints[i] ==
xsymmetry) matrix[numpoints][4] = 1.0;
252 const std::vector<Coordinate>& args,
255 assert( args.size() >= 2 && args.size() <= 3 );
256 assert( type == 1 || type == -1 );
263 double eccentricity, d1, d2, dl;
266 double f2f1l = f2f1.
length();
270 if ( args.size() == 3 )
273 d1 = ( d - f1 ).length();
274 d2 = ( d - f2 ).length();
275 dl = fabs( d1 + type * d2 );
276 eccentricity = f2f1l/dl;
280 if ( type > 0 ) eccentricity = 0.7;
else eccentricity = 2.0;
281 dl = f2f1l/eccentricity;
284 double rhomax = (dl + f2f1l) /2.0;
288 ret.
pdimen = type*(1 - eccentricity)*rhomax;
289 ret.
focus1 = type == 1 ? f1 : f2;
300 double a = data.
coeffs[0];
301 double b = data.
coeffs[1];
302 double c = data.
coeffs[2];
303 double d = data.
coeffs[3];
304 double e = data.
coeffs[4];
305 double f = data.
coeffs[5];
307 double alpha = 2*a*x + c*y + d;
308 double beta = c*x + 2*b*y + e;
309 double gamma = d*x + e*y + 2*f;
311 double normsq = alpha*alpha + beta*beta;
321 Coordinate retb = reta + Coordinate (-beta, alpha);
332 double alpha = p2.
y - p1.
y;
333 double beta = p1.
x - p2.
x;
334 double gamma = p1.
y*p2.
x - p1.
x*p2.
y;
336 double a11 = data.
coeffs[0];
337 double a22 = data.
coeffs[1];
338 double a12 = data.
coeffs[2]/2.0;
339 double a13 = data.
coeffs[3]/2.0;
340 double a23 = data.
coeffs[4]/2.0;
341 double a33 = data.
coeffs[5];
346 double a11inv = a22*a33 - a23*a23;
347 double a22inv = a11*a33 - a13*a13;
348 double a33inv = a11*a22 - a12*a12;
349 double a12inv = a23*a13 - a12*a33;
350 double a23inv = a12*a13 - a23*a11;
351 double a13inv = a12*a23 - a13*a22;
353 double x = a11inv*alpha + a12inv*beta + a13inv*gamma;
354 double y = a12inv*alpha + a22inv*beta + a23inv*gamma;
355 double z = a13inv*alpha + a23inv*beta + a33inv*gamma;
372 assert( which == 1 || which == -1 || which == 0 );
383 double dx = l.
b.
x - l.
a.
x;
384 double dy = l.
b.
y - l.
a.
y;
386 double aaa = aa*dx*dx + bb*dy*dy + cc*dx*dy;
387 double bbb = 2*aa*x*dx + 2*bb*y*dy + cc*x*dy + cc*y*dx + dd*dx + ee*dy;
388 double ccc = aa*x*x + bb*y*y + cc*x*y + dd*x + ee*y + ff;
393 t = - bbb/aaa - knownparam;
394 return l.
a + t*(l.
b - l.
a);
397 double discrim = bbb*bbb - 4*aaa*ccc;
406 t = bbb + which*sqrt(discrim);
409 t = -bbb + which*sqrt(discrim);
417 return l.
a + t*(l.
b - l.
a);
423 double ec,
double es )
424 : focus1( f ), pdimen( d ), ecostheta0( ec ), esintheta0( es )
429 : focus1(), pdimen( 0 ), ecostheta0( 0 ), esintheta0( 0 )
447 double distpf = (cpoint - cfocus).length();
448 double distpd = ( pa.
y*ba.
x - pa.
x*ba.
y)/bal;
450 double eccentricity = distpf/distpd;
456 ret.
pdimen *= eccentricity;
464 std::copy( incoeffs, incoeffs + 6,
coeffs );
469 int which,
bool &valid )
471 assert( which == -1 || which == 1 );
480 double normabc = a*a + b*b + c*c;
481 double delta = c*c - 4*a*b;
482 if (fabs(delta) < 1e-6*normabc) { valid =
false;
return ret; }
484 double yc = (2*a*e - c*d)/delta;
485 double xc = (2*b*d - c*e)/delta;
500 double sqrtdelta = sqrt(delta);
503 displacement =
Coordinate(-2*b, c + sqrtdelta);
505 displacement =
Coordinate(c + sqrtdelta, -2*a);
507 ret.
b = ret.
a + displacement;
521 double c1 = p1.
x*p2.
y - p2.
x*p1.
y;
522 double b1 = p2.
x - p1.
x;
523 double a1 = p1.
y - p2.
y;
528 double c2 = p1.
x*p2.
y - p2.
x*p1.
y;
529 double b2 = p2.
x - p1.
x;
530 double a2 = p1.
y - p2.
y;
534 double c = a1*b2 + a2*b1;
535 double d = a1*c2 + a2*c1;
536 double e = b1*c2 + c1*b2;
538 double f = a*x*x + b*y*y + c*x*y + d*x + e*y;
546 int which,
int zeroindex,
bool& valid )
548 assert( which == 1 || which == -1 );
549 assert( 0 < zeroindex && zeroindex < 4 );
553 double a = cequation1.
coeffs[0];
554 double b = cequation1.
coeffs[1];
555 double c = cequation1.
coeffs[2];
556 double d = cequation1.
coeffs[3];
557 double e = cequation1.
coeffs[4];
558 double f = cequation1.
coeffs[5];
560 double a2 = cequation2.
coeffs[0];
561 double b2 = cequation2.
coeffs[1];
562 double c2 = cequation2.
coeffs[2];
563 double d2 = cequation2.
coeffs[3];
564 double e2 = cequation2.
coeffs[4];
565 double f2 = cequation2.
coeffs[5];
574 double df = 4*a*b*f - a*e*e - b*d*d - c*c*f + c*d*e;
575 double cf = 4*a2*b*f + 4*a*b2*f + 4*a*b*f2
576 - 2*a*e*e2 - 2*b*d*d2 - 2*f*c*c2
577 - a2*e*e - b2*d*d - f2*c*c
578 + c2*d*e + c*d2*e + c*d*e2;
579 double bf = 4*a*b2*f2 + 4*a2*b*f2 + 4*a2*b2*f
580 - 2*a2*e2*e - 2*b2*d2*d - 2*f2*c2*c
581 - a*e2*e2 - b*d2*d2 - f*c2*c2
582 + c*d2*e2 + c2*d*e2 + c2*d2*e;
583 double af = 4*a2*b2*f2 - a2*e2*e2 - b2*d2*d2 - c2*c2*f2 + c2*d2*e2;
594 double p1a = 2*bf*bf - 6*cf;
595 double p1b = bf*cf - 9*df;
596 double p0a = cf*p1a*p1a + p1b*(3*p1b - 2*bf*p1a);
597 double fval, fpval, lambda;
599 if (p0a < 0 && p1a < 0)
607 double displace = 1.0;
610 displace += sqrt(p1a);
616 fval = cf + lambda*fval;
617 fval = df + lambda*fval;
619 if (fabs(p0a) < 1e-7)
627 lambda += ( 2 - zeroindex )* displace;
656 const int maxiterations = 30;
657 while (iterations++ < maxiterations)
661 fval = bf + lambda*fval;
662 fpval = fval + lambda*fpval;
663 fval = cf + lambda*fval;
664 fpval = fval + lambda*fpval;
665 fval = df + lambda*fval;
669 if (fabs(delta) < 1e-6)
break;
671 if (iterations >= maxiterations) { valid =
false;
return ret; }
685 df = 4*a*b*f - a*e*e - b*d*d - c*c*f + c*d*e;
689 double dis1 = e*e - 4*b*f;
690 double maxval = fabs(dis1);
692 double dis2 = d*d - 4*a*f;
693 if (fabs(dis2) > maxval)
698 double dis3 = c*c - 4*a*b;
699 if (fabs(dis3) > maxval)
711 temp = a; a = f; f = temp;
712 temp = c; c = e; e = temp;
713 temp = dis1; dis1 = dis3; dis3 = temp;
717 temp = b; b = f; f = temp;
718 temp = c; c = d; d = temp;
719 temp = dis2; dis2 = dis3; dis3 = temp;
752 temp = a; a = f; f = temp;
753 temp = c; c = e; e = temp;
754 temp = dis1; dis1 = dis3; dis3 = temp;
755 temp = r[0]; r[0] = r[2]; r[2] = temp;
759 temp = b; b = f; f = temp;
760 temp = c; c = d; d = temp;
761 temp = dis2; dis2 = dis3; dis3 = temp;
762 temp = r[1]; r[1] = r[2]; r[2] = temp;
770 double rnormsq = r[0]*r[0] + r[1]*r[1] + r[2]*r[2];
771 double k = sqrt( rnormsq );
772 if ( k*r[2] < 0) k = -k;
773 double wnorm = sqrt( 2*rnormsq + 2*k*r[2] );
776 w[2] = (r[2] + k)/wnorm;
782 double q0 = a*w[0] + c*w[1]/2 + d*w[2]/2;
783 double q1 = b*w[1] + c*w[0]/2 + e*w[2]/2;
784 double alpha = a*w[0]*w[0] + b*w[1]*w[1] + c*w[0]*w[1] +
785 d*w[0]*w[2] + e*w[1]*w[2] + f*w[2]*w[2];
786 double a00 = a - 4*w[0]*q0 + 4*w[0]*w[0]*alpha;
787 double a11 = b - 4*w[1]*q1 + 4*w[1]*w[1]*alpha;
788 double a01 = c/2 - 2*w[1]*q0 - 2*w[0]*q1 + 4*w[0]*w[1]*alpha;
790 double dis = a01*a01 - a00*a11;
792 double sqrtdis = sqrt( dis );
796 px = a01 + which*sqrtdis;
800 py = a01 - which*sqrtdis;
803 double pscalw = w[0]*px + w[1]*py;
804 p[0] = px - 2*pscalw*w[0];
805 p[1] = py - 2*pscalw*w[1];
806 p[2] = - 2*pscalw*w[2];
819 ret.
a = -p[2]/(p[0]*p[0] + p[1]*p[1]) *
Coordinate (p[0],p[1]);
834 a[1][2] = a[2][1] = data.
coeffs[2]/2;
835 a[0][1] = a[1][0] = data.
coeffs[3]/2;
836 a[0][2] = a[2][0] = data.
coeffs[4]/2;
842 double supnorm = 0.0;
843 for (
int i = 0; i < 3; i++)
845 for (
int j = 0; j < 3; j++)
848 for (
int ii = 0; ii < 3; ii++)
850 for (
int jj = 0; jj < 3; jj++)
852 b[i][j] += a[ii][jj]*ti.
data( ii, i )*ti.
data( jj, j );
855 if ( std::fabs( b[i][j] ) > supnorm ) supnorm = std::fabs( b[i][j] );
859 for (
int i = 0; i < 3; i++)
861 for (
int j = 0; j < 3; j++)
868 b[0][1] + b[1][0], b[0][2] + b[2][0], b[0][0] );
892 return finite(
coeffs[0] );
const LineData calcConicPolarLine(const ConicCartesianData &data, const Coordinate &cpole, bool &valid)
This function calculates the polar line of the point cpole with respect to the given conic data...
LinearConstraints
These are the constraint values that can be passed to the calcConicThroughPoints function.
double esintheta0
The esintheta0 value from the polar equation.
Simple class representing a line.
const Coordinate dir() const
The direction of the line.
Coordinate b
Another point on the line.
const LineData calcConicAsymptote(const ConicCartesianData data, int which, bool &valid)
This function calculates the asymptote of the given conic ( data ).
const ConicCartesianData calcConicThroughPoints(const std::vector< Coordinate > &points, const LinearConstraints c1, const LinearConstraints c2, const LinearConstraints c3, const LinearConstraints c4, const LinearConstraints c5)
Calculate a conic through a given set of points.
const Coordinate calcConicPolarPoint(const ConicCartesianData &data, const LineData &polar)
This function calculates the polar point of the line polar with respect to the given conic data...
static ConicCartesianData invalidData()
Invalid conic.
The Coordinate class is the basic class representing a 2D location by its x and y components...
double length() const
Length.
bool GaussianElimination(double *matrix[], int numrows, int numcols, int exchange[])
Gaussian Elimination.
const ConicPolarData calcConicBDFP(const LineData &directrix, const Coordinate &cfocus, const Coordinate &cpoint)
function used by ConicBDFP.
const Coordinate calcConicLineIntersect(const ConicCartesianData &c, const LineData &l, double knownparam, int which)
This function calculates the intersection of a given line ( l ) and a given conic ( c )...
Coordinate focus1
The first focus of this conic.
const LineData calcConicRadical(const ConicCartesianData &cequation1, const ConicCartesianData &cequation2, int which, int zeroindex, bool &valid)
This function calculates the radical line of two conics.
Coordinate a
One point on the line.
double pdimen
The pdimen value from the polar equation.
double ecostheta0
The ecostheta0 value from the polar equation.
static Coordinate invalidCoord()
Create an invalid Coordinate.
const ConicPolarData calcConicBFFP(const std::vector< Coordinate > &args, int type)
This function is used by ConicBFFP.
bool operator==(const ConicPolarData &lhs, const ConicPolarData &rhs)
const ConicCartesianData calcConicByAsymptotes(const LineData &line1, const LineData &line2, const Coordinate &p)
This calcs the hyperbola defined by its two asymptotes line1 and line2, and a point p on the edge...
bool valid() const
Test validity.
void BackwardSubstitution(double *matrix[], int numrows, int numcols, int exchange[], double solution[])
const ConicCartesianData calcConicTransformation(const ConicCartesianData &data, const Transformation &t, bool &valid)
This calculates the image of the given conic ( data ) through the given transformation ( t )...
This class represents an equation of a conic in the form .