// Created on: 2000-10-20
// Created by: Julia DOROVSKIKH
// Copyright (c) 2000-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <PrsDim_MidPointRelation.hxx>

#include <PrsDim.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <DsgPrs_MidPointPresentation.hxx>
#include <ElCLib.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Ax2.hxx>
#include <gp_Circ.hxx>
#include <gp_Dir.hxx>
#include <gp_Elips.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <Precision.hxx>
#include <Prs3d_Presentation.hxx>
#include <Select3D_SensitiveCurve.hxx>
#include <Select3D_SensitiveSegment.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_Selection.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>

IMPLEMENT_STANDARD_RTTIEXT(PrsDim_MidPointRelation, PrsDim_Relation)

//=================================================================================================

PrsDim_MidPointRelation::PrsDim_MidPointRelation(const TopoDS_Shape&       aMidPointTool,
                                                 const TopoDS_Shape&       FirstShape,
                                                 const TopoDS_Shape&       SecondShape,
                                                 const Handle(Geom_Plane)& aPlane)
    : PrsDim_Relation(),
      myTool(aMidPointTool)
{
  SetFirstShape(FirstShape);
  SetSecondShape(SecondShape);
  SetPlane(aPlane);
  myPosition = aPlane->Pln().Location();
}

//=================================================================================================

void PrsDim_MidPointRelation::Compute(const Handle(PrsMgr_PresentationManager)&,
                                      const Handle(Prs3d_Presentation)& aprs,
                                      const Standard_Integer)
{
  if (myTool.ShapeType() == TopAbs_VERTEX)
  {
    gp_Pnt           pp;
    Standard_Boolean isonplane;
    if (PrsDim::ComputeGeometry(TopoDS::Vertex(myTool), pp, myPlane, isonplane))
    {
      if (!isonplane)
        ComputeProjVertexPresentation(aprs, TopoDS::Vertex(myTool), pp);
    }
    myMidPoint = pp;
  }
  else
    return;

  if (myAutomaticPosition)
    myPosition = myMidPoint;

  switch (myFShape.ShapeType())
  {
    case TopAbs_FACE: {
      ComputeFaceFromPnt(aprs, Standard_True);
    }
    break;
    case TopAbs_EDGE: {
      ComputeEdgeFromPnt(aprs, Standard_True);
    }
    break;
    case TopAbs_VERTEX: {
      ComputeVertexFromPnt(aprs, Standard_True);
    }
    break;
    default:
      break;
  }

  switch (mySShape.ShapeType())
  {
    case TopAbs_FACE: {
      ComputeFaceFromPnt(aprs, Standard_False);
    }
    break;
    case TopAbs_EDGE: {
      ComputeEdgeFromPnt(aprs, Standard_False);
    }
    break;
    case TopAbs_VERTEX: {
      ComputeVertexFromPnt(aprs, Standard_False);
    }
    break;
    default:
      break;
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSel,
                                               const Standard_Integer)
{
  Handle(Select3D_SensitiveSegment) seg;
  Handle(SelectMgr_EntityOwner)     own = new SelectMgr_EntityOwner(this, 7);

  if (!myMidPoint.IsEqual(myFAttach, Precision::Confusion()))
  {
    // segment from mid point to the first geometry
    seg = new Select3D_SensitiveSegment(own, myFAttach, myMidPoint);
    aSel->Add(seg);
    // segment from mid point to the second geometry
    seg = new Select3D_SensitiveSegment(own, mySAttach, myMidPoint);
    aSel->Add(seg);
  }
  if (!myMidPoint.IsEqual(myPosition, Precision::Confusion()))
  {
    // segment from mid point to the text position
    seg = new Select3D_SensitiveSegment(own, myMidPoint, myPosition);
    aSel->Add(seg);
  }

  // center of the symmetry - circle around the MidPoint
  gp_Ax2 ax = myPlane->Pln().Position().Ax2();
  ax.SetLocation(myMidPoint);
  Standard_Real                   rad = myFAttach.Distance(myMidPoint) / 20.0;
  gp_Circ                         aCircleM(ax, rad);
  Handle(Geom_Curve)              thecir = new Geom_Circle(aCircleM);
  Handle(Select3D_SensitiveCurve) scurv  = new Select3D_SensitiveCurve(own, thecir);
  aSel->Add(scurv);

  Handle(Geom_Curve) curv;
  gp_Pnt             firstp, lastp;
  Standard_Boolean   isInfinite, isOnPlane;
  Handle(Geom_Curve) extCurv;

  // segment on first curve
  if (myFShape.ShapeType() == TopAbs_EDGE)
  {
    TopoDS_Edge E = TopoDS::Edge(myFShape);
    if (!PrsDim::ComputeGeometry(E, curv, firstp, lastp, extCurv, isInfinite, isOnPlane, myPlane))
      return;
    if (curv->IsInstance(STANDARD_TYPE(Geom_Line))) // case of line
    {
      // segment on line
      seg = new Select3D_SensitiveSegment(own, myFirstPnt1, myFirstPnt2);
      aSel->Add(seg);
    }
    else if (curv->IsInstance(STANDARD_TYPE(Geom_Circle))) // case of circle
    {
      // segment on circle
      Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast(curv);
      Standard_Real       udeb    = ElCLib::Parameter(thecirc->Circ(), myFirstPnt1);
      Standard_Real       ufin    = ElCLib::Parameter(thecirc->Circ(), myFirstPnt2);
      Handle(Geom_Curve)  thecu   = new Geom_TrimmedCurve(thecirc, udeb, ufin);

      scurv = new Select3D_SensitiveCurve(own, thecu);
      aSel->Add(scurv);
    }
    else if (curv->IsInstance(STANDARD_TYPE(Geom_Ellipse))) // case of ellipse
    {
      // segment on ellipse
      Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast(curv);
      Standard_Real        udeb   = ElCLib::Parameter(theEll->Elips(), myFirstPnt1);
      Standard_Real        ufin   = ElCLib::Parameter(theEll->Elips(), myFirstPnt2);
      Handle(Geom_Curve)   thecu  = new Geom_TrimmedCurve(theEll, udeb, ufin);

      scurv = new Select3D_SensitiveCurve(own, thecu);
      aSel->Add(scurv);
    }
  }

  // segment on second curve
  if (mySShape.ShapeType() == TopAbs_EDGE)
  {
    TopoDS_Edge E = TopoDS::Edge(mySShape);
    if (!PrsDim::ComputeGeometry(E, curv, firstp, lastp, extCurv, isInfinite, isOnPlane, myPlane))
      return;
    if (curv->IsInstance(STANDARD_TYPE(Geom_Line))) // case of line
    {
      // segment on line
      seg = new Select3D_SensitiveSegment(own, mySecondPnt1, mySecondPnt2);
      aSel->Add(seg);
    }
    else if (curv->IsInstance(STANDARD_TYPE(Geom_Circle))) // case of circle
    {
      // segment on circle
      Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast(curv);
      Standard_Real       udeb    = ElCLib::Parameter(thecirc->Circ(), mySecondPnt1);
      Standard_Real       ufin    = ElCLib::Parameter(thecirc->Circ(), mySecondPnt2);
      Handle(Geom_Curve)  thecu   = new Geom_TrimmedCurve(thecirc, udeb, ufin);

      scurv = new Select3D_SensitiveCurve(own, thecu);
      aSel->Add(scurv);
    }
    else if (curv->IsInstance(STANDARD_TYPE(Geom_Ellipse))) // case of ellipse
    {
      // segment on ellipse
      Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast(curv);
      Standard_Real        udeb   = ElCLib::Parameter(theEll->Elips(), mySecondPnt1);
      Standard_Real        ufin   = ElCLib::Parameter(theEll->Elips(), mySecondPnt2);
      Handle(Geom_Curve)   thecu  = new Geom_TrimmedCurve(theEll, udeb, ufin);

      scurv = new Select3D_SensitiveCurve(own, thecu);
      aSel->Add(scurv);
    }
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputeFaceFromPnt(const Handle(Prs3d_Presentation)&,
                                                 const Standard_Boolean /*first*/)
{
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputeEdgeFromPnt(const Handle(Prs3d_Presentation)& aprs,
                                                 const Standard_Boolean            first)
{
  TopoDS_Edge E;
  if (first)
    E = TopoDS::Edge(myFShape);
  else
    E = TopoDS::Edge(mySShape);

  Handle(Geom_Curve) geom;
  gp_Pnt             ptat1, ptat2;
  Handle(Geom_Curve) extCurv;
  Standard_Boolean   isInfinite, isOnPlane;
  if (!PrsDim::ComputeGeometry(E, geom, ptat1, ptat2, extCurv, isInfinite, isOnPlane, myPlane))
    return;

  gp_Ax2 ax = myPlane->Pln().Position().Ax2();

  if (geom->IsInstance(STANDARD_TYPE(Geom_Line)))
  {
    if (!isInfinite)
      ComputePointsOnLine(ptat1, ptat2, first);
    else
    {
      const gp_Lin& line = Handle(Geom_Line)::DownCast(geom)->Lin();
      ComputePointsOnLine(line, first);
    }
    if (first)
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       ax,
                                       myMidPoint,
                                       myPosition,
                                       myFAttach,
                                       myFirstPnt1,
                                       myFirstPnt2,
                                       first);
    else
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       ax,
                                       myMidPoint,
                                       myPosition,
                                       mySAttach,
                                       mySecondPnt1,
                                       mySecondPnt2,
                                       first);
  }
  else if (geom->IsInstance(STANDARD_TYPE(Geom_Circle)))
  {
    Handle(Geom_Circle) geom_cir(Handle(Geom_Circle)::DownCast(geom));
    gp_Circ             circ(geom_cir->Circ());
    ComputePointsOnCirc(circ, ptat1, ptat2, first);
    if (first)
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       circ,
                                       myMidPoint,
                                       myPosition,
                                       myFAttach,
                                       myFirstPnt1,
                                       myFirstPnt2,
                                       first);
    else
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       circ,
                                       myMidPoint,
                                       myPosition,
                                       mySAttach,
                                       mySecondPnt1,
                                       mySecondPnt2,
                                       first);
  }
  else if (geom->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
  {
    Handle(Geom_Ellipse) geom_ell(Handle(Geom_Ellipse)::DownCast(geom));
    gp_Elips             elips(geom_ell->Elips());
    ComputePointsOnElips(elips, ptat1, ptat2, first);
    if (first)
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       elips,
                                       myMidPoint,
                                       myPosition,
                                       myFAttach,
                                       myFirstPnt1,
                                       myFirstPnt2,
                                       first);
    else
      DsgPrs_MidPointPresentation::Add(aprs,
                                       myDrawer,
                                       elips,
                                       myMidPoint,
                                       myPosition,
                                       mySAttach,
                                       mySecondPnt1,
                                       mySecondPnt2,
                                       first);
  }
  else
    return;

  // projection on myPlane
  if (!isOnPlane)
    ComputeProjEdgePresentation(aprs, E, geom, ptat1, ptat2);
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputeVertexFromPnt(const Handle(Prs3d_Presentation)& aprs,
                                                   const Standard_Boolean            first)
{
  gp_Ax2 ax = myPlane->Pln().Position().Ax2();
  if (first)
  {
    Standard_Boolean isOnPlane;
    TopoDS_Vertex    V = TopoDS::Vertex(myFShape);
    PrsDim::ComputeGeometry(V, myFAttach, myPlane, isOnPlane);
    DsgPrs_MidPointPresentation::Add(aprs, myDrawer, ax, myMidPoint, myPosition, myFAttach, first);
    if (!isOnPlane)
      ComputeProjVertexPresentation(aprs, V, myFAttach);
  }
  else
  {
    Standard_Boolean isOnPlane;
    TopoDS_Vertex    V = TopoDS::Vertex(mySShape);
    PrsDim::ComputeGeometry(V, mySAttach, myPlane, isOnPlane);
    DsgPrs_MidPointPresentation::Add(aprs, myDrawer, ax, myMidPoint, myPosition, mySAttach, first);
    if (!isOnPlane)
      ComputeProjVertexPresentation(aprs, V, mySAttach);
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputePointsOnLine(const gp_Lin& aLin, const Standard_Boolean first)
{
  Standard_Real ppar     = ElCLib::Parameter(aLin, myMidPoint);
  gp_Pnt        anAttach = ElCLib::Value(ppar, aLin);

  Standard_Real dist = anAttach.Distance(myMidPoint) / 10.0;
  if (dist < Precision::Confusion())
    dist = 10.0;

  Standard_Real fpar = ppar + dist;
  Standard_Real spar = ppar - dist;

  gp_Pnt aPnt1 = ElCLib::Value(fpar, aLin);
  gp_Pnt aPnt2 = ElCLib::Value(spar, aLin);

  if (first)
  {
    myFAttach   = anAttach;
    myFirstPnt1 = aPnt1;
    myFirstPnt2 = aPnt2;
  }
  else
  {
    mySAttach    = anAttach;
    mySecondPnt1 = aPnt1;
    mySecondPnt2 = aPnt2;
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputePointsOnLine(const gp_Pnt&          pnt1,
                                                  const gp_Pnt&          pnt2,
                                                  const Standard_Boolean first)
{
  gp_Vec aVec(pnt1, pnt2);
  gp_Lin aLin(pnt1, gp_Dir(aVec));

  Standard_Real fpar = ElCLib::Parameter(aLin, pnt1);
  Standard_Real spar = ElCLib::Parameter(aLin, pnt2);
  Standard_Real ppar = ElCLib::Parameter(aLin, myMidPoint);

  gp_Pnt        aProjPnt = ElCLib::Value(ppar, aLin);
  Standard_Real dist     = myMidPoint.Distance(aProjPnt);
  Standard_Real ll       = pnt1.Distance(pnt2);
  Standard_Real segm     = Min(dist, ll) * 0.75;
  if (dist < Precision::Confusion())
    segm = ll * 0.75;

  gp_Pnt anAttach, aPnt1, aPnt2;
  anAttach = aProjPnt;
  gp_Vec aVecTr;
  if (ppar <= fpar)
  {
    aPnt2  = pnt1;
    aVecTr = gp_Vec(pnt2, pnt1);
    aVecTr.Normalize();
    aPnt1 = aProjPnt.Translated(aVecTr * segm);
  }
  else if (ppar >= spar)
  {
    aPnt1  = pnt2;
    aVecTr = gp_Vec(pnt1, pnt2);
    aVecTr.Normalize();
    aPnt2 = aProjPnt.Translated(aVecTr * segm);
  }
  else
  {
    Standard_Real dp1 = aProjPnt.Distance(pnt1);
    Standard_Real dp2 = aProjPnt.Distance(pnt2);

    segm   = Min(dist, dp1) * 0.75;
    aVecTr = gp_Vec(aProjPnt, pnt1);
    aVecTr.Normalize();
    aPnt1 = aProjPnt.Translated(aVecTr * segm);

    segm   = Min(dist, dp2) * 0.75;
    aVecTr = gp_Vec(aProjPnt, pnt2);
    aVecTr.Normalize();
    aPnt2 = aProjPnt.Translated(aVecTr * segm);
  }

  if (first)
  {
    myFAttach   = anAttach;
    myFirstPnt1 = aPnt1;
    myFirstPnt2 = aPnt2;
  }
  else
  {
    mySAttach    = anAttach;
    mySecondPnt1 = aPnt1;
    mySecondPnt2 = aPnt2;
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputePointsOnCirc(const gp_Circ&         aCirc,
                                                  const gp_Pnt&          pnt1,
                                                  const gp_Pnt&          pnt2,
                                                  const Standard_Boolean first)
{
  gp_Pnt curpos = myMidPoint;

  // Case of confusion between the current position and the center
  // of the circle -> we move the current position
  constexpr Standard_Real confusion(Precision::Confusion());
  gp_Pnt                  aCenter = aCirc.Location();
  if (aCenter.Distance(curpos) <= confusion)
  {
    gp_Vec vprec(aCenter, pnt1);
    vprec.Normalize();
    curpos.Translate(vprec * 1e-5);
  }

  Standard_Real pcurpos = ElCLib::Parameter(aCirc, curpos);

  Standard_Real rad = M_PI / 5.0;
  Standard_Real segm;

  Standard_Real pFPnt;
  Standard_Real pSPnt;

  if (pnt1.IsEqual(pnt2, confusion)) // full circle
  {
    pFPnt = pcurpos - rad;
    pSPnt = pcurpos + rad;
  }
  else
  {
    Standard_Real pFAttach = ElCLib::Parameter(aCirc, pnt1);
    Standard_Real pSAttach = ElCLib::Parameter(aCirc, pnt2);

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

    Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;

    Standard_Real pcurpos1 = pcurpos;
    // define where curpos lays
    if (pcurpos1 < pFAttach)
    {
      pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
      if (pcurpos1 > pSAttachM) // out
      {
        segm = Min(rad, deltap * 0.75);
        if (pcurpos1 > pmiddleout)
        {
          pcurpos = pFAttach;
          pFPnt   = pFAttach;
          pSPnt   = pFAttach + segm;
        }
        else
        {
          pcurpos = pSAttach;
          pFPnt   = pSAttach - segm;
          pSPnt   = pSAttach;
        }
      }
      else // on arc
      {
        Standard_Real dp1 = pcurpos1 - pFAttach;
        Standard_Real dp2 = pSAttachM - pcurpos1;

        segm  = Min(rad, dp1 * 0.75);
        pFPnt = pcurpos - segm;

        segm  = Min(rad, dp2 * 0.75);
        pSPnt = pcurpos + segm;
      }
    }
    else if (pcurpos1 > (pFAttach + deltap)) // out
    {
      pcurpos1 -= pFAttach;
      segm = Min(rad, deltap * 0.75);
      if (pcurpos1 > pmiddleout)
      {
        pcurpos = pFAttach;
        pFPnt   = pFAttach;
        pSPnt   = pFAttach + segm;
      }
      else
      {
        pcurpos = pSAttach;
        pFPnt   = pSAttach - segm;
        pSPnt   = pSAttach;
      }
    }
    else // on arc
    {
      Standard_Real dp1 = pcurpos1 - pFAttach;
      Standard_Real dp2 = pSAttach - pcurpos1;

      segm  = Min(rad, dp1 * 0.75);
      pFPnt = pcurpos - segm;

      segm  = Min(rad, dp2 * 0.75);
      pSPnt = pcurpos + segm;
    }
  }

  if (first)
  {
    myFAttach   = ElCLib::Value(pcurpos, aCirc);
    myFirstPnt1 = ElCLib::Value(pFPnt, aCirc);
    myFirstPnt2 = ElCLib::Value(pSPnt, aCirc);
  }
  else
  {
    mySAttach    = ElCLib::Value(pcurpos, aCirc);
    mySecondPnt1 = ElCLib::Value(pFPnt, aCirc);
    mySecondPnt2 = ElCLib::Value(pSPnt, aCirc);
  }
}

//=================================================================================================

void PrsDim_MidPointRelation::ComputePointsOnElips(const gp_Elips&        anEll,
                                                   const gp_Pnt&          pnt1,
                                                   const gp_Pnt&          pnt2,
                                                   const Standard_Boolean first)
{
  gp_Pnt curpos = myMidPoint;

  // Case of confusion between the current position and the center
  // of the circle -> we move the current position
  constexpr Standard_Real confusion(Precision::Confusion());
  gp_Pnt                  aCenter = anEll.Location();
  if (aCenter.Distance(curpos) <= confusion)
  {
    gp_Vec vprec(aCenter, pnt1);
    vprec.Normalize();
    curpos.Translate(vprec * 1e-5);
  }

  Standard_Real pcurpos = ElCLib::Parameter(anEll, curpos);

  Standard_Real rad = M_PI / 5.0;
  Standard_Real segm;

  Standard_Real pFPnt;
  Standard_Real pSPnt;

  if (pnt1.IsEqual(pnt2, confusion)) // full circle
  {
    pFPnt = pcurpos - rad;
    pSPnt = pcurpos + rad;
  }
  else
  {
    Standard_Real pFAttach = ElCLib::Parameter(anEll, pnt1);
    Standard_Real pSAttach = ElCLib::Parameter(anEll, pnt2);

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

    Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;

    Standard_Real pcurpos1 = pcurpos;
    // define where curpos lays
    if (pcurpos1 < pFAttach)
    {
      pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
      if (pcurpos1 > pSAttachM) // out
      {
        segm = Min(rad, deltap * 0.75);
        if (pcurpos1 > pmiddleout)
        {
          pcurpos = pFAttach;
          pFPnt   = pFAttach;
          pSPnt   = pFAttach + segm;
        }
        else
        {
          pcurpos = pSAttach;
          pFPnt   = pSAttach - segm;
          pSPnt   = pSAttach;
        }
      }
      else // on arc
      {
        Standard_Real dp1 = pcurpos1 - pFAttach;
        Standard_Real dp2 = pSAttachM - pcurpos1;

        segm  = Min(rad, dp1 * 0.75);
        pFPnt = pcurpos - segm;

        segm  = Min(rad, dp2 * 0.75);
        pSPnt = pcurpos + segm;
      }
    }
    else if (pcurpos1 > (pFAttach + deltap)) // out
    {
      pcurpos1 -= pFAttach;
      segm = Min(rad, deltap * 0.75);
      if (pcurpos1 > pmiddleout)
      {
        pcurpos = pFAttach;
        pFPnt   = pFAttach;
        pSPnt   = pFAttach + segm;
      }
      else
      {
        pcurpos = pSAttach;
        pFPnt   = pSAttach - segm;
        pSPnt   = pSAttach;
      }
    }
    else // on arc
    {
      Standard_Real dp1 = pcurpos1 - pFAttach;
      Standard_Real dp2 = pSAttach - pcurpos1;

      segm  = Min(rad, dp1 * 0.75);
      pFPnt = pcurpos - segm;

      segm  = Min(rad, dp2 * 0.75);
      pSPnt = pcurpos + segm;
    }
  }

  if (first)
  {
    myFAttach   = ElCLib::Value(pcurpos, anEll);
    myFirstPnt1 = ElCLib::Value(pFPnt, anEll);
    myFirstPnt2 = ElCLib::Value(pSPnt, anEll);
  }
  else
  {
    mySAttach    = ElCLib::Value(pcurpos, anEll);
    mySecondPnt1 = ElCLib::Value(pFPnt, anEll);
    mySecondPnt2 = ElCLib::Value(pSPnt, anEll);
  }
}
