00001
00021 #include "conic-common.h"
00022
00023 #include <math.h>
00024
00025 #include "common.h"
00026 #include "kigtransform.h"
00027
00028 #include <cmath>
00029 #include <algorithm>
00030
00031 #include <config-kig.h>
00032
00033 #ifdef HAVE_IEEEFP_H
00034 #include <ieeefp.h>
00035 #endif
00036
00037 ConicCartesianData::ConicCartesianData(
00038 const ConicPolarData& polardata
00039 )
00040 {
00041 double ec = polardata.ecostheta0;
00042 double es = polardata.esintheta0;
00043 double p = polardata.pdimen;
00044 double fx = polardata.focus1.x;
00045 double fy = polardata.focus1.y;
00046
00047 double a = 1 - ec*ec;
00048 double b = 1 - es*es;
00049 double c = - 2*ec*es;
00050 double d = - 2*p*ec;
00051 double e = - 2*p*es;
00052 double f = - p*p;
00053
00054 f += a*fx*fx + b*fy*fy + c*fx*fy - d*fx - e*fy;
00055 d -= 2*a*fx + c*fy;
00056 e -= 2*b*fy + c*fx;
00057
00058 coeffs[0] = a;
00059 coeffs[1] = b;
00060 coeffs[2] = c;
00061 coeffs[3] = d;
00062 coeffs[4] = e;
00063 coeffs[5] = f;
00064 }
00065
00066 ConicPolarData::ConicPolarData( const ConicCartesianData& cartdata )
00067 {
00068 double a = cartdata.coeffs[0];
00069 double b = cartdata.coeffs[1];
00070 double c = cartdata.coeffs[2];
00071 double d = cartdata.coeffs[3];
00072 double e = cartdata.coeffs[4];
00073 double f = cartdata.coeffs[5];
00074
00075
00076 double theta = std::atan2(c, b - a)/2;
00077
00078
00079 double costheta = std::cos(theta);
00080 double sintheta = std::sin(theta);
00081
00082 double aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
00083 double bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
00084 if (aa*bb < 0)
00085 {
00086 double dd = d*costheta - e*sintheta;
00087 double ee = d*sintheta + e*costheta;
00088 double xc = - dd / ( 2*aa );
00089 double yc = - ee / ( 2*bb );
00090 double ff = f + aa*xc*xc + bb*yc*yc + dd*xc + ee*yc;
00091 if (ff*aa > 0)
00092 {
00093 if (theta > 0) theta -= M_PI/2;
00094 else theta += M_PI/2;
00095 costheta = cos(theta);
00096 sintheta = sin(theta);
00097 aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
00098 bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
00099 }
00100 }
00101 else
00102 {
00103 if ( std::fabs (bb) < std::fabs (aa) )
00104 {
00105 if (theta > 0) theta -= M_PI/2;
00106 else theta += M_PI/2;
00107 costheta = cos(theta);
00108 sintheta = sin(theta);
00109 aa = a*costheta*costheta + b*sintheta*sintheta - c*sintheta*costheta;
00110 bb = a*sintheta*sintheta + b*costheta*costheta + c*sintheta*costheta;
00111 }
00112 }
00113
00114 double cc = 2*(a - b)*sintheta*costheta +
00115 c*(costheta*costheta - sintheta*sintheta);
00116
00117 double dd = d*costheta - e*sintheta;
00118 double ee = d*sintheta + e*costheta;
00119
00120 a = aa;
00121 b = bb;
00122 c = cc;
00123 d = dd;
00124 e = ee;
00125
00126
00127 a /= b;
00128 c /= b;
00129 d /= b;
00130 e /= b;
00131 f /= b;
00132 b = 1.0;
00133
00134
00135
00136 double yf = - e/2;
00137
00138
00139 f += yf*yf + e*yf;
00140 e += 2*yf;
00141
00142
00143
00144
00145
00146 double eccentricity = sqrt(1.0 - a);
00147
00148 double sqrtdiscrim = sqrt(d*d - 4*a*f);
00149 if (d < 0.0) sqrtdiscrim = -sqrtdiscrim;
00150 double xf = (4*a*f - 4*f - d*d)/(d + eccentricity*sqrtdiscrim) / 2;
00151
00152
00153 focus1.x = xf*costheta + yf*sintheta;
00154 focus1.y = -xf*sintheta + yf*costheta;
00155
00156
00157 pdimen = -sqrtdiscrim/2;
00158
00159 ecostheta0 = eccentricity*costheta;
00160 esintheta0 = -eccentricity*sintheta;
00161 if ( pdimen < 0)
00162 {
00163 pdimen = -pdimen;
00164 ecostheta0 = -ecostheta0;
00165 esintheta0 = -esintheta0;
00166 }
00167 }
00168
00169 const ConicCartesianData calcConicThroughPoints (
00170 const std::vector<Coordinate>& points,
00171 const LinearConstraints c1,
00172 const LinearConstraints c2,
00173 const LinearConstraints c3,
00174 const LinearConstraints c4,
00175 const LinearConstraints c5 )
00176 {
00177 assert( 0 < points.size() && points.size() <= 5 );
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 double row0[6];
00192 double row1[6];
00193 double row2[6];
00194 double row3[6];
00195 double row4[6];
00196 double *matrix[5] = {row0, row1, row2, row3, row4};
00197 double solution[6];
00198 int scambio[6];
00199 LinearConstraints constraints[] = {c1, c2, c3, c4, c5};
00200
00201 int numpoints = points.size();
00202 int numconstraints = 5;
00203
00204
00205 for ( int i = 0; i < numpoints; ++i )
00206 {
00207 double xi = points[i].x;
00208 double yi = points[i].y;
00209 matrix[i][0] = xi*xi;
00210 matrix[i][1] = yi*yi;
00211 matrix[i][2] = xi*yi;
00212 matrix[i][3] = xi;
00213 matrix[i][4] = yi;
00214 matrix[i][5] = 1.0;
00215 }
00216
00217 for ( int i = 0; i < numconstraints; i++ )
00218 {
00219 if (numpoints >= 5) break;
00220 for (int j = 0; j < 6; ++j) matrix[numpoints][j] = 0.0;
00221
00222
00223 if (constraints[i] == zerotilt) matrix[numpoints][2] = 1.0;
00224
00225 if (constraints[i] == parabolaifzt) matrix[numpoints][1] = 1.0;
00226
00227 if (constraints[i] == circleifzt) {
00228 matrix[numpoints][0] = 1.0;
00229 matrix[numpoints][1] = -1.0; }
00230
00231 if (constraints[i] == equilateral) {
00232 matrix[numpoints][0] = 1.0;
00233 matrix[numpoints][1] = 1.0; }
00234
00235 if (constraints[i] == ysymmetry) matrix[numpoints][3] = 1.0;
00236
00237 if (constraints[i] == xsymmetry) matrix[numpoints][4] = 1.0;
00238
00239 if (constraints[i] != noconstraint) ++numpoints;
00240 }
00241
00242 if ( ! GaussianElimination( matrix, numpoints, 6, scambio ) )
00243 return ConicCartesianData::invalidData();
00244
00245 BackwardSubstitution( matrix, numpoints, 6, scambio, solution );
00246
00247
00248 return ConicCartesianData( solution );
00249 }
00250
00251 const ConicPolarData calcConicBFFP(
00252 const std::vector<Coordinate>& args,
00253 int type )
00254 {
00255 assert( args.size() >= 2 && args.size() <= 3 );
00256 assert( type == 1 || type == -1 );
00257
00258 ConicPolarData ret;
00259
00260 Coordinate f1 = args[0];
00261 Coordinate f2 = args[1];
00262 Coordinate d;
00263 double eccentricity, d1, d2, dl;
00264
00265 Coordinate f2f1 = f2 - f1;
00266 double f2f1l = f2f1.length();
00267 ret.ecostheta0 = f2f1.x / f2f1l;
00268 ret.esintheta0 = f2f1.y / f2f1l;
00269
00270 if ( args.size() == 3 )
00271 {
00272 d = args[2];
00273 d1 = ( d - f1 ).length();
00274 d2 = ( d - f2 ).length();
00275 dl = fabs( d1 + type * d2 );
00276 eccentricity = f2f1l/dl;
00277 }
00278 else
00279 {
00280 if ( type > 0 ) eccentricity = 0.7; else eccentricity = 2.0;
00281 dl = f2f1l/eccentricity;
00282 }
00283
00284 double rhomax = (dl + f2f1l) /2.0;
00285
00286 ret.ecostheta0 *= eccentricity;
00287 ret.esintheta0 *= eccentricity;
00288 ret.pdimen = type*(1 - eccentricity)*rhomax;
00289 ret.focus1 = type == 1 ? f1 : f2;
00290 return ret;
00291 }
00292
00293 const LineData calcConicPolarLine (
00294 const ConicCartesianData& data,
00295 const Coordinate& cpole,
00296 bool& valid )
00297 {
00298 double x = cpole.x;
00299 double y = cpole.y;
00300 double a = data.coeffs[0];
00301 double b = data.coeffs[1];
00302 double c = data.coeffs[2];
00303 double d = data.coeffs[3];
00304 double e = data.coeffs[4];
00305 double f = data.coeffs[5];
00306
00307 double alpha = 2*a*x + c*y + d;
00308 double beta = c*x + 2*b*y + e;
00309 double gamma = d*x + e*y + 2*f;
00310
00311 double normsq = alpha*alpha + beta*beta;
00312
00313 if (normsq < 1e-10)
00314 {
00315 valid = false;
00316 return LineData();
00317 }
00318 valid = true;
00319
00320 Coordinate reta = -gamma/normsq * Coordinate (alpha, beta);
00321 Coordinate retb = reta + Coordinate (-beta, alpha);
00322 return LineData( reta, retb );
00323 }
00324
00325 const Coordinate calcConicPolarPoint (
00326 const ConicCartesianData& data,
00327 const LineData& polar )
00328 {
00329 Coordinate p1 = polar.a;
00330 Coordinate p2 = polar.b;
00331
00332 double alpha = p2.y - p1.y;
00333 double beta = p1.x - p2.x;
00334 double gamma = p1.y*p2.x - p1.x*p2.y;
00335
00336 double a11 = data.coeffs[0];
00337 double a22 = data.coeffs[1];
00338 double a12 = data.coeffs[2]/2.0;
00339 double a13 = data.coeffs[3]/2.0;
00340 double a23 = data.coeffs[4]/2.0;
00341 double a33 = data.coeffs[5];
00342
00343
00344
00345
00346 double a11inv = a22*a33 - a23*a23;
00347 double a22inv = a11*a33 - a13*a13;
00348 double a33inv = a11*a22 - a12*a12;
00349 double a12inv = a23*a13 - a12*a33;
00350 double a23inv = a12*a13 - a23*a11;
00351 double a13inv = a12*a23 - a13*a22;
00352
00353 double x = a11inv*alpha + a12inv*beta + a13inv*gamma;
00354 double y = a12inv*alpha + a22inv*beta + a23inv*gamma;
00355 double z = a13inv*alpha + a23inv*beta + a33inv*gamma;
00356
00357 if (fabs(z) < 1e-10)
00358 {
00359 return Coordinate::invalidCoord();
00360 }
00361
00362 x /= z;
00363 y /= z;
00364 return Coordinate (x, y);
00365 }
00366
00367 const Coordinate calcConicLineIntersect( const ConicCartesianData& c,
00368 const LineData& l,
00369 double knownparam,
00370 int which )
00371 {
00372 assert( which == 1 || which == -1 || which == 0 );
00373
00374 double aa = c.coeffs[0];
00375 double bb = c.coeffs[1];
00376 double cc = c.coeffs[2];
00377 double dd = c.coeffs[3];
00378 double ee = c.coeffs[4];
00379 double ff = c.coeffs[5];
00380
00381 double x = l.a.x;
00382 double y = l.a.y;
00383 double dx = l.b.x - l.a.x;
00384 double dy = l.b.y - l.a.y;
00385
00386 double aaa = aa*dx*dx + bb*dy*dy + cc*dx*dy;
00387 double bbb = 2*aa*x*dx + 2*bb*y*dy + cc*x*dy + cc*y*dx + dd*dx + ee*dy;
00388 double ccc = aa*x*x + bb*y*y + cc*x*y + dd*x + ee*y + ff;
00389
00390 double t;
00391 if ( which == 0 )
00392 {
00393 t = - bbb/aaa - knownparam;
00394 return l.a + t*(l.b - l.a);
00395 }
00396
00397 double discrim = bbb*bbb - 4*aaa*ccc;
00398 if (discrim < 0.0)
00399 {
00400 return Coordinate::invalidCoord();
00401 }
00402 else
00403 {
00404 if ( which*bbb > 0 )
00405 {
00406 t = bbb + which*sqrt(discrim);
00407 t = - 2*ccc/t;
00408 } else {
00409 t = -bbb + which*sqrt(discrim);
00410 t /= 2*aaa;
00411 }
00412
00413 return l.a + t*(l.b - l.a);
00414 }
00415 }
00416
00417 ConicPolarData::ConicPolarData(
00418 const Coordinate& f, double d,
00419 double ec, double es )
00420 : focus1( f ), pdimen( d ), ecostheta0( ec ), esintheta0( es )
00421 {
00422 }
00423
00424 ConicPolarData::ConicPolarData()
00425 : focus1(), pdimen( 0 ), ecostheta0( 0 ), esintheta0( 0 )
00426 {
00427 }
00428
00429 const ConicPolarData calcConicBDFP(
00430 const LineData& directrix,
00431 const Coordinate& cfocus,
00432 const Coordinate& cpoint )
00433 {
00434 ConicPolarData ret;
00435
00436 Coordinate ba = directrix.dir();
00437 double bal = ba.length();
00438 ret.ecostheta0 = -ba.y / bal;
00439 ret.esintheta0 = ba.x / bal;
00440
00441 Coordinate pa = cpoint - directrix.a;
00442
00443 double distpf = (cpoint - cfocus).length();
00444 double distpd = ( pa.y*ba.x - pa.x*ba.y)/bal;
00445
00446 double eccentricity = distpf/distpd;
00447 ret.ecostheta0 *= eccentricity;
00448 ret.esintheta0 *= eccentricity;
00449
00450 Coordinate fa = cfocus - directrix.a;
00451 ret.pdimen = ( fa.y*ba.x - fa.x*ba.y )/bal;
00452 ret.pdimen *= eccentricity;
00453 ret.focus1 = cfocus;
00454
00455 return ret;
00456 }
00457
00458 ConicCartesianData::ConicCartesianData( const double incoeffs[6] )
00459 {
00460 std::copy( incoeffs, incoeffs + 6, coeffs );
00461 }
00462
00463 const LineData calcConicAsymptote(
00464 const ConicCartesianData data,
00465 int which, bool &valid )
00466 {
00467 assert( which == -1 || which == 1 );
00468
00469 LineData ret;
00470 double a=data.coeffs[0];
00471 double b=data.coeffs[1];
00472 double c=data.coeffs[2];
00473 double d=data.coeffs[3];
00474 double e=data.coeffs[4];
00475
00476 double normabc = a*a + b*b + c*c;
00477 double delta = c*c - 4*a*b;
00478 if (fabs(delta) < 1e-6*normabc) { valid = false; return ret; }
00479
00480 double yc = (2*a*e - c*d)/delta;
00481 double xc = (2*b*d - c*e)/delta;
00482
00483 if (c < 0)
00484 {
00485 c *= -1;
00486 a *= -1;
00487 b *= -1;
00488 }
00489
00490 if ( delta < 0 )
00491 {
00492 valid = false;
00493 return ret;
00494 }
00495
00496 double sqrtdelta = sqrt(delta);
00497 Coordinate displacement;
00498 if (which > 0)
00499 displacement = Coordinate(-2*b, c + sqrtdelta);
00500 else
00501 displacement = Coordinate(c + sqrtdelta, -2*a);
00502 ret.a = Coordinate(xc, yc);
00503 ret.b = ret.a + displacement;
00504 return ret;
00505 }
00506
00507 const ConicCartesianData calcConicByAsymptotes(
00508 const LineData& line1,
00509 const LineData& line2,
00510 const Coordinate& p )
00511 {
00512 Coordinate p1 = line1.a;
00513 Coordinate p2 = line1.b;
00514 double x = p.x;
00515 double y = p.y;
00516
00517 double c1 = p1.x*p2.y - p2.x*p1.y;
00518 double b1 = p2.x - p1.x;
00519 double a1 = p1.y - p2.y;
00520
00521 p1 = line2.a;
00522 p2 = line2.b;
00523
00524 double c2 = p1.x*p2.y - p2.x*p1.y;
00525 double b2 = p2.x - p1.x;
00526 double a2 = p1.y - p2.y;
00527
00528 double a = a1*a2;
00529 double b = b1*b2;
00530 double c = a1*b2 + a2*b1;
00531 double d = a1*c2 + a2*c1;
00532 double e = b1*c2 + c1*b2;
00533
00534 double f = a*x*x + b*y*y + c*x*y + d*x + e*y;
00535 f = -f;
00536
00537 return ConicCartesianData( a, b, c, d, e, f );
00538 }
00539
00540 const LineData calcConicRadical( const ConicCartesianData& cequation1,
00541 const ConicCartesianData& cequation2,
00542 int which, int zeroindex, bool& valid )
00543 {
00544 assert( which == 1 || which == -1 );
00545 assert( 0 < zeroindex && zeroindex < 4 );
00546 LineData ret;
00547 valid = true;
00548
00549 double a = cequation1.coeffs[0];
00550 double b = cequation1.coeffs[1];
00551 double c = cequation1.coeffs[2];
00552 double d = cequation1.coeffs[3];
00553 double e = cequation1.coeffs[4];
00554 double f = cequation1.coeffs[5];
00555
00556 double a2 = cequation2.coeffs[0];
00557 double b2 = cequation2.coeffs[1];
00558 double c2 = cequation2.coeffs[2];
00559 double d2 = cequation2.coeffs[3];
00560 double e2 = cequation2.coeffs[4];
00561 double f2 = cequation2.coeffs[5];
00562
00563
00564
00565
00566
00567
00568
00569
00570 double df = 4*a*b*f - a*e*e - b*d*d - c*c*f + c*d*e;
00571 double cf = 4*a2*b*f + 4*a*b2*f + 4*a*b*f2
00572 - 2*a*e*e2 - 2*b*d*d2 - 2*f*c*c2
00573 - a2*e*e - b2*d*d - f2*c*c
00574 + c2*d*e + c*d2*e + c*d*e2;
00575 double bf = 4*a*b2*f2 + 4*a2*b*f2 + 4*a2*b2*f
00576 - 2*a2*e2*e - 2*b2*d2*d - 2*f2*c2*c
00577 - a*e2*e2 - b*d2*d2 - f*c2*c2
00578 + c*d2*e2 + c2*d*e2 + c2*d2*e;
00579 double af = 4*a2*b2*f2 - a2*e2*e2 - b2*d2*d2 - c2*c2*f2 + c2*d2*e2;
00580
00581
00582
00583 df /= af;
00584 cf /= af;
00585 bf /= af;
00586 af = 1.0;
00587
00588
00589
00590 double p1a = 2*bf*bf - 6*cf;
00591 double p1b = bf*cf - 9*df;
00592 double p0a = cf*p1a*p1a + p1b*(3*p1b - 2*bf*p1a);
00593 double fval, fpval, lambda;
00594
00595 if (p0a < 0 && p1a < 0)
00596 {
00597
00598 valid = false;
00599 return ret;
00600 }
00601
00602 lambda = -bf/3.0;
00603 double displace = 1.0;
00604 if (p1a > 0)
00605 {
00606 displace += sqrt(p1a);
00607
00608
00609 }
00610
00611 fval = bf + lambda;
00612 fval = cf + lambda*fval;
00613 fval = df + lambda*fval;
00614
00615 if (fabs(p0a) < 1e-7)
00616 {
00617 p0a = 1e-7;
00618 }
00619 if (p0a < 0)
00620 {
00621
00622
00623 lambda += ( 2 - zeroindex )* displace;
00624 }
00625 else
00626 {
00627
00628 if( zeroindex > 1 )
00629 {
00630 valid = false;
00631 return ret;
00632 }
00633
00634 if (fval > 0)
00635 {
00636 lambda -= displace;
00637 } else {
00638 lambda += displace;
00639 }
00640
00641
00642 }
00643
00644
00645
00646
00647
00648
00649 double delta;
00650
00651 int iterations = 0;
00652 const int maxiterations = 30;
00653 while (iterations++ < maxiterations)
00654 {
00655
00656 fval = fpval = af;
00657 fval = bf + lambda*fval;
00658 fpval = fval + lambda*fpval;
00659 fval = cf + lambda*fval;
00660 fpval = fval + lambda*fpval;
00661 fval = df + lambda*fval;
00662
00663 delta = fval/fpval;
00664 lambda -= delta;
00665 if (fabs(delta) < 1e-6) break;
00666 }
00667 if (iterations >= maxiterations) { valid = false; return ret; }
00668
00669
00670
00671 a += lambda*a2;
00672 b += lambda*b2;
00673 c += lambda*c2;
00674 d += lambda*d2;
00675 e += lambda*e2;
00676 f += lambda*f2;
00677
00678
00679
00680
00681 df = 4*a*b*f - a*e*e - b*d*d - c*c*f + c*d*e;
00682
00683
00684
00685 double dis1 = e*e - 4*b*f;
00686 double maxval = fabs(dis1);
00687 int maxind = 1;
00688 double dis2 = d*d - 4*a*f;
00689 if (fabs(dis2) > maxval)
00690 {
00691 maxval = fabs(dis2);
00692 maxind = 2;
00693 }
00694 double dis3 = c*c - 4*a*b;
00695 if (fabs(dis3) > maxval)
00696 {
00697 maxval = fabs(dis3);
00698 maxind = 3;
00699 }
00700
00701
00702
00703 double temp;
00704 switch (maxind)
00705 {
00706 case 1:
00707 temp = a; a = f; f = temp;
00708 temp = c; c = e; e = temp;
00709 temp = dis1; dis1 = dis3; dis3 = temp;
00710 break;
00711
00712 case 2:
00713 temp = b; b = f; f = temp;
00714 temp = c; c = d; d = temp;
00715 temp = dis2; dis2 = dis3; dis3 = temp;
00716 break;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 if (dis3 < 0)
00730 {
00731
00732
00733
00734
00735 valid = false;
00736 return ret;
00737 };
00738
00739 double r[3];
00740 r[0] = 2*b*d - c*e;
00741 r[1] = 2*a*e - c*d;
00742 r[2] = dis3;
00743
00744
00745 switch (maxind)
00746 {
00747 case 1:
00748 temp = a; a = f; f = temp;
00749 temp = c; c = e; e = temp;
00750 temp = dis1; dis1 = dis3; dis3 = temp;
00751 temp = r[0]; r[0] = r[2]; r[2] = temp;
00752 break;
00753
00754 case 2:
00755 temp = b; b = f; f = temp;
00756 temp = c; c = d; d = temp;
00757 temp = dis2; dis2 = dis3; dis3 = temp;
00758 temp = r[1]; r[1] = r[2]; r[2] = temp;
00759 break;
00760 }
00761
00762
00763
00764
00765 double w[3];
00766 double rnormsq = r[0]*r[0] + r[1]*r[1] + r[2]*r[2];
00767 double k = sqrt( rnormsq );
00768 if ( k*r[2] < 0) k = -k;
00769 double wnorm = sqrt( 2*rnormsq + 2*k*r[2] );
00770 w[0] = r[0]/wnorm;
00771 w[1] = r[1]/wnorm;
00772 w[2] = (r[2] + k)/wnorm;
00773
00774
00775
00776
00777
00778 double q0 = a*w[0] + c*w[1]/2 + d*w[2]/2;
00779 double q1 = b*w[1] + c*w[0]/2 + e*w[2]/2;
00780 double alpha = a*w[0]*w[0] + b*w[1]*w[1] + c*w[0]*w[1] +
00781 d*w[0]*w[2] + e*w[1]*w[2] + f*w[2]*w[2];
00782 double a00 = a - 4*w[0]*q0 + 4*w[0]*w[0]*alpha;
00783 double a11 = b - 4*w[1]*q1 + 4*w[1]*w[1]*alpha;
00784 double a01 = c/2 - 2*w[1]*q0 - 2*w[0]*q1 + 4*w[0]*w[1]*alpha;
00785
00786 double dis = a01*a01 - a00*a11;
00787 assert ( dis >= 0 );
00788 double sqrtdis = sqrt( dis );
00789 double px, py;
00790 if ( which*a01 > 0 )
00791 {
00792 px = a01 + which*sqrtdis;
00793 py = a11;
00794 } else {
00795 px = a00;
00796 py = a01 - which*sqrtdis;
00797 }
00798 double p[3];
00799 double pscalw = w[0]*px + w[1]*py;
00800 p[0] = px - 2*pscalw*w[0];
00801 p[1] = py - 2*pscalw*w[1];
00802 p[2] = - 2*pscalw*w[2];
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815 ret.a = -p[2]/(p[0]*p[0] + p[1]*p[1]) * Coordinate (p[0],p[1]);
00816 ret.b = ret.a + Coordinate (-p[1],p[0]);
00817 valid = true;
00818
00819 return ret;
00820 }
00821
00822 const ConicCartesianData calcConicTransformation (
00823 const ConicCartesianData& data, const Transformation& t, bool& valid )
00824 {
00825 double a[3][3];
00826 double b[3][3];
00827
00828 a[1][1] = data.coeffs[0];
00829 a[2][2] = data.coeffs[1];
00830 a[1][2] = a[2][1] = data.coeffs[2]/2;
00831 a[0][1] = a[1][0] = data.coeffs[3]/2;
00832 a[0][2] = a[2][0] = data.coeffs[4]/2;
00833 a[0][0] = data.coeffs[5];
00834
00835 Transformation ti = t.inverse( valid );
00836 if ( ! valid ) return ConicCartesianData();
00837
00838 double supnorm = 0.0;
00839 for (int i = 0; i < 3; i++)
00840 {
00841 for (int j = 0; j < 3; j++)
00842 {
00843 b[i][j] = 0.;
00844 for (int ii = 0; ii < 3; ii++)
00845 {
00846 for (int jj = 0; jj < 3; jj++)
00847 {
00848 b[i][j] += a[ii][jj]*ti.data( ii, i )*ti.data( jj, j );
00849 }
00850 }
00851 if ( std::fabs( b[i][j] ) > supnorm ) supnorm = std::fabs( b[i][j] );
00852 }
00853 }
00854
00855 for (int i = 0; i < 3; i++)
00856 {
00857 for (int j = 0; j < 3; j++)
00858 {
00859 b[i][j] /= supnorm;
00860 }
00861 }
00862
00863 return ConicCartesianData ( b[1][1], b[2][2], b[1][2] + b[2][1],
00864 b[0][1] + b[1][0], b[0][2] + b[2][0], b[0][0] );
00865 }
00866
00867 ConicCartesianData::ConicCartesianData()
00868 {
00869 }
00870
00871 bool operator==( const ConicPolarData& lhs, const ConicPolarData& rhs )
00872 {
00873 return lhs.focus1 == rhs.focus1 &&
00874 lhs.pdimen == rhs.pdimen &&
00875 lhs.ecostheta0 == rhs.ecostheta0 &&
00876 lhs.esintheta0 == rhs.esintheta0;
00877 }
00878
00879 ConicCartesianData ConicCartesianData::invalidData()
00880 {
00881 ConicCartesianData ret;
00882 ret.coeffs[0] = double_inf;
00883 return ret;
00884 }
00885
00886 bool ConicCartesianData::valid() const
00887 {
00888 return finite( coeffs[0] );
00889 }
00890