Logo Search packages:      
Sourcecode: opencascade version File versions  Download package

AIS_IdenticRelation.cxx

// File:    AIS_IdenticRelation.cxx
// Created: Mon Mar  3 17:21:37 1997
// Author:  Jean-Pierre COMBE
//          <jpr>


#include <Standard_NotImplemented.hxx>

#include <AIS_IdenticRelation.ixx>

#include <AIS.hxx>
#include <AIS_Shape.hxx>
#include <AIS_Drawer.hxx>

#include <BRep_Tool.hxx>

#include <DsgPrs_IdenticPresentation.hxx>

#include <ElCLib.hxx>

#include <Geom_Circle.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>

#include <Precision.hxx>

#include <Prs3d_Drawer.hxx>
#include <Prs3d_LineAspect.hxx>

#include <Select3D_SensitiveCurve.hxx>
#include <Select3D_SensitiveSegment.hxx>
#include <SelectMgr_EntityOwner.hxx>

#include <TColStd_ListIteratorOfListOfTransient.hxx>

#include <StdPrs_WFDeflectionShape.hxx>

#include <TCollection_ExtendedString.hxx>

#include <TopAbs.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>

#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pln.hxx>
#include <gp_Vec.hxx>

// jfa 15/10/2000
#include <Geom_Ellipse.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>

static Standard_Real Modulo2PI(const Standard_Real ANGLE)
{
  if ( ANGLE < 0 )          return Modulo2PI(ANGLE + 2*PI);
  else if ( ANGLE >= 2*PI ) return Modulo2PI(ANGLE - 2*PI);
  return ANGLE;
}

static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
                           const Standard_Real angle2, const Standard_Real precision)
{
  Standard_Real diff = Abs(angle1-angle2);
  if ( diff < precision )                return Standard_True;
  else if ( Abs(diff-2*PI) < precision ) return Standard_True;
  return Standard_False;
}
// jfa 15/10/2000 end

//=======================================================================
//function : AIS_Sort
//purpose  : sort an array of parameters <tab1> in increasing order
//           updates <tab2> and <tab3> according to <tab1>
//=======================================================================
static void AIS_Sort(Standard_Real tab1[4],
                 gp_Pnt tab2[4],
                 Standard_Integer tab3[4])
{
  Standard_Boolean found = Standard_True;
  Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
  
  while (found) {
    found = Standard_False;
    for (Standard_Integer i=0; i< 3; i++) {
      if (tab1[i+1] < tab1[i]) {
      found = Standard_True;
      cur = tab1[i]; cur1 = tab2[i]; cur2 = tab3[i];
      tab1[i] = tab1[i+1]; tab2[i] = tab2[i+1]; tab3[i] = tab3[i+1]; 
      tab1[i+1] = cur; tab2[i+1] = cur1; tab3[i+1] = cur2; 
      }
    }
  }
}

//=======================================================================
//function : ConnectedEdges
//purpose  : 
//=======================================================================
static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
                               const TopoDS_Vertex& V, 
                               TopoDS_Edge& E1, 
                               TopoDS_Edge& E2)
{
  TopTools_IndexedDataMapOfShapeListOfShape  vertexMap;
  TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
  
  Standard_Boolean found(Standard_False);
  TopoDS_Vertex theVertex;
  for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
    if (vertexMap.FindKey(i).IsSame(V)) {
      theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
      found = Standard_True;
    }
  }
  if (!found) {
    E1.Nullify();
    E2.Nullify();
    return Standard_False;
  }
  
  TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
  if (iterator.More()) {
    E1 = TopoDS::Edge(iterator.Value());
    iterator.Next();
  }
  else {
    E1.Nullify();
    return Standard_False;
  }
  
  if (iterator.More()) {
    E2 = TopoDS::Edge(iterator.Value());
    iterator.Next();
  }
  else {
    E2.Nullify();
    return Standard_False;
  }
  
  if (iterator.More()) {
    E1.Nullify();
    E2.Nullify();
    return Standard_False;
  }
  return Standard_True;
}

// jfa 16/10/2000
//=======================================================================
//function : ComputeAttach
//purpose  : Compute a point on the arc of <thecirc>
//             between <aFAttach> and <aSAttach>
//             corresponding to <aPosition>
//           Returns result into <aPosition>
// Note    : This function is to be used only in the case of circles.
//           The <aPosition> parameter is in/out.
//=======================================================================
static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
                              const gp_Pnt& aFAttach,
                              const gp_Pnt& aSAttach,
                              gp_Pnt& aPosition)
{
  gp_Pnt curpos = aPosition;

  // Case of confusion between the current position and the center 
  // of the circle -> we move the current position
  Standard_Real confusion (Precision::Confusion());
  gp_Pnt aCenter = thecirc.Location();
  if ( aCenter.Distance(curpos) <= confusion )
    {
      gp_Vec vprec(aCenter, aFAttach);
      vprec.Normalize();
      curpos.Translate(vprec*1e-5);
    }
  
  Standard_Real pcurpos  = ElCLib::Parameter(thecirc,curpos);
  Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
  Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);

  Standard_Real pSAttachM = pSAttach;
  Standard_Real deltap = pSAttachM - pFAttach;
  if ( deltap < 0 )
    {
      deltap += 2*Standard_PI;
      pSAttachM += 2*Standard_PI;
    }
  pSAttachM -= pFAttach;

  Standard_Real pmiddleout = pSAttachM/2.0 + Standard_PI;

  Standard_Real pcurpos1 = pcurpos;
  // define where curpos lays
  if ( pcurpos1 < pFAttach )
    {
      pcurpos1 = pcurpos1 + 2*Standard_PI - pFAttach;
      if ( pcurpos1 > pSAttachM ) // out
      {
        if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
        else pcurpos = pSAttach;
      }
    }
  else if ( pcurpos1 > (pFAttach + deltap) ) // out
    {
      pcurpos1 -= pFAttach;
      if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
      else pcurpos = pSAttach;
    }

  aPosition = ElCLib::Value(pcurpos,thecirc);
  return Standard_True;
}

//=======================================================================
//function : ComputeAttach
//purpose  : Compute a point on the arc of ellipse <theEll>
//             between <aFAttach> and <aSAttach>
//             corresponding to <aPosition>
//           Returns result into <aPosition>
// Note    : This function is to be used only in the case of ellipses.
//           The <aPosition> parameter is in/out.
//=======================================================================
static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
                              const gp_Pnt& aFAttach,
                              const gp_Pnt& aSAttach,
                              gp_Pnt& aPosition)
{
  gp_Pnt curpos = aPosition;

  // Case of confusion between the current position and the center 
  // of the circle -> we move the current position
  Standard_Real confusion (Precision::Confusion());
  gp_Pnt aCenter = theEll.Location();
  if ( aCenter.Distance(curpos) <= confusion )
    {
      gp_Vec vprec(aCenter, aFAttach);
      vprec.Normalize();
      curpos.Translate(vprec*1e-5);
    }
  
// for ellipses it's not good  Standard_Real pcurpos  = ElCLib::Parameter(theEll,curpos);
  Handle(Geom_Ellipse) theEllg = new Geom_Ellipse(theEll);
  GeomAPI_ProjectPointOnCurve aProj (curpos, theEllg);
  Standard_Real pcurpos  = aProj.LowerDistanceParameter();

  Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
  Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);

  Standard_Real pSAttachM = pSAttach;
  Standard_Real deltap = pSAttachM - pFAttach;
  if ( deltap < 0 )
    {
      deltap += 2*Standard_PI;
      pSAttachM += 2*Standard_PI;
    }
  pSAttachM -= pFAttach;

  Standard_Real pmiddleout = pSAttachM/2.0 + Standard_PI;

  Standard_Real pcurpos1 = pcurpos;
  // define where curpos lays
  if ( pcurpos1 < pFAttach )
    {
      pcurpos1 = pcurpos1 + 2*Standard_PI - pFAttach;
      if ( pcurpos1 > pSAttachM ) // out
      {
        if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
        else pcurpos = pSAttach;
      }
    }
  else if ( pcurpos1 > (pFAttach + deltap) ) // out
    {
      pcurpos1 -= pFAttach;
      if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
      else pcurpos = pSAttach;
    }

  aPosition = ElCLib::Value(pcurpos,theEll);
  return Standard_True;
}
// jfa 16/10/2000 end

//=======================================================================
//function : AIS_IdenticRelation
//purpose  : 
//=======================================================================
00292 AIS_IdenticRelation::AIS_IdenticRelation(const TopoDS_Shape& FirstShape, 
                               const TopoDS_Shape& SecondShape, 
                               const Handle(Geom_Plane)& aPlane)
  :isCircle(Standard_False)
{
  myFShape = FirstShape;
  mySShape = SecondShape;
  myPlane  = aPlane;
}

//=======================================================================
//function : Compute
//purpose  : 
//=======================================================================
00306 void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&, 
                          const Handle(Prs3d_Presentation)& aprs, 
                          const Standard_Integer)
{
  aprs->Clear();

  switch ( myFShape.ShapeType() ) {
    
  case TopAbs_VERTEX:
    {
      switch ( mySShape.ShapeType() ) {
      case TopAbs_VERTEX:
      {
        ComputeTwoVerticesPresentation(aprs);
      }
      break;
      case TopAbs_EDGE:
      {
        ComputeOneEdgeOVertexPresentation(aprs);
      }
      break;
      default:
      break;
      }
    }
    break;
    
  case TopAbs_EDGE:
    {
      switch ( mySShape.ShapeType() ) {
      case TopAbs_VERTEX:
      {
        ComputeOneEdgeOVertexPresentation(aprs);
      }
      break;
      case TopAbs_EDGE:
      {
        ComputeTwoEdgesPresentation(aprs);        
      }
      break;
      default:
      break;
      }
    }
  break;
  default: break;
  }
}

//=======================================================================
//function : Compute
//purpose  : 
//=======================================================================
00359 void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
                          const Handle(Prs3d_Presentation)& aPresentation)
{
// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
}

//=======================================================================
//function : Compute
//purpose  : 
//=======================================================================
00370 void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d, 
                          const Handle(Graphic2d_GraphicObject)& aGraphicObject, 
                          const Standard_Integer anInteger)
{
// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
 PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ; 
}

void AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
{
// Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
}

//=======================================================================
//function : ComputeSelection
//purpose  : function used to compute the selection associated to the 
//           "identic" presentation
// note    : if we are in the case of lines, we create a segment between
//           myFAttach and mySAttach. In the case of Circles, we create
//           an arc of circle between the sames points.We Add a segment
//           to link Position to its projection on the curve described
//           before.
//=======================================================================

00395 void AIS_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
                                 const Standard_Integer)
{
  Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);

  Handle(Select3D_SensitiveSegment) seg;
  // attachement point of the segment linking position to the curve
  gp_Pnt attach; 
  Standard_Real confusion (Precision::Confusion());
    
  if ( myFAttach.IsEqual(mySAttach, confusion) )
    {
      attach = myFAttach;
    }
  else
    {    
// jfa 24/10/2000
      if ( myFShape.ShapeType() == TopAbs_EDGE )
      {
        Handle(Geom_Curve) curv1,curv2;
        gp_Pnt firstp1,lastp1,firstp2,lastp2;
        Standard_Boolean isInfinite1,isInfinite2;
        Handle(Geom_Curve) extCurv;
        if ( !AIS::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
                             myExtShape,curv1,curv2,
                             firstp1,lastp1,firstp2,lastp2,
                             extCurv,isInfinite1,isInfinite2,myPlane) ) return;

        if ( isCircle ) // case of Circles
          {
            Handle(Geom_Circle) thecirc = (Handle(Geom_Circle)&) curv1;
            Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
            Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
            Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
      
            Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
            aSelection->Add(scurv);
      
            attach = myPosition;
            ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
          }
        else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
          {
            Handle(Geom_Ellipse) theEll = (Handle(Geom_Ellipse)&) curv1;

            Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
            Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
            Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
      
            Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
            aSelection->Add(scurv);
      
            attach = myPosition;
            ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
          }
        else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
          {
            seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
            aSelection->Add(seg);
            
            //attach = projection de Position() sur la curve;
            gp_Vec v1 (myFAttach, mySAttach);
            gp_Vec v2 (myFAttach, myPosition);
            if ( v1.IsParallel(v2, Precision::Angular()) )
            {
              attach = mySAttach;
            }
            else
            {
              gp_Lin ll (myFAttach, gp_Dir(v1));
              attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
            }
          }
        else return;
      }
//      else if ( myFShape.ShapeType() == TopAbs_VERTEX )
//    {
//    }
// jfa 24/10/2000 end
    }

  // Creation of the segment linking the attachement point with the
  // position
  if ( !attach.IsEqual(myPosition, confusion) )
    {
      seg = new Select3D_SensitiveSegment(own, attach, myPosition);
      aSelection->Add(seg);
    }
}

//=======================================================================
//function : ComputeTwoEdgesPresentation
//purpose  : 
//=======================================================================
void AIS_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
{
  Handle(Geom_Curve) curv1,curv2;
  gp_Pnt firstp1,lastp1,firstp2,lastp2;
  Standard_Boolean isInfinite1,isInfinite2;

  Handle(Geom_Curve) extCurv;
  if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
                      TopoDS::Edge(mySShape),
                      myExtShape,
                      curv1,
                      curv2,
                      firstp1,
                      lastp1,
                      firstp2,
                      lastp2,
                      extCurv,
                      isInfinite1,isInfinite2,
                      myPlane))
    return;
  aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);

  // Treatement of the case of lines
  if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) && curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
    // we take the line curv1 like support
    Handle(Geom_Line) thelin;
    if (isInfinite1 && !isInfinite2) thelin = (Handle(Geom_Line)&) curv2;
    else if (!isInfinite1 && isInfinite2) thelin = (Handle(Geom_Line)&) curv1;
    else thelin = (Handle(Geom_Line)&) curv1;
    ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
  }

  //  Treatement of the case of circles
  else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
    //gp_Pnt curpos;
    isCircle = Standard_True; // usefull for ComputeSelection
    const Handle(Geom_Circle)& thecirc = (Handle(Geom_Circle)&) curv1;
    ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
  }

  // jfa 10/10/2000
  //  Treatement of the case of ellipses
  else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
      {
      const Handle(Geom_Ellipse)& theEll = (Handle(Geom_Ellipse)&) curv1;
      ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
      }
  // jfa 10/10/2000 end
  else
    return;

 // Calcul de la presentation des edges projettees
 if ( (myExtShape != 0) &&  !extCurv.IsNull()) {
   if (myExtShape == 1 )
     ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
   else
     ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
 }
}

//=======================================================================
//function : ComputeTwoLinesPresentation
//purpose  : Compute the presentation of the 'identic' constraint
//           between two lines ( which are equal)
//input    : <thelin> : the 
//           <firstp1>: first extremity of the 1st curve of the constraint
//           <lastp1> : last extremity of the 1st curve of the constraint
//           <firstp2>: first extremity of the 2nd curve of the constraint
//           <lastp2> :last extremity of the 2nd curve of the constraint
//=======================================================================
void AIS_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs, 
                                          const Handle(Geom_Line)& thelin,
                                          gp_Pnt& firstp1,
                                          gp_Pnt& lastp1,
                                          gp_Pnt& firstp2,
                                          gp_Pnt& lastp2,
                                          const Standard_Boolean isInfinite1,
                                          const Standard_Boolean isInfinite2)
{
  if (isInfinite1 && isInfinite2) {
    if ( myAutomaticPosition ) {
      myFAttach = mySAttach = thelin->Lin().Location();
      gp_Pnt curpos;
      gp_Pln pln(myPlane->Pln());
      gp_Dir dir(pln.XAxis().Direction());
      gp_Vec transvec = gp_Vec(dir)*myArrowSize;
      curpos = myFAttach.Translated(transvec);;
      myPosition = curpos;
      myAutomaticPosition = Standard_True;
    }
    else {
      myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());            
    }
    TCollection_ExtendedString vals(" ==");
    DsgPrs_IdenticPresentation::Add(aPrs,
                            myDrawer,
                            vals,
                            myFAttach,
                            myPosition);    
  }
  else {
    // Computation of the parameters of the 4 points on the line <thelin>
    Standard_Real pf1, pf2, pl1, pl2;    

    pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
    pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);

    pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
    pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);

    if (isInfinite1) {
      pf1 = pf2;
      pl1 = pl2;
      firstp1 = firstp2;
      lastp1 = lastp2;
    }
    else if (isInfinite2) {
      pf2 = pf1;
      pl2 = pl1;
      firstp2 = firstp1;
      lastp2 = lastp1;
    }

    Standard_Real tabRang1[4];      // array taht contains the parameters of the 4 points
    // ordered by increasing abscisses.

    gp_Pnt tabRang2[4];             // array containing the points corresponding to the
    // parameters in tabRang1

    Standard_Integer tabRang3[4];   // array containing the number of the curve( 1 or 2)
    // of which belongs each point of tabRang2

    // Filling of the arrays
    tabRang1[0] = pf1; tabRang2[0] = firstp1; tabRang3[0] = 1;
    tabRang1[1] = pf2; tabRang2[1] = firstp2; tabRang3[1] = 2;
    tabRang1[2] = pl1; tabRang2[2] = lastp1;  tabRang3[2] = 1;
    tabRang1[3] = pl2; tabRang2[3] = lastp2;  tabRang3[3] = 2;

  // Sort of the array of parameters (tabRang1)
    AIS_Sort(tabRang1, tabRang2, tabRang3);

    // Computation of myFAttach and mySAttach according to the
    // position of the 2 linear edges
    gp_Pnt curpos;
    gp_Pnt middle;
  
    if ( (tabRang1[0] == tabRang1[1]) && (tabRang1[2] == tabRang1[3]) ) {
      middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
      Standard_Real pmiddle = (tabRang1[1] + tabRang1[2]) / 2.;
      Standard_Real delta = (tabRang1[3] - tabRang1[0])/ 5.;
      myFAttach = ElCLib::Value(pmiddle-delta, thelin->Lin());
      mySAttach = ElCLib::Value(pmiddle+delta, thelin->Lin());
    }
  
    else if ( tabRang1[1] == tabRang1[2] ) {
      middle = tabRang2[1];
      Standard_Real delta1 = tabRang1[1] - tabRang1[0];
      Standard_Real delta2 = tabRang1[3] - tabRang1[2];
      if ( delta1 > delta2 ) delta1 = delta2;
      myFAttach = ElCLib::Value(tabRang1[1]-delta1/2., thelin->Lin());
      mySAttach = ElCLib::Value(tabRang1[1]+delta1/2., thelin->Lin());
    }
  
    // Case of 2 disconnected segments -> the symbol completes the gap 
    //                                    between the 2 edges
    //--------------------------------
    else if ( (tabRang3[0] == tabRang3[1]) && (tabRang1[1] != tabRang1[2])) {
      middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
      myFAttach = tabRang2[1];
      mySAttach = tabRang2[2];
    }
    else if ( (tabRang3[0] != tabRang3[1]) 
            && (tabRang3[1] != tabRang3[2])    // Intersection
            && (tabRang1[1] != tabRang1[2]) ) { 
      middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
      myFAttach = tabRang2[1];
      mySAttach = tabRang2[2];
    }
    else {                                     // Inclusion
      myFAttach.SetXYZ((tabRang2[0].XYZ() + tabRang2[1].XYZ())/2. );
      mySAttach.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
      middle.SetXYZ( (myFAttach.XYZ() + mySAttach.XYZ() )/2.);
    }
  

    if ( myAutomaticPosition ) {
    
      gp_Vec vtrans(myFAttach, mySAttach);
      vtrans.Normalize();
      vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
      vtrans *= ComputeSegSize();
      curpos = middle.Translated(vtrans);
      myPosition = curpos;
      myAutomaticPosition = Standard_True;
    }

    else {

      curpos = myPosition;
      Standard_Real pcurpos = ElCLib::Parameter(thelin->Lin() ,curpos);
      Standard_Real dist = thelin->Lin().Distance(curpos);
      gp_Pnt proj = ElCLib::Value( pcurpos, thelin->Lin());
      gp_Vec  trans;
      Standard_Real confusion(Precision::Confusion());
      if ( dist >= confusion ) {
      trans = gp_Vec(proj, curpos);
      trans.Normalize();
      }
      Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
      Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
      if ( pcurpos <= pf ) {
      pcurpos = pf + 1e-5;
      curpos = ElCLib::Value( pcurpos, thelin->Lin());
      if ( dist >= confusion ) curpos.Translate(trans*dist);
      }
      else if ( pcurpos >= pl ) {
      pcurpos = pl - 1e-5;
      curpos = ElCLib::Value( pcurpos, thelin->Lin());
      if ( dist >= confusion ) curpos.Translate(trans*dist);
      }
      SetPosition(curpos);
    }

    // Display of the presentation
    TCollection_ExtendedString vals(" ==");
    DsgPrs_IdenticPresentation::Add(aPrs,
                            myDrawer,
                            vals,
                            myFAttach,
                            mySAttach,
                            curpos);
  }
}

// jfa 17/10/2000
//=======================================================================
//function : ComputeTwoCirclesPresentation
//purpose  : Compute the presentation of the 'identic' constraint
//           between two circles ( which are equal)
//input    : <thecirc>: the circle
//           <firstp1>: first extremity of the 1st curve of the constraint
//           <lastp1> : last extremity of the 1st curve of the constraint
//           <firstp2>: first extremity of the 2nd curve of the constraint
//           <lastp2> :last extremity of the 2nd curve of the constraint
//=======================================================================
void AIS_IdenticRelation::ComputeTwoCirclesPresentation(const Handle(Prs3d_Presentation)& aPrs,
                                          const Handle(Geom_Circle)& thecirc,
                                          const gp_Pnt& firstp1,
                                          const gp_Pnt& lastp1,
                                          const gp_Pnt& firstp2,
                                          const gp_Pnt& lastp2)
{
  Standard_Real confusion (Precision::Confusion());

  // Searching of complete circles
  Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
  Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
    
  myCenter = thecirc->Location();
  Standard_Real aSegSize = thecirc->Radius()/5.0;
  Standard_Real rad = Standard_PI/5.0;
    
  // I. Case of 2 complete circles
  if ( circ1complete && circ2complete )
    {
      if (myAutomaticPosition)
      {
        Standard_Real pfirst1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
        myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), thecirc->Circ());
        mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), thecirc->Circ());

        gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
        gp_Vec vtrans(myCenter, curpos);
        vtrans.Normalize();
        vtrans *= aSegSize;
        curpos.Translate(vtrans);
        myPosition = curpos;
      }
      else ComputeNotAutoCircPresentation(thecirc);
    }

  // II. Case of one complete circle and one arc
  else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
    {
      gp_Pnt firstp, lastp;
      if ( circ1complete && !circ2complete)
      {
        firstp = firstp2;
        lastp  = lastp2;
      }
      else
      {
        firstp = firstp1;
        lastp  = lastp1;
      }

      if (myAutomaticPosition)
      {
        ComputeAutoArcPresentation(thecirc, firstp, lastp);
      }
      else
      {
        ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
      }
    }

  // III and IV. Case of two arcs
  else if ( !circ1complete && !circ2complete )
    {
      // We project all the points on the circle
      Standard_Real pf1, pf2, pl1, pl2;
      pf1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
      pf2 = ElCLib::Parameter(thecirc->Circ(), firstp2);
      pl1 = ElCLib::Parameter(thecirc->Circ(), lastp1);
      pl2 = ElCLib::Parameter(thecirc->Circ(), lastp2);

      // III. Arcs with common ends
      // III.1. First of one and last of another
      if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
      {
        gp_Pnt curpos(0.,0.,0.);
        Standard_Real att=0.;
        if ( IsEqual2PI(pl1,pf2,confusion) )
          {
            att = pl1;
            curpos = lastp1;
          }
        else if ( IsEqual2PI(pf1,pl2,confusion) )
          {
            att = pf1;
            curpos = firstp1;
          }
        Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
        if ( rad > maxrad ) rad = maxrad;
        Standard_Real pFAttach = Modulo2PI(att - rad);
        Standard_Real pSAttach = Modulo2PI(att + rad);
        myFAttach = ElCLib::Value(pFAttach, thecirc->Circ());
        mySAttach = ElCLib::Value(pSAttach, thecirc->Circ());
        if ( myAutomaticPosition )
          {
            gp_Vec vtrans(myCenter,curpos);
            vtrans.Normalize();
            vtrans *= aSegSize;
            curpos.Translate(vtrans);
            myPosition = curpos;
          }
      }
      // III.2. Two first or two last
      else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
      {
        Standard_Real l1 = Modulo2PI(pl1 - pf1);
        Standard_Real l2 = Modulo2PI(pl2 - pf2);
        gp_Pnt firstp,lastp;
        if ( l1 < l2 )
          {
            firstp = firstp1;
            lastp = lastp1;
          }
        else
          {
            firstp = firstp2;
            lastp = lastp2;
          }

        if ( myAutomaticPosition )
          {
            ComputeAutoArcPresentation(thecirc, firstp, lastp);
          }
        else
          {
            ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
          }
      }
      // IV. All others arcs (without common ends)
      else
      {
        // order the parameters; first will be pf1
        Standard_Real pl1m = Modulo2PI(pl1 - pf1);
        Standard_Real pf2m = Modulo2PI(pf2 - pf1);
        Standard_Real pl2m = Modulo2PI(pl2 - pf1);

        Standard_Boolean case1 = Standard_False;
        // 1 - not intersecting arcs
        // 2 - intersecting arcs, but one doesn't contain another
        // 3a - first arc contains the second one
        // 3b - second arc contains the first one
        // 4 - two intersections

        gp_Pnt firstp, lastp;

        if ( pl1m < pf2m ) // 1 or 2b or 3b
          {
            if ( pl1m < pl2m ) // 1 or 3b
            {
              if ( pl2m < pf2m ) // 3b
                {
                  firstp = firstp1;
                  lastp  = lastp1;
                }
              else // 1
                {
                  case1 = Standard_True;
                  Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
                  Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
                  if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
                     ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
                  {
                    firstp = lastp1;
                    lastp  = firstp2;
                  }
                  else // deltap1
                  {
                    firstp = lastp2;
                    lastp  = firstp1;
                  }
                }
            }
            else // 2b
            {
              firstp = firstp1;
              lastp  = lastp2;
            }
          }
        else // 2a or 3a or 4
          {
            if ( pl1m < pl2m ) // 2a
            {
              firstp = firstp2;
              lastp  = lastp1;
            }
            else // 3a or 4
            {
              if ( pl2m > pf2m ) // 3a
                {
                  firstp = firstp2;
                  lastp  = lastp2;
                }
              else // 4
                {
                  Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
                  Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
                  if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
                     ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
                  {
                    firstp = firstp1;
                    lastp  = lastp2;
                  }
                  else // deltap1
                  {
                    firstp = firstp2;
                    lastp  = lastp1;
                  }
                }
            }
          }

        if ( myAutomaticPosition )
          {
            ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
          }
        else
          {
            if ( case1 )
            {
              myFAttach = firstp;
              mySAttach = lastp;
            }
            else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
          }
      }
    }

  // Display of the presentation
  TCollection_ExtendedString vals(" ==");
  gp_Pnt attach = myPosition;
  ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
  DsgPrs_IdenticPresentation::Add(aPrs,
                          myDrawer,
                          vals,
                          myPlane->Pln().Position().Ax2(),
                          myCenter,
                          myFAttach,
                          mySAttach,
                          myPosition,
                          attach);
}

//=======================================================================
//function : ComputeAutoArcPresentation
//purpose  : Compute the presentation of the constraint where we are
//           not in the case of dragging.
//=======================================================================
00981 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
                                         const gp_Pnt& firstp,
                                         const gp_Pnt& lastp,
                                         const Standard_Boolean isstatic)
{
  Standard_Real aSegSize = thecirc->Radius()/5.0;
  Standard_Real rad = Standard_PI/5.0;

  Standard_Real pFA = ElCLib::Parameter(thecirc->Circ(),firstp);
  Standard_Real pSA = ElCLib::Parameter(thecirc->Circ(),lastp);
  Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
  
  if ( (rad > maxrad) || isstatic ) rad = maxrad;
  Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
  
  myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
  mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
  
  gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
  gp_Vec vtrans(myCenter, curpos);
  vtrans.Normalize();
  vtrans *= aSegSize;
  myPosition = curpos.Translated(vtrans);
}

//=======================================================================
//function : ComputeNotAutoCircPresentation
//purpose  : Compute the presentation of the constraint where we are
//           in the case of dragging.
// Note    : This function is to be used only in the case of full circles.
//           The symbol of the constraint moves together with arc
//           representing the constraint around all the circle.
//=======================================================================
01014 void AIS_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
{
  gp_Pnt curpos = myPosition;

  Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
  
  // Case of confusion between the current position and the center 
  // of the circle -> we move the current position
  Standard_Real confusion (Precision::Confusion());
  if ( myCenter.Distance(curpos) <= confusion )
    {
      gp_Vec vprec(myCenter, myFAttach);
      vprec.Normalize();
      curpos.Translate(vprec*1e-5);
    }
  
  Standard_Real rad = Standard_PI/5.0;
  Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto->Circ(),curpos);
  Standard_Real pFAttach = pcurpos - rad;
  Standard_Real pSAttach = pcurpos + rad;
  myFAttach = ElCLib::Value(pFAttach,cirNotAuto->Circ());
  mySAttach = ElCLib::Value(pSAttach,cirNotAuto->Circ());
}

//=======================================================================
//function : ComputeNotAutoArcPresentation
//purpose  : Compute the presentation of the constraint where we are
//           in the case of dragging.
// Note    : This function is to be used only in the case of circles.
//           The symbol of the constraint moves only between myFAttach
//           and mySAttach.
//=======================================================================
01046 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
                                          const gp_Pnt& pntfirst,
                                          const gp_Pnt& pntlast)
{
  gp_Pnt curpos = myPosition;

  gp_Circ cirNotAuto = thecirc->Circ();

  Standard_Real pFPnt = ElCLib::Parameter(cirNotAuto, pntfirst);
  Standard_Real pSPnt = ElCLib::Parameter(cirNotAuto, pntlast);
  Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;

  Standard_Real rad = Standard_PI/5;
  if ( deltap < rad )
    {
      myFAttach = pntfirst;
      mySAttach = pntlast;
    }
  else
    {
      gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
      gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);

      ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);

      Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
      myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
      mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
    }
}
// jfa 17/10/2000 end

// jfa 18/10/2000
//=======================================================================
//function : ComputeTwoEllipsesPresentation
//purpose  : Compute the presentation of the 'identic' constraint
//           between two ellipses (which are equal)
//input    : <theEll>: the ellipse
//           <firstp1>: first extremity of the 1st curve of the constraint
//           <lastp1> : last extremity of the 1st curve of the constraint
//           <firstp2>: first extremity of the 2nd curve of the constraint
//           <lastp2> :last extremity of the 2nd curve of the constraint
//=======================================================================
void AIS_IdenticRelation::ComputeTwoEllipsesPresentation(const Handle(Prs3d_Presentation)& aPrs,
                                           const Handle(Geom_Ellipse)& theEll,
                                           const gp_Pnt& firstp1,
                                           const gp_Pnt& lastp1,
                                           const gp_Pnt& firstp2,
                                           const gp_Pnt& lastp2)
{
  Standard_Real confusion (Precision::Confusion());

  // Searching of complete ellipses
  Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
  Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
    
  myCenter = theEll->Location();
  Standard_Real aSegSize = theEll->MajorRadius()/5.0;
  Standard_Real rad = Standard_PI/5.0;
    
  // I. Case of 2 complete ellipses
  if ( circ1complete && circ2complete )
    {
      if (myAutomaticPosition)
      {
        Standard_Real pfirst1 = ElCLib::Parameter(theEll->Elips(), firstp1);
        myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), theEll->Elips());
        mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), theEll->Elips());

        gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
        gp_Vec vtrans(myCenter, curpos);
        vtrans.Normalize();
        vtrans *= aSegSize;
        curpos.Translate(vtrans);
        myPosition = curpos;
      }
      else ComputeNotAutoElipsPresentation(theEll);
    }

  // II. Case of one complete circle and one arc
  else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
    {
      gp_Pnt firstp, lastp;
      if ( circ1complete && !circ2complete)
      {
        firstp = firstp2;
        lastp  = lastp2;
      }
      else
      {
        firstp = firstp1;
        lastp  = lastp1;
      }

      if (myAutomaticPosition)
      {
        ComputeAutoArcPresentation(theEll, firstp, lastp);
      }
      else
      {
        ComputeNotAutoArcPresentation(theEll, firstp, lastp);
      }
    }

  // III and IV. Case of two arcs
  else if ( !circ1complete && !circ2complete )
    {
      // We project all the points on the circle
      Standard_Real pf1, pf2, pl1, pl2;
      pf1 = ElCLib::Parameter(theEll->Elips(), firstp1);
      pf2 = ElCLib::Parameter(theEll->Elips(), firstp2);
      pl1 = ElCLib::Parameter(theEll->Elips(), lastp1);
      pl2 = ElCLib::Parameter(theEll->Elips(), lastp2);

      // III. Arcs with common ends
      // III.1. First of one and last of another
      if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
      {
        gp_Pnt curpos;
        Standard_Real att=0.;
        if ( IsEqual2PI(pl1,pf2,confusion) )
          {
            att = pl1;
            curpos = lastp1;
          }
        else if ( IsEqual2PI(pf1,pl2,confusion) )
          {
            att = pf1;
            curpos = firstp1;
          }
        Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
        if ( rad > maxrad ) rad = maxrad;
        Standard_Real pFAttach = Modulo2PI(att - rad);
        Standard_Real pSAttach = Modulo2PI(att + rad);
        myFAttach = ElCLib::Value(pFAttach, theEll->Elips());
        mySAttach = ElCLib::Value(pSAttach, theEll->Elips());
        if ( myAutomaticPosition )
          {
            gp_Vec vtrans(myCenter,curpos);
            vtrans.Normalize();
            vtrans *= aSegSize;
            curpos.Translate(vtrans);
            myPosition = curpos;
          }
      }
      // III.2. Two first or two last
      else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
      {
        Standard_Real l1 = Modulo2PI(pl1 - pf1);
        Standard_Real l2 = Modulo2PI(pl2 - pf2);
        gp_Pnt firstp,lastp;
        if ( l1 < l2 )
          {
            firstp = firstp1;
            lastp = lastp1;
          }
        else
          {
            firstp = firstp2;
            lastp = lastp2;
          }

        if ( myAutomaticPosition )
          {
            ComputeAutoArcPresentation(theEll, firstp, lastp);
          }
        else
          {
            ComputeNotAutoArcPresentation(theEll, firstp, lastp);
          }
      }
      // IV. All others arcs (without common ends)
      else
      {
        // order the parameters; first will be pf1
        Standard_Real pl1m = Modulo2PI(pl1 - pf1);
        Standard_Real pf2m = Modulo2PI(pf2 - pf1);
        Standard_Real pl2m = Modulo2PI(pl2 - pf1);

        Standard_Boolean case1 = Standard_False;
        // 1 - not intersecting arcs
        // 2 - intersecting arcs, but one doesn't contain another
        // 3a - first arc contains the second one
        // 3b - second arc contains the first one
        // 4 - two intersections

        gp_Pnt firstp, lastp;

        if ( pl1m < pf2m ) // 1 or 2b or 3b
          {
            if ( pl1m < pl2m ) // 1 or 3b
            {
              if ( pl2m < pf2m ) // 3b
                {
                  firstp = firstp1;
                  lastp  = lastp1;
                }
              else // 1
                {
                  case1 = Standard_True;
                  Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
                  Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
                  if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
                     ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
                  {
                    firstp = lastp1;
                    lastp  = firstp2;
                  }
                  else // deltap1
                  {
                    firstp = lastp2;
                    lastp  = firstp1;
                  }
                }
            }
            else // 2b
            {
              firstp = firstp1;
              lastp  = lastp2;
            }
          }
        else // 2a or 3a or 4
          {
            if ( pl1m < pl2m ) // 2a
            {
              firstp = firstp2;
              lastp  = lastp1;
            }
            else // 3a or 4
            {
              if ( pl2m > pf2m ) // 3a
                {
                  firstp = firstp2;
                  lastp  = lastp2;
                }
              else // 4
                {
                  Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
                  Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
                  if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
                     ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
                  {
                    firstp = firstp1;
                    lastp  = lastp2;
                  }
                  else // deltap1
                  {
                    firstp = firstp2;
                    lastp  = lastp1;
                  }
                }
            }
          }

        if ( myAutomaticPosition )
          {
            ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
          }
        else
          {
            if ( case1 )
            {
              myFAttach = firstp;
              mySAttach = lastp;
            }
            else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
          }
      }
    }

  // Display of the presentation
  TCollection_ExtendedString vals(" ==");
  gp_Pnt attach = myPosition;
  ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
  DsgPrs_IdenticPresentation::Add(aPrs,
                          myDrawer,
                          vals,
                          theEll->Elips(),
                          myFAttach,
                          mySAttach,
                          myPosition,
                          attach);
}

//=======================================================================
//function : ComputeAutoArcPresentation
//purpose  : Compute the presentation of the constraint where we are
//           not in the case of dragging.
//=======================================================================
01335 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
                                         const gp_Pnt& firstp,
                                         const gp_Pnt& lastp,
                                         const Standard_Boolean isstatic)
{
  Standard_Real aSegSize = theEll->MajorRadius()/5.0;
  Standard_Real rad = Standard_PI/5.0;

  gp_Elips anEll = theEll->Elips();
  
  Standard_Real pFA = ElCLib::Parameter(anEll,firstp);
  Standard_Real pSA = ElCLib::Parameter(anEll,lastp);
  Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
  
  if ( (rad > maxrad) || isstatic ) rad = maxrad;
  Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
  
  myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
  mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
  
  gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
  gp_Vec vtrans(myCenter, curpos);
  vtrans.Normalize();
  vtrans *= aSegSize;
  myPosition = curpos.Translated(vtrans);
}

//=======================================================================
//function : ComputeNotAutoElipsPresentation
//purpose  : Compute the presentation of the constraint where we are
//           in the case of dragging.
// Note    : This function is to be used only in the case of ellipses.
//           The symbol of the constraint moves only between myFAttach
//           and mySAttach.
//=======================================================================
01370 void AIS_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
{
  gp_Pnt curpos = myPosition;

  gp_Elips anEll = theEll->Elips();
  
  // Case of confusion between the current position and the center 
  // of the ellipse -> we move the current position
  Standard_Real confusion (Precision::Confusion());
  if ( myCenter.Distance(curpos) <= confusion )
    {
      gp_Vec vprec(myCenter, myFAttach);
      vprec.Normalize();
      curpos.Translate(vprec*1e-5);
    }
  
  Standard_Real rad = Standard_PI/5.0;
//  Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
  GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
  Standard_Real pcurpos  = aProj.LowerDistanceParameter();

  Standard_Real pFAttach = pcurpos - rad;
  Standard_Real pSAttach = pcurpos + rad;
  myFAttach = ElCLib::Value(pFAttach,anEll);
  mySAttach = ElCLib::Value(pSAttach,anEll);
}

//=======================================================================
//function : ComputeNotAutoArcPresentation
//purpose  : Compute the presentation of the constraint where we are
//           in the case of dragging.
// Note    : This function is to be used only in the case of ellipses.
//           The symbol of the constraint moves only between myFAttach
//           and mySAttach.
//=======================================================================
01405 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
                                          const gp_Pnt& pntfirst,
                                          const gp_Pnt& pntlast)
{
  gp_Pnt curpos = myPosition;

  gp_Elips anEll = theEll->Elips();

  Standard_Real pFPnt = ElCLib::Parameter(anEll, pntfirst);
  Standard_Real pSPnt = ElCLib::Parameter(anEll, pntlast);
  Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;

  Standard_Real rad = Standard_PI/5;
  if ( deltap < rad )
    {
      myFAttach = pntfirst;
      mySAttach = pntlast;
    }
  else
    {
      gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
      gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);

      ComputeAttach(anEll,aFPnt,aSPnt,curpos);

//      Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
      GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
      Standard_Real pcurpos  = aProj.LowerDistanceParameter();

      myFAttach = ElCLib::Value(pcurpos - rad, anEll);
      mySAttach = ElCLib::Value(pcurpos + rad, anEll);
    }
}
// jfa 18/10/2000 end

//=======================================================================
//function : ComputeTwoVerticesPresentation
//purpose  : 
//=======================================================================
void AIS_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
{
  Standard_Boolean isOnPlane1, isOnPlane2;
  const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
  const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
  
  AIS::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
  AIS::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
  
  if (isOnPlane1 && isOnPlane2)
    myExtShape = 0;
  else if ( isOnPlane1 && !isOnPlane2)
    myExtShape = 2;
  else if (!isOnPlane1 && isOnPlane2)
    myExtShape = 1;
  else
    return ;

  
  // The attachement points are the points themselves that must be 
  //identical
  myFAttach = BRep_Tool::Pnt(FVertex);
  mySAttach = myFAttach;

  gp_Pnt curpos;
  if (myAutomaticPosition)
    {
      //Computation of the size of the symbol
      Standard_Real symbsize = ComputeSegSize();
      if (symbsize <= Precision::Confusion()) symbsize = 1.;
      symbsize*=5;
      // Computation of the direction of the segment of the presentation 
      // we take the median of the edges connected to vertices
      gp_Dir dF, dS;
      gp_Dir myDir;
      TColStd_ListIteratorOfListOfTransient it(Users());
      if (it.More())
      {
        const Handle(AIS_Shape)& USER = Handle(AIS_Shape)::DownCast(it.Value());
        if (!USER.IsNull())
          {
            const TopoDS_Shape& SH =USER->Shape();
            if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
            {
              const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
              Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
              if (!done) return;
              done =  ComputeDirection(WIRE,SVertex,dS);
              if (!done) return;
            }
            else return;
          }
        else return;

        // computation of the segment direction like average 
        // of the 2 computed directions.
        if ( dF.IsParallel(dS, Precision::Angular()) )
          {
            myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
          }
        else
          {
            myDir.SetXYZ(dF.XYZ() + dS.XYZ());
          }
        curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
      }
// jfa 11/10/2000
      else
      {
        curpos = myFAttach;
      }
// jfa 11/10/2000 end

      myPosition = curpos;
      myAutomaticPosition = Standard_False;
    }
  else
    {
      curpos = myPosition;
    }

  // Presentation computation
  TCollection_ExtendedString vals(" ++");
  DsgPrs_IdenticPresentation::Add(aPrs,
                          myDrawer,
                          vals,
                          myFAttach,
                          curpos);
  // Calcul de la projection du vertex
  if ( myExtShape == 1)
    ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
  else if ( myExtShape == 2)
    ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
}



//=======================================================================
//function : ComputeSegSize
//purpose  : 
//=======================================================================
Standard_Real AIS_IdenticRelation::ComputeSegSize() const 
{
  return 1.;
}

//=======================================================================
//function : ComputeDirection
//purpose  : Compute a direction according to the different geometric
//           elements connected to the vertex <VERT>, in way to not have
//            overlap between the symbol and them.
//=======================================================================
Standard_Boolean AIS_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire, 
                                           const TopoDS_Vertex& VERT, 
                                           gp_Dir& dF) const 
{
   // we take the median of the edges connected to vertices
  TopoDS_Edge edg1,edg2;
  ConnectedEdges(aWire,VERT,edg1,edg2);

  if ( edg1.IsNull() && edg2.IsNull() ) {
    return Standard_False;
  }
  
  Handle(Geom_Curve) curv1,curv2;
  gp_Pnt firstp1,lastp1,firstp2,lastp2;

  // Case with 2 edges connected to the vertex <VERT>
  if ( !edg1.IsNull() && !edg2.IsNull() ) {
    if ( !AIS::ComputeGeometry(edg1,edg2,
                         curv1,curv2,
                         firstp1, lastp1,
                         firstp2, lastp2,myPlane))
      return Standard_False;

    gp_Dir d1, d2;
    if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
      d1 = ComputeCircleDirection((Handle(Geom_Circle)&) curv1, VERT);
    }
    else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
      d1 = ComputeLineDirection((Handle(Geom_Line)&) curv1, firstp1);
    }
    else 
      return Standard_False;
    
    if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
      d2 = ComputeCircleDirection( (Handle(Geom_Circle)&) curv2, VERT);
    }
    else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
      d2 =ComputeLineDirection( (Handle(Geom_Line)&) curv2, firstp2);
    }
    else 
      return Standard_False;
    
    if ( !d1.IsParallel(d2, Precision::Angular() ))
      dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
    else {
      dF= d1.Crossed(myPlane->Pln().Axis().Direction());
    }
  }

  // Case where <VERT> is at an extremity of a wire.
  else {
    TopoDS_Edge VEdge;
    if ( !edg1.IsNull() )  
      VEdge = edg1;
    else if (!edg2.IsNull() )
       VEdge = edg2;
    else 
      return Standard_False;

    if ( !AIS::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
      return Standard_False; 
    if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
      dF = ComputeCircleDirection( (Handle(Geom_Circle)&) curv1, VERT);
    }
    else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
      dF = ComputeLineDirection( (Handle(Geom_Line)&) curv1, firstp1);
    }
    else
      return Standard_False;
  }

  return Standard_True;
}

//=======================================================================
//function : ComputeLineDirection
//purpose  : 
//=======================================================================
gp_Dir AIS_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin, 
                                     const gp_Pnt& firstP) const 
{
  gp_Dir dir;
  dir = lin->Lin().Direction();
  if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
    dir.Reverse();
  return dir;
}

//=======================================================================
//function : ComputeCircleDirection
//purpose  : 
//=======================================================================
gp_Dir AIS_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ, 
                                       const TopoDS_Vertex& VERT) const 
{
  gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
  return gp_Dir(V);
}

//=======================================================================
//function : ComputeOneEdgeOVertexPresentation
//purpose  : 
//=======================================================================
void AIS_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
{
  TopoDS_Vertex V;
  TopoDS_Edge E;
  Standard_Integer numedge;
  
  if (myFShape.ShapeType() == TopAbs_VERTEX) {
    V = TopoDS::Vertex(myFShape);
    E = TopoDS::Edge(mySShape);
    numedge = 2;// edge = 2 iem shape
  }
  else {
    V = TopoDS::Vertex(mySShape);
    E   = TopoDS::Edge(myFShape);
    numedge = 1;  // edge = 1 ere shape
  }
  gp_Pnt ptonedge1,ptonedge2;
  Handle(Geom_Curve) aCurve;
  Handle(Geom_Curve) extCurv;
  Standard_Boolean isInfinite;
  Standard_Boolean isOnPlanEdge, isOnPlanVertex;
  if (!AIS::ComputeGeometry(E,aCurve,ptonedge1,ptonedge2,extCurv,isInfinite,isOnPlanEdge,myPlane))
    return;
  aPrs->SetInfiniteState(isInfinite);
  AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);

  // on considere que seule la courbe peut etre projetee 
  if (!isOnPlanEdge && !isOnPlanVertex) return;

  if (!isOnPlanEdge) {
    if (numedge == 1) myExtShape = 1;
    else myExtShape = 2;
  }
  else if (!isOnPlanVertex) {
    if (numedge == 1) myExtShape = 2;
    else myExtShape = 1;
  }
  // The attachement points are the point 
  myFAttach = BRep_Tool::Pnt(V);
  mySAttach = myFAttach;

  gp_Pnt curpos;
  if (myAutomaticPosition) {
    //Computation of the size of the symbol
    Standard_Real symbsize = ComputeSegSize();
    symbsize*=5;
    // Computation of the direction of the segment of the presentation 
    // we take the median of the edges connected to vertices
    gp_Dir myDir;
    if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
      myDir = ((Handle(Geom_Line)&) aCurve)->Lin().Direction();
      myDir.Cross(myPlane->Pln().Axis().Direction());
    }
    else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
      Handle(Geom_Circle) CIR = (Handle(Geom_Circle)&) aCurve;
      myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
    }
    // jfa 10/10/2000
    else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
      Handle(Geom_Ellipse) CIR = (Handle(Geom_Ellipse)&) aCurve;
      myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
    }
    // jfa 10/10/2000 end

    curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
    myPosition = curpos;
    myAutomaticPosition = Standard_True;
  }
  else {
    curpos = myPosition;
  }

  // Presentation computation
  TCollection_ExtendedString vals(" -+-");
  DsgPrs_IdenticPresentation::Add(aPrs,
                          myDrawer,
                          vals,
                          myFAttach,
                          curpos);
  if (myExtShape != 0) {
    if (!extCurv.IsNull()) { // c'est l'edge qui n'est pas dans le WP
     ComputeProjEdgePresentation(aPrs,E,(Handle(Geom_Line)&) aCurve,ptonedge1,ptonedge2);
    }
  }
}

Generated by  Doxygen 1.6.0   Back to index