#include <IntAna2d_AnaIntersection.jxx>
  
void IntAna2d_AnaIntersection::Perform(const gp_Lin2d& L,
				       const gp_Circ2d& C) {
 
  done=Standard_False;

  iden=Standard_False; 
  para=Standard_False;

  Standard_Real A,B,C0;
  L.Coefficients(A,B,C0);
  Standard_Real d=A*C.Location().X() + B*C.Location().Y() + C0;

  if (Abs(d)-C.Radius()>Epsilon(C.Radius())) {
    empt=Standard_True;
    nbp=0;
  }
  else {                                       // Au moins 1 solution
    empt=Standard_False;
    Standard_Real ang = C.XAxis().Direction().Angle(L.Direction());
    ang = ang + PI / 2.0;
    if (Abs(Abs(d)-C.Radius())<=Epsilon(C.Radius())) {    // Cas de tangence
      nbp=1;
      Standard_Real u;
      Standard_Real XS=C.Location().X() - d*A;
      Standard_Real YS=C.Location().Y() - d*B;
      u=B*(L.Location().X()-C.Location().X()) -
	A*(L.Location().Y()-C.Location().Y());
      if (d<0.0) {ang=ang+PI;}
      if (ang>=2.0*PI) {
	ang=ang-2.0*PI;
      }
      else if (ang<0.0) {
	ang=ang+2.0*PI;
      }
      lpnt[0].SetValue(XS,YS,u,ang);
    }
    else {                                        // 2 points d intersection
      nbp=2;
      Standard_Real h=Sqrt(C.Radius()*C.Radius()-d*d);

      Standard_Real cost=d/C.Radius();
      Standard_Real sint=h/C.Radius();

      Standard_Real XS1=C.Location().X() - d*A - h*B;
      Standard_Real YS1=C.Location().Y() - d*B + h*A;
      Standard_Real XS2=C.Location().X() - d*A + h*B;
      Standard_Real YS2=C.Location().Y() - d*B - h*A;

      Standard_Real angt;
      if (Abs(cost)<=0.707) {
	angt=ACos(cost);
      }
      else {
	angt=ASin(sint);
	if (cost<0) {angt=PI-angt;}
      }
      Standard_Real ang1,ang2;
      ang1=ang-angt;
      ang2=ang+angt;
      if (ang1<0.0) {
	ang1=ang1+2.0*PI;
      }
      else if (ang1>=2.0*PI) {
	ang1=ang1-2.0*PI;
      }
      if (ang2<0.0) {
	ang2=ang2+2.0*PI;
      }
      else if (ang2>=2.0*PI) {
	ang2=ang2-2.0*PI;
      }

      Standard_Real u1=B*(L.Location().X()-C.Location().X()) -
	      A*(L.Location().Y()-C.Location().Y()) +h;
      Standard_Real u2=u1-2.0*h;
      lpnt[0].SetValue(XS1,YS1,u1,ang1);
      lpnt[1].SetValue(XS2,YS2,u2,ang2);
    }
  }
  done=Standard_True;
}

