home *** CD-ROM | disk | FTP | other *** search
- /* CONMAT.C - Ellipse tranformation and intersection functions */
- /* Written by Kenneth J. Hill, June, 24, 1994 */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <values.h>
-
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
-
- #ifndef M_PI_2
- #define M_PI_2 1.57079632679489661923
- #endif
-
- #ifndef max
- #define max(a,b) ((a)>=(b) ? (a) : (b) )
- #endif
-
- /* Type definitions */
-
- /* Point structure */
- typedef struct PointTag
- {
- double X,Y;
- } Point;
-
- /* Line structure */
- typedef struct LineTag
- {
- Point P1,P2;
- } Line;
-
- /* Circle structure */
- typedef struct CircleTag
- {
- Point Center;
- double Radius;
- } Circle;
-
- /* Ellipse structure */
- typedef struct EllipseTag
- {
- Point Center; /* ellipse center */
- double MaxRad,MinRad; /* major and minor axis */
- double Phi; /* major axis rotation */
- } Ellipse;
-
- /* Conic coefficients structure */
- typedef struct ConicTag
- {
- double A,B,C,D,E,F;
- } Conic;
-
- /* transformation matrix type */
- typedef struct TMatTag
- {
- double a,b,c,d; /* tranformation coefficients */
- double m,n; /* translation coefficients */
- } TMat;
-
- /* prototypes */
-
- /* Functions with names beginning with a O:
- *
- * 1. Ignore ellipse center coordinates.
- *
- * 2. Ignore any translation components in tranformation matrices.
- *
- * 3. Assume that conic coeficients were generated by "O-name" functions.
- *
- * This keeps the computations relatively simple. The ellipse centers
- * can then be transformed separately as points.
- */
-
- /* OTransformConic - Transform conic coefficients about the origin */
- void OTransformConic(Conic *ConicP,TMat *TMatP);
-
- /* OGenEllipseCoefs - Generate conic coefficients of an ellipse */
- void OGenEllipseCoefs(Ellipse *EllipseP,Conic *ConicP);
-
- /* OGenEllipseGeom - Generates ellipse geometry from conic coefficients */
- void OGenEllipseGeom(Conic *ConicP,Ellipse *EllipseP);
-
- /* TransformPoint - Transform a point using a tranformation matrix */
- void TransformPoint(Point *PointP,TMat *TMatP);
-
- /* TransformEllipse - Transform an ellipse using a tranformation matrix */
- void TransformEllipse(Ellipse *EllipseP,TMat *TMatP);
-
- /* The following functions are defined in cubicand.c, on
- the Graphic Gems I diskette. */
- int SolveCubic(double c[4],double s[3]);
- int SolveQuadic(double c[3],double dest[2]);
-
-
- /* Identity matrix */
- static const TMat IdentMat={1.0,0.0,0.0,1.0,0.0,0.0};
-
- /* Transformation matrix routines */
-
- /* Translate a matrix by m,n */
- void TranslateMat(TMat *Mat,double m,double n)
- {
- Mat->m += m;
- Mat->n += n;
- }
-
- /* Rotate a matrix by Phi */
- void RotateMat(TMat *Mat,double Phi)
- {
- double SinPhi=sin(Phi);
- double CosPhi=cos(Phi);
- TMat temp=*Mat; /* temporary copy of Mat */
-
- /* These are just the matrix operations written out long hand */
- Mat->a = temp.a*CosPhi - temp.b*SinPhi;
- Mat->b = temp.b*CosPhi + temp.a*SinPhi;
- Mat->c = temp.c*CosPhi - temp.d*SinPhi;
- Mat->d = temp.d*CosPhi + temp.c*SinPhi;
- Mat->m = temp.m*CosPhi - temp.n*SinPhi;
- Mat->n = temp.n*CosPhi + temp.m*SinPhi;
- }
-
- /* Scale a matrix by sx, sy */
- void ScaleMat(TMat *Mat,double sx,double sy)
- {
- Mat->a *= sx;
- Mat->b *= sy;
- Mat->c *= sx;
- Mat->d *= sy;
- Mat->m *= sx;
- Mat->n *= sy;
- }
-
- /* TransformPoint - Transform a point using a tranformation matrix */
- void TransformPoint(Point *PointP,TMat *TMatP)
- {
- Point TempPoint;
-
- TempPoint.X = PointP->X*TMatP->a + PointP->Y*TMatP->c + TMatP->m;
- TempPoint.Y = PointP->X*TMatP->b + PointP->Y*TMatP->d + TMatP->n;
- *PointP=TempPoint;
- }
-
- /* Conic routines */
-
- /* near zero test */
- #define EPSILON 1e-9
- #define IsZero(x) (x > -EPSILON && x < EPSILON)
-
- /* GenEllipseCoefs - Generate conic coefficients of an ellipse */
- static void GenEllipseCoefs(Ellipse *elip,Conic *M)
- {
- double sqr_r1,sqr_r2;
- double sint,cost,sin2t,sqr_sint,sqr_cost;
- double cenx,ceny,sqr_cenx,sqr_ceny,invsqr_r1,invsqr_r2;
-
- /* common coeficients */
- sqr_r1 = elip->MaxRad;
- sqr_r2 = elip->MinRad;
- sqr_r1 *= sqr_r1;
- sqr_r2 *= sqr_r2;
- sint = sin(elip->Phi);
- cost = cos(elip->Phi);
- sin2t = 2.0*sint*cost;
- sqr_sint = sint*sint;
- sqr_cost = cost*cost;
- cenx = elip->Center.X;
- sqr_cenx = cenx*cenx;
- ceny = elip->Center.Y;
- sqr_ceny = ceny*ceny;
- invsqr_r1 = 1.0/sqr_r1;
- invsqr_r2 = 1.0/sqr_r2;
-
- /* Compute the coefficients. These formulae are the transformations
- on the unit circle written out long hand */
- M->A = sqr_cost/sqr_r1 + sqr_sint/sqr_r2;
- M->B = (sqr_r2-sqr_r1)*sin2t/(2.0*sqr_r1*sqr_r2);
- M->C = sqr_cost/sqr_r2 + sqr_sint/sqr_r1;
- M->D = -ceny*M->B-cenx*M->A;
- M->E = -cenx*M->B-ceny*M->C;
- M->F = -1.0 + (sqr_cenx + sqr_ceny)*(invsqr_r1 + invsqr_r2)/2.0 +
- (sqr_cost - sqr_sint)*(sqr_cenx - sqr_ceny)*(invsqr_r1 - invsqr_r2)/2.0 +
- cenx*ceny*(invsqr_r1 - invsqr_r2)*sin2t;
- }
-
- /* Compute the transformation which turns an ellipse into a circle */
- void Elp2Cir(Ellipse *Elp,TMat *CirMat)
- {
- /* Start with identity matrix */
- *CirMat = IdentMat;
- /* Translate to origin */
- TranslateMat(CirMat,-Elp->Center.X,-Elp->Center.Y);
- /* Rotate into standard position */
- RotateMat(CirMat,-Elp->Phi);
- /* Scale into a circle. */
- ScaleMat(CirMat,1.0/Elp->MaxRad,1.0/Elp->MinRad);
- }
-
- /* Compute the inverse of the transformation
- which turns an ellipse into a circle */
- void InvElp2Cir(Ellipse *Elp,TMat *InvMat)
- {
- /* Start with identity matrix */
- *InvMat = IdentMat;
- /* Scale back into an ellipse. */
- ScaleMat(InvMat,Elp->MaxRad,Elp->MinRad);
- /* Rotate */
- RotateMat(InvMat,Elp->Phi);
- /* Translate from origin */
- TranslateMat(InvMat,Elp->Center.X,Elp->Center.Y);
- }
-
- /* OTransformConic - Transform conic coefficients about the origin */
- /* This routine ignores the translation components of *TMatP and
- assumes the conic is "centered" at the origin (i.e. D,E=0, F=-1) */
- /* The computations are just the matrix operations written out long hand */
- /* This code assumes that the transformation is not degenerate */
- void OTransformConic(Conic *ConicP,TMat *TMatP)
- {
- double A,B,C,Denom;
-
- /* common denominator for transformed cooefficients */
- Denom = TMatP->a*TMatP->d - TMatP->b*TMatP->c;
- Denom *= Denom;
-
- A = (ConicP->C*TMatP->b*TMatP->b - 2.0*ConicP->B*TMatP->b*TMatP->d +
- ConicP->A*TMatP->d*TMatP->d)/Denom;
-
- B = (-ConicP->C*TMatP->a*TMatP->b + ConicP->B*TMatP->b*TMatP->c +
- ConicP->B*TMatP->a*TMatP->d - ConicP->A*TMatP->c*TMatP->d)/Denom;
-
- C = (ConicP->C*TMatP->a*TMatP->a - 2.0*ConicP->B*TMatP->a*TMatP->c +
- ConicP->A*TMatP->c*TMatP->c)/Denom;
-
- ConicP->A=A;
- ConicP->B=B;
- ConicP->C=C;
- }
-
- /* OGenEllipseCoefs - Generate conic coefficients of an ellipse */
- /* The ellipse is assumed to be centered at the origin. */
- void OGenEllipseCoefs(Ellipse *EllipseP,Conic *ConicP)
- {
- double SinPhi = sin(EllipseP->Phi); /* sine of ellipse rotation */
- double CosPhi = cos(EllipseP->Phi); /* cosine of ellipse rotation */
- double SqSinPhi = SinPhi*SinPhi; /* square of sin(phi) */
- double SqCosPhi = CosPhi*CosPhi; /* square of cos(phi) */
- double SqMaxRad = EllipseP->MaxRad*EllipseP->MaxRad;
- double SqMinRad = EllipseP->MinRad*EllipseP->MinRad;
-
- /* compute coefficients for the ellipse in standard position */
- ConicP->A = SqCosPhi/SqMaxRad + SqSinPhi/SqMinRad;
- ConicP->B = (1.0/SqMaxRad - 1.0/SqMinRad)*SinPhi*CosPhi;
- ConicP->C = SqCosPhi/SqMinRad + SqSinPhi/SqMaxRad;
- ConicP->D = ConicP->E = 0.0;
- ConicP->F = -1.0;
- }
-
- /* OGenEllipseGeom - Generates ellipse geometry from conic coefficients */
- /* This routine assumes the conic coefficients D=E=0, F=-1 */
- void OGenEllipseGeom(Conic *ConicP,Ellipse *EllipseP)
- {
- double Numer,Denom,Temp;
- TMat DiagTransform; /* transform diagonalization */
- Conic ConicT = *ConicP; /* temporary copy of conic coefficients */
- double SinPhi,CosPhi;
-
- /* compute new ellipse rotation */
- Numer = ConicT.B + ConicT.B;
- Denom = ConicT.A - ConicT.C;
- /* Phi = 1/2 atan(Numer/Denom) = 1/2 (pi/2 - atan(Denom/Numer)
- We use the form that keeps the argument to atan between -1 and 1 */
-
- EllipseP->Phi = 0.5*(fabs(Numer) < fabs(Denom)?
- atan(Numer/Denom):M_PI_2-atan(Denom/Numer));
-
- /* diagonalize the conic */
- SinPhi = sin(EllipseP->Phi);
- CosPhi = cos(EllipseP->Phi);
- DiagTransform.a = CosPhi; /* rotate by -Phi */
- DiagTransform.b = -SinPhi;
- DiagTransform.c = SinPhi;
- DiagTransform.d = CosPhi;
- DiagTransform.m = DiagTransform.n = 0.0;
- OTransformConic(&ConicT,&DiagTransform);
-
- /* compute new radii from diagonalized coefficients */
- EllipseP->MaxRad = 1.0/sqrt(ConicT.A);
- EllipseP->MinRad = 1.0/sqrt(ConicT.C);
-
- /* be sure MaxRad >= MinRad */
- if (EllipseP->MaxRad < EllipseP->MinRad)
- {
- Temp = EllipseP->MaxRad; /* exchange the radii */
- EllipseP->MaxRad = EllipseP->MinRad;
- EllipseP->MinRad = Temp;
- EllipseP->Phi += M_PI_2; /* adjust the rotation */
- }
- }
-
- /* TransformEllipse - Transform an ellipse using a tranformation matrix */
- void TransformEllipse(Ellipse *EllipseP,TMat *TMatP)
- {
- Conic EllipseCoefs;
-
- /* generate the ellipse coefficients (using Center=origin) */
- OGenEllipseCoefs(EllipseP,&EllipseCoefs);
-
- /* transform the coefficients */
- OTransformConic(&EllipseCoefs,TMatP);
-
- /* turn the transformed coefficients back into geometry */
- OGenEllipseGeom(&EllipseCoefs,EllipseP);
-
- /* translate the center */
- TransformPoint(&EllipseP->Center,TMatP);
- }
-
- /* MultMat3 - Multiply two 3x3 matrices */
- void MultMat3(double *Mat1,double *Mat2, double *Result)
- {
- int i,j;
-
- for (i = 0;i < 3;i++)
- for (j = 0;j < 3;j++)
- Result[i*3+j] = Mat1[i*3+0]*Mat2[0*3+j] +
- Mat1[i*3+1]*Mat2[1*3+j] +
- Mat1[i*3+2]*Mat2[2*3+j];
- }
-
- /* Transform a conic by a tranformation matrix */
- void TransformConic(Conic *ConicP,TMat *TMatP)
- {
- double InvMat[3][3],ConMat[3][3],TranInvMat[3][3];
- double Result1[3][3],Result2[3][3];
- double D;
- int i,j;
-
- /* Compute M' = Inv(TMat).M.Transpose(Inv(TMat))
-
- /* compute the transformation using matrix muliplication */
- ConMat[0][0] = ConicP->A;
- ConMat[0][1] = ConMat[1][0] = ConicP->B;
- ConMat[1][1] = ConicP->C;
- ConMat[0][2] = ConMat[2][0] = ConicP->D;
- ConMat[1][2] = ConMat[2][1] = ConicP->E;
- ConMat[2][2] = ConicP->F;
-
- /* inverse transformation */
- D = TMatP->a*TMatP->d - TMatP->b*TMatP->c;
- InvMat[0][0] = TMatP->d/D;
- InvMat[0][1] = -TMatP->b/D;
- InvMat[0][2] = 0.0;
- InvMat[1][0] = -TMatP->c/D;
- InvMat[1][1] = TMatP->a/D;
- InvMat[1][2] = 0.0;
- InvMat[2][0] = (TMatP->c*TMatP->n - TMatP->d*TMatP->m)/D;
- InvMat[2][1] = (TMatP->b*TMatP->m - TMatP->a*TMatP->n)/D;
- InvMat[2][2] = 1.0;
-
- /* compute transpose */
- for (i = 0;i < 3;i++)
- for (j = 0;j < 3;j++)
- TranInvMat[j][i] = InvMat[i][j];
-
- /* multiply the matrices */
- MultMat3((double *)InvMat,(double *)ConMat,(double *)Result1);
- MultMat3((double *)Result1,(double *)TranInvMat,(double *)Result2);
- ConicP->A = Result2[0][0]; /* return to conic form */
- ConicP->B = Result2[0][1];
- ConicP->C = Result2[1][1];
- ConicP->D = Result2[0][2];
- ConicP->E = Result2[1][2];
- ConicP->F = Result2[2][2];
- }
-
- /* Compute the intersection of a circle and a line */
- /* See Graphic Gems Volume 1, page 5 for a description of this algorithm */
- int IntCirLine(Point *IntPts,Circle *Cir,Line *Ln)
- {
- Point G,V;
- double a,b,c,d,t,sqrt_d;
-
- G.X = Ln->P1.X - Cir->Center.X; /* G = Ln->P1 - Cir->Center */
- G.Y = Ln->P1.Y - Cir->Center.Y;
- V.X = Ln->P2.X - Ln->P1.X; /* V = Ln->P2 - Ln->P1 */
- V.Y = Ln->P2.Y - Ln->P1.Y;
- a = V.X*V.X + V.Y*V.Y; /* a = V.V */
- b = V.X*G.X + V.Y*G.Y;b += b; /* b = 2(V.G) */
- c = (G.X*G.X + G.Y*G.Y) - /* c = G.G + Circle->Radius^2 */
- Cir->Radius*Cir->Radius;
- d = b*b - 4.0*a*c; /* discriminant */
-
- if (d <= 0.0)
- return 0; /* no intersections */
-
- sqrt_d = sqrt(d);
- t = (-b + sqrt_d)/(a + a); /* t = (-b +/- sqrt(d))/2a */
- IntPts[0].X = Ln->P1.X + t*V.X; /* Pt = Ln->P1 + t V */
- IntPts[0].Y = Ln->P1.Y + t*V.Y;
- t = (-b - sqrt_d)/(a + a);
- IntPts[1].X = Ln->P1.X + t*V.X;
- IntPts[1].Y = Ln->P1.Y + t*V.Y;
- return 2;
- }
-
- /* compute all intersections of two ellipses */
- /* E1 and E2 are the two ellipses */
- /* IntPts points to an array of twelve points
- (some duplicates may be returned) */
- /* The number of intersections found is returned */
- /* Both ellipses are assumed to have non-zero radii */
- int Int2Elip(Point *IntPts,Ellipse *E1,Ellipse *E2)
- {
- TMat ElpCirMat1,ElpCirMat2,InvMat,TempMat;
- Conic Conic1,Conic2,Conic3,TempConic;
- double Roots[3],qRoots[2];
- static Circle TestCir = {{0.0,0.0},1.0};
- Line TestLine[2];
- Point TestPoint;
- double PolyCoef[4]; /* coefficients of the polynomial */
- double D; /* discriminant: B^2 - AC */
- double Phi; /* ellipse rotation */
- double m,n; /* ellipse translation */
- double Scl; /* scaling factor */
- int NumRoots,NumLines;
- int CircleInts; /* intersections between line and circle */
- int IntCount = 0; /* number of intersections found */
- int i,j,k;
-
- /* compute the transformations which turn E1 and E2 into circles */
- Elp2Cir(E1,&ElpCirMat1);
- Elp2Cir(E2,&ElpCirMat2);
-
- /* compute the inverse transformation of ElpCirMat1 */
- InvElp2Cir(E1,&InvMat);
-
- /* Compute the characteristic matrices */
- GenEllipseCoefs(E1,&Conic1);
- GenEllipseCoefs(E2,&Conic2);
-
- /* Find x such that Det(Conic1 + x Conic2) = 0 */
- PolyCoef[0] = -Conic1.C*Conic1.D*Conic1.D + 2.0*Conic1.B*Conic1.D*Conic1.E -
- Conic1.A*Conic1.E*Conic1.E - Conic1.B*Conic1.B*Conic1.F +
- Conic1.A*Conic1.C*Conic1.F;
- PolyCoef[1] = -(Conic2.C*Conic1.D*Conic1.D) -
- 2.0*Conic1.C*Conic1.D*Conic2.D + 2.0*Conic2.B*Conic1.D*Conic1.E +
- 2.0*Conic1.B*Conic2.D*Conic1.E - Conic2.A*Conic1.E*Conic1.E +
- 2.0*Conic1.B*Conic1.D*Conic2.E - 2.0*Conic1.A*Conic1.E*Conic2.E -
- 2.0*Conic1.B*Conic2.B*Conic1.F + Conic2.A*Conic1.C*Conic1.F +
- Conic1.A*Conic2.C*Conic1.F - Conic1.B*Conic1.B*Conic2.F +
- Conic1.A*Conic1.C*Conic2.F;
- PolyCoef[2] = -2.0*Conic2.C*Conic1.D*Conic2.D - Conic1.C*Conic2.D*Conic2.D +
- 2.0*Conic2.B*Conic2.D*Conic1.E + 2.0*Conic2.B*Conic1.D*Conic2.E +
- 2.0*Conic1.B*Conic2.D*Conic2.E - 2.0*Conic2.A*Conic1.E*Conic2.E -
- Conic1.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic1.F +
- Conic2.A*Conic2.C*Conic1.F - 2.0*Conic1.B*Conic2.B*Conic2.F +
- Conic2.A*Conic1.C*Conic2.F + Conic1.A*Conic2.C*Conic2.F;
- PolyCoef[3] = -Conic2.C*Conic2.D*Conic2.D + 2.0*Conic2.B*Conic2.D*Conic2.E -
- Conic2.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic2.F +
- Conic2.A*Conic2.C*Conic2.F;
- NumRoots = SolveCubic(PolyCoef,Roots);
-
- if (NumRoots == 0)
- return 0;
-
- /* we try all the roots, even though it's redundant, so that we
- avoid some pathological situations */
- for (i=0;i<NumRoots;i++)
- {
- NumLines = 0;
-
- /* Conic3 = Conic1 + mu Conic2 */
- Conic3.A = Conic1.A + Roots[i]*Conic2.A;
- Conic3.B = Conic1.B + Roots[i]*Conic2.B;
- Conic3.C = Conic1.C + Roots[i]*Conic2.C;
- Conic3.D = Conic1.D + Roots[i]*Conic2.D;
- Conic3.E = Conic1.E + Roots[i]*Conic2.E;
- Conic3.F = Conic1.F + Roots[i]*Conic2.F;
-
- D = Conic3.B*Conic3.B - Conic3.A*Conic3.C;
- if (IsZero(Conic3.A) && IsZero(Conic3.B) && IsZero(Conic3.C))
- {
- /* Case 1 - Single line */
- NumLines = 1;
- /* compute endpoints of the line, avoiding division by zero */
- if (fabs(Conic3.D) > fabs(Conic3.E))
- {
- TestLine[0].P1.Y = 0.0;
- TestLine[0].P1.X = -Conic3.F/(Conic3.D + Conic3.D);
- TestLine[0].P2.Y = 1.0;
- TestLine[0].P2.X = -(Conic3.E + Conic3.E + Conic3.F)/
- (Conic3.D + Conic3.D);
- }
- else
- {
- TestLine[0].P1.X = 0.0;
- TestLine[0].P1.Y = -Conic3.F/(Conic3.E + Conic3.E);
- TestLine[0].P2.X = 1.0;
- TestLine[0].P2.X = -(Conic3.D + Conic3.D + Conic3.F)/
- (Conic3.E + Conic3.E);
- }
- }
- else
- {
- /* use the espresion for Phi that takes atan of the
- smallest argument */
- Phi = (fabs(Conic3.B + Conic3.B) < fabs(Conic3.A-Conic3.C)?
- atan((Conic3.B + Conic3.B)/(Conic3.A - Conic3.C)):
- M_PI_2 - atan((Conic3.A - Conic3.C)/(Conic3.B + Conic3.B)))/2.0;
- if (IsZero(D))
- {
- /* Case 2 - Parallel lines */
- TempConic = Conic3;
- TempMat = IdentMat;
- RotateMat(&TempMat,-Phi);
- TransformConic(&TempConic,&TempMat);
- if (IsZero(TempConic.C)) /* vertical */
- {
- PolyCoef[0] = TempConic.F;
- PolyCoef[1] = TempConic.D;
- PolyCoef[2] = TempConic.A;
- if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0)
- {
- TestLine[0].P1.X = qRoots[0];
- TestLine[0].P1.Y = -1.0;
- TestLine[0].P2.X = qRoots[0];
- TestLine[0].P2.Y = 1.0;
- if (NumLines==2)
- {
- TestLine[1].P1.X = qRoots[1];
- TestLine[1].P1.Y = -1.0;
- TestLine[1].P2.X = qRoots[1];
- TestLine[1].P2.Y = 1.0;
- }
- }
- }
- else /* horizontal */
- {
- PolyCoef[0] = TempConic.F;
- PolyCoef[1] = TempConic.E;
- PolyCoef[2] = TempConic.C;
- if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0)
- {
- TestLine[0].P1.X = -1.0;
- TestLine[0].P1.Y = qRoots[0];
- TestLine[0].P2.X = 1.0;
- TestLine[0].P2.Y = qRoots[0];
- if (NumLines==2)
- {
- TestLine[1].P1.X = -1.0;
- TestLine[1].P1.Y = qRoots[1];
- TestLine[1].P2.X = 1.0;
- TestLine[1].P2.Y = qRoots[1];
- }
- }
- }
- TempMat = IdentMat;
- RotateMat(&TempMat,Phi);
- TransformPoint(&TestLine[0].P1,&TempMat);
- TransformPoint(&TestLine[0].P2,&TempMat);
- if (NumLines==2)
- {
- TransformPoint(&TestLine[1].P1,&TempMat);
- TransformPoint(&TestLine[1].P2,&TempMat);
- }
- }
- else
- {
- /* Case 3 - Crossing lines */
- NumLines = 2;
-
- /* translate the system so that the intersection of the lines
- is at the origin */
- TempConic = Conic3;
- m = (Conic3.C*Conic3.D - Conic3.B*Conic3.E)/D;
- n = (Conic3.A*Conic3.E - Conic3.B*Conic3.D)/D;
- TempMat = IdentMat;
- TranslateMat(&TempMat,-m,-n);
- RotateMat(&TempMat,-Phi);
- TransformConic(&TempConic,&TempMat);
-
- /* Compute the line endpoints */
- TestLine[0].P1.X = sqrt(fabs(1.0/TempConic.A));
- TestLine[0].P1.Y = sqrt(fabs(1.0/TempConic.C));
- Scl = max(TestLine[0].P1.X,TestLine[0].P1.Y); /* adjust range */
- TestLine[0].P1.X /= Scl;
- TestLine[0].P1.Y /= Scl;
- TestLine[0].P2.X = - TestLine[0].P1.X;
- TestLine[0].P2.Y = - TestLine[0].P1.Y;
- TestLine[1].P1.X = TestLine[0].P1.X;
- TestLine[1].P1.Y = - TestLine[0].P1.Y;
- TestLine[1].P2.X = - TestLine[1].P1.X;
- TestLine[1].P2.Y = - TestLine[1].P1.Y;
-
- /* translate the lines back */
- TempMat = IdentMat;
- RotateMat(&TempMat,Phi);
- TranslateMat(&TempMat,m,n);
- TransformPoint(&TestLine[0].P1,&TempMat);
- TransformPoint(&TestLine[0].P2,&TempMat);
- TransformPoint(&TestLine[1].P1,&TempMat);
- TransformPoint(&TestLine[1].P2,&TempMat);
- }
- }
-
- /* find the ellipse line intersections */
- for (j = 0;j < NumLines;j++)
- {
- /* transform the line endpts into the circle space of the ellipse */
- TransformPoint(&TestLine[j].P1,&ElpCirMat1);
- TransformPoint(&TestLine[j].P2,&ElpCirMat1);
-
- /* compute the number of intersections of the transformed line
- and test circle */
- CircleInts = IntCirLine(&IntPts[IntCount],&TestCir,&TestLine[j]);
- if (CircleInts>0)
- {
- /* transform the intersection points back into ellipse space */
- for (k = 0;k < CircleInts;k++)
- TransformPoint(&IntPts[IntCount+k],&InvMat);
- /* update the number of intersections found */
- IntCount += CircleInts;
- }
- }
- }
- /* validate the points */
- j = IntCount;
- IntCount = 0;
- for (i = 0;i < j;i++)
- {
- TestPoint = IntPts[i];
- TransformPoint(&TestPoint,&ElpCirMat2);
- if (TestPoint.X < 2.0 && TestPoint.Y < 2.0 &&
- IsZero(1.0 - sqrt(TestPoint.X*TestPoint.X +
- TestPoint.Y*TestPoint.Y)))
- IntPts[IntCount++]=IntPts[i];
- }
- return IntCount;
- }
-
- /* Test routines */
-
- /* Ellipse with center at (1,2), major radius 2, minor radius 1,
- and rotation 0. */
- Ellipse TestEllipse={{2.0,1.0},2.0,1.0,0.0};
-
- /* Transform matrix for shear of 45 degrees from vertical */
- TMat TestTransform={1.0,0.0,1.0,1.0,0.0,0.0};
-
- /* Display an ellipse. This version lists the structure values. */
- void DisplayEllipse(Ellipse *EllipseP)
- {
- printf("\tCenter at (%6.3f,%6.3f)\n"
- "\tMajor radius: %6.3f\n"
- "\tMinor radius: %6.3f\n"
- "\tRotation: %6.3f degrees\n\n",
- EllipseP->Center.X,EllipseP->Center.Y,
- EllipseP->MaxRad,EllipseP->MinRad,
- 180.0*EllipseP->Phi/M_PI);
- }
-
-
- /* test ellipses for intersection */
- Ellipse Elp1={{5.0,4.0},1.0,0.5,M_PI/3.0};
- Ellipse Elp2={{4.0,3.0},2.0,1.0,0.0};
- Ellipse Elp3={{1.0,1.0},2.0,1.0,M_PI_2};
- Ellipse Elp4={{1.0,1.0},2.0,0.5,0.0};
-
- void main(void)
- {
- Point IntPts[12];
- int IntCount;
- int i;
-
- /* find ellipse intersections */
- printf("Intersections of ellipses 1 & 2:\n\n");
- IntCount=Int2Elip(IntPts,&Elp1,&Elp2);
- for (i = 0;i < IntCount;i++)
- printf(" %f, %f\n",IntPts[i].X,IntPts[i].Y);
- printf("Intersections of ellipses 3 & 4:\n");
- IntCount=Int2Elip(IntPts,&Elp3,&Elp4);
- for (i = 0;i < IntCount;i++)
- printf(" %f, %f\n",IntPts[i].X,IntPts[i].Y);
-
- /* transform ellipses */
- printf("\n\nBefore transformation:\n");
- DisplayEllipse(&TestEllipse);
-
- TransformEllipse(&TestEllipse,&TestTransform);
-
- printf("After transformation:\n");
- DisplayEllipse(&TestEllipse);
- }
-