Salome HOME
[bos #41409][FORUM] (2024) kindOfShape() bug for CONE2D
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_ShapeInfoFiller.cxx
index 08390a3d57c88bed043a32339bfa0c5afcbc7cc3..e5b61b2864b83fc78f5ad3fcfd2c87455efdb031 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include <gp_Cone.hxx>
 #include <gp_Torus.hxx>
 #include <gp_Pln.hxx>
+#include <gp_Hypr.hxx>
+#include <gp_Parab.hxx>
 
 #include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_BSplineCurve.hxx>
+#include <Geom_BezierCurve.hxx>
 
 #include <GeomAdaptor_Curve.hxx>
 #include <GeomAdaptor_Surface.hxx>
@@ -333,7 +336,7 @@ void GEOMAlgo_ShapeInfoFiller::FillFace(const TopoDS_Shape& aS)
     aP0=aPln.Location();
     aAx3=aPln.Position();
     //
-    aInfo.SetKindOfShape(GEOMAlgo_KS_PLANE); 
+    aInfo.SetKindOfShape(GEOMAlgo_KS_PLANE);
     aInfo.SetKindOfName(GEOMAlgo_KN_PLANE);
     aInfo.SetKindOfClosed(GEOMAlgo_KC_NOTCLOSED);
     aInfo.SetLocation(aP0);
@@ -417,38 +420,52 @@ void GEOMAlgo_ShapeInfoFiller::FillFace(const TopoDS_Shape& aS)
   //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
   // 4. Cone
   else if (aST==GeomAbs_Cone) {
-    Standard_Real aSemiAngle;
-    gp_Cone aCone;
-    //
-    aCone=aGAS.Cone();
-    aP0=aCone.Location();
-    aAx3=aCone.Position();
+    const gp_Cone aCone=aGAS.Cone();
     //
     aInfo.SetKindOfShape(GEOMAlgo_KS_CONE);
     aInfo.SetKindOfName(GEOMAlgo_KN_CONE);
-    aInfo.SetLocation(aP0);
-    aInfo.SetPosition(aAx3);
     //
     BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
+
     bInfU1=Precision::IsNegativeInfinite(aUMin);
     bInfU2=Precision::IsPositiveInfinite(aUMax);
     bInfV1=Precision::IsNegativeInfinite(aVMin);
     bInfV2=Precision::IsPositiveInfinite(aVMax);
     //
-    bInf=(bInfU1 || bInfU2 || bInfV1 || bInfV2);
+    bInf=bInfV1 || bInfV2;
     if (bInf) {
+      aP0=aAx3.Location();
+      aAx3=aCone.Position();
+      aInfo.SetLocation(aP0);
+      aInfo.SetPosition(aAx3);
       aInfo.SetKindOfBounds(GEOMAlgo_KB_INFINITE);
       return;
     }
     //
     aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
     //
-    aSemiAngle=fabs(aCone.SemiAngle());
-    dV=(aVMax-aVMin)*cos(aSemiAngle);
-    
-    aInfo.SetHeight(dV);
-    //
-    FillDetails(aF, aCone);
+    const Standard_Real aSemiAngle = aCone.SemiAngle();
+
+    dV = aVMax - aVMin;
+    Standard_Real H = dV * std::cos(aSemiAngle);
+
+    aAx3 = aCone.Position();
+    Standard_Real aShiftAlongAxisLength = aVMin * std::cos(aSemiAngle); // Required, because R1 does not equal to gp_Cone.RefRadius() in general case, and gp_Cone.Location() corresponds to the latter one.
+    auto aShiftAlongAxis = gp_Vec(aAx3.Direction().XYZ());
+    aShiftAlongAxis *= aShiftAlongAxisLength;
+    aAx3.Translate(aShiftAlongAxis);
+
+    aP0=aAx3.Location();
+    aInfo.SetLocation(aP0);
+    aInfo.SetPosition(aAx3);
+
+    aR1 = aCone.RefRadius() + aVMin * std::sin(aSemiAngle);
+    aR2 = aCone.RefRadius() + aVMax * std::sin(aSemiAngle);
+
+    aInfo.SetRadius1(aR1);
+    aInfo.SetRadius2(aR2);
+    aInfo.SetHeight(H);
+    aInfo.SetKindOfDef(GEOMAlgo_KD_SPECIFIED);
   }
   //
   //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@@ -525,45 +542,122 @@ void GEOMAlgo_ShapeInfoFiller::FillEdge(const TopoDS_Shape& aS)
   }
   // BSplineCurve
   if (aCT==GeomAbs_BSplineCurve) {
-    Standard_Integer aNbKnots, aNbPoles, aDegree;
+    Standard_Integer aNbKnots, aNbPoles, aNbWeights, aNbMultiplicities, aDegree, i;
     Standard_Real aLength;
     gp_XYZ aXYZ1, aXYZ2, aXYZc;
     Handle(Geom_BSplineCurve) aBSp;
     //
     aBSp=aGAC.BSpline();
-    aNbKnots=aBSp->NbKnots();
-    aNbPoles=aBSp->NbPoles();
-    aDegree =aBSp->Degree();
-    if (!(aDegree==1 && aNbKnots==2 && aNbPoles==2)) {
-      return; // unallowed B-Spline curve
+    aDegree = aBSp->Degree();
+    aNbPoles = aBSp->NbPoles();
+    aNbKnots = aBSp->NbKnots();
+    aNbWeights = (aBSp->IsRational() ? aNbPoles : 0);
+    aNbMultiplicities = (aBSp->KnotDistribution() == GeomAbs_Uniform ? 0 : aNbKnots);
+    if (aDegree==1 && aNbKnots==2 && aNbPoles==2) {
+      // This is a single line segment
+      aInfo.SetKindOfShape(GEOMAlgo_KS_BSPLINE);
+      aInfo.SetKindOfClosed(GEOMAlgo_KC_NOTCLOSED);
+      //
+      aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
+      aInfo.SetKindOfName(GEOMAlgo_KN_SEGMENT);
+      aGAC.D0(aT1, aP1);
+      aGAC.D0(aT2, aP2);
+      aInfo.SetPnt1(aP1);
+      aInfo.SetPnt2(aP2);
+      //
+      aLength=aP1.Distance(aP2);
+      aInfo.SetLength(aLength);
+      //
+      aXYZ1=aP1.XYZ();
+      aXYZ2=aP2.XYZ();
+      aXYZc=aXYZ1+aXYZ2;
+      aXYZc.Multiply(0.5);
+      aPc.SetXYZ(aXYZc);
+      aInfo.SetLocation(aPc);
+      //
+      if ( aLength >= gp::Resolution() ) {
+        gp_Vec aVec(aPc, aP2);
+        gp_Dir aDir(aVec);
+        aInfo.SetDirection(aDir);
+      }
     }
-    //
-    aInfo.SetKindOfShape(GEOMAlgo_KS_BSPLINE);
-    aInfo.SetKindOfClosed(GEOMAlgo_KC_NOTCLOSED);
-    //
+    else {
+      // We have a higher degree B-Spline curve
+      aInfo.SetKindOfShape(GEOMAlgo_KS_BSPLINE);
+      aInfo.SetKindOfName(GEOMAlgo_KN_CURVEBSPLINE);
+      aInfo.SetKindOfPeriod(aBSp->IsPeriodic() ? GEOMAlgo_KP_PERIODIC : GEOMAlgo_KP_NONPERIODIC);
+      aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
+      aInfo.SetKindOfClosed(aBSp->IsClosed() ? GEOMAlgo_KC_CLOSED : GEOMAlgo_KC_NOTCLOSED);
+      aGAC.D0(aT1, aP1);
+      aGAC.D0(aT2, aP2);
+      aInfo.SetPnt1(aP1);
+      aInfo.SetPnt2(aP2);
+      //
+      aInfo.SetDegree(aDegree);
+      aInfo.SetNbKnots(aNbKnots);
+      aInfo.SetNbPoles(aNbPoles);
+      aInfo.SetNbWeights(aNbWeights);
+      aInfo.SetNbMultiplicities(aNbMultiplicities);
+      // Fill the poles
+      Handle(TColgp_HArray1OfPnt) poles = new TColgp_HArray1OfPnt(1, aNbPoles);
+      for (i=1; i<=aNbPoles; i++)
+        poles->SetValue(i, aBSp->Pole(i));
+      aInfo.SetPoles(poles);
+      // Fill the knots
+      Handle(TColStd_HArray1OfReal) knots = new TColStd_HArray1OfReal(1, aNbKnots);
+      for (i=1; i<=aNbKnots; i++)
+        knots->SetValue(i, aBSp->Knot(i));
+      aInfo.SetKnots(knots);
+      // Fill the weights
+      if (aNbWeights > 0) {
+        Handle(TColStd_HArray1OfReal) weights = new TColStd_HArray1OfReal(1, aNbWeights);
+        for (i=1; i<=aNbWeights; i++)
+          weights->SetValue(i, aBSp->Weight(i));
+        aInfo.SetWeights(weights);
+      }
+      // Fill the multiplicities
+      if (aNbMultiplicities > 0) {
+        Handle(TColStd_HArray1OfInteger) mults = new TColStd_HArray1OfInteger(1, aNbMultiplicities);
+        for (i=1; i<=aNbMultiplicities; i++)
+          mults->SetValue(i, aBSp->Multiplicity(i));
+        aInfo.SetMultiplicities(mults);
+      }
+    }
+  }//if (aCT==GeomAbs_BSplineCurve) {
+  // Bezier
+  else if (aCT==GeomAbs_BezierCurve) {
+    Standard_Integer aNbPoles, aNbWeights, aDegree, i;
+    Handle(Geom_BezierCurve) aBC;
+    aBC=aGAC.Bezier();
+    aNbPoles = aBC->NbPoles();
+    aNbWeights = (aBC->IsRational() ? aNbPoles : 0);
+    aDegree = aBC->Degree();
+    aInfo.SetKindOfShape(GEOMAlgo_KS_BEZIER);
+    aInfo.SetKindOfName(GEOMAlgo_KN_CURVEBEZIER);
+    aInfo.SetKindOfPeriod(aBC->IsPeriodic() ? GEOMAlgo_KP_PERIODIC : GEOMAlgo_KP_NONPERIODIC);
     aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
-    aInfo.SetKindOfName(GEOMAlgo_KN_SEGMENT);
+    aInfo.SetKindOfClosed(aBC->IsClosed() ? GEOMAlgo_KC_CLOSED : GEOMAlgo_KC_NOTCLOSED);
     aGAC.D0(aT1, aP1);
     aGAC.D0(aT2, aP2);
     aInfo.SetPnt1(aP1);
     aInfo.SetPnt2(aP2);
     //
-    aLength=aP1.Distance(aP2);
-    aInfo.SetLength(aLength);
-    //
-    aXYZ1=aP1.XYZ();
-    aXYZ2=aP2.XYZ();
-    aXYZc=aXYZ1+aXYZ2;
-    aXYZc.Multiply(0.5);
-    aPc.SetXYZ(aXYZc);
-    aInfo.SetLocation(aPc);
-    //
-    if ( aLength >= gp::Resolution() ) {
-      gp_Vec aVec(aPc, aP2);
-      gp_Dir aDir(aVec);
-      aInfo.SetDirection(aDir);
+    aInfo.SetDegree(aDegree);
+    aInfo.SetNbPoles(aNbPoles);
+    aInfo.SetNbWeights(aNbWeights);
+    // Fill the poles
+    Handle(TColgp_HArray1OfPnt) poles = new TColgp_HArray1OfPnt(1, aNbPoles);
+    for (i=1; i<=aNbPoles; i++)
+      poles->SetValue(i, aBC->Pole(i));
+    aInfo.SetPoles(poles);
+    // Fill the weights
+    if (aNbWeights > 0) {
+      Handle(TColStd_HArray1OfReal) weights = new TColStd_HArray1OfReal(1, aNbWeights);
+      for (i=1; i<=aNbWeights; i++)
+        weights->SetValue(i, aBC->Weight(i));
+      aInfo.SetWeights(weights);
     }
-  }
+  }// if (aCT==GeomAbs_BezierCurve) {
   // Line
   else if (aCT==GeomAbs_Line) {
     Standard_Boolean bInf1, bInf2;
@@ -684,13 +778,50 @@ void GEOMAlgo_ShapeInfoFiller::FillEdge(const TopoDS_Shape& aS)
     else {
       aInfo.SetKindOfClosed(GEOMAlgo_KC_NOTCLOSED);
       aInfo.SetKindOfName(GEOMAlgo_KN_ARCELLIPSE);
-      //
-      gp_Vec aVecX(aP, aP1);
-      gp_Dir aDirX(aVecX);
-      gp_Ax2 aAx2new(aP, aAx2.Direction(), aDirX);
-      aInfo.SetPosition(aAx2new);
     }
   }// else if (aCT==GeomAbs_Ellipse) {
+  // Hyperbola
+  else if (aCT==GeomAbs_Hyperbola) {
+    gp_Hypr aHyp;
+    aHyp=aGAC.Hyperbola();
+    aP=aHyp.Location();
+    aAx2=aHyp.Position();
+    aR1=aHyp.MajorRadius();
+    aR2=aHyp.MinorRadius();
+    aInfo.SetKindOfShape(GEOMAlgo_KS_HYPERBOLA);
+    aInfo.SetKindOfName(GEOMAlgo_KN_HYPERBOLA);
+    aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
+    aInfo.SetLocation(aP);
+    aInfo.SetPosition(aAx2);
+    aInfo.SetRadius1(aR1);
+    aInfo.SetRadius2(aR2);
+    //
+    aGAC.D0(aT1, aP1);
+    aGAC.D0(aT2, aP2);
+    aInfo.SetPnt1(aP1);
+    aInfo.SetPnt2(aP2);
+    //
+  }// if (aCT==GeomAbs_Hyperbola) {
+  // Parabola
+  else if (aCT==GeomAbs_Parabola) {
+    gp_Parab aPara;
+    aPara=aGAC.Parabola();
+    aP=aPara.Location();
+    aAx2=aPara.Position();
+    aR1=aPara.Focal();
+    aInfo.SetKindOfShape(GEOMAlgo_KS_PARABOLA);
+    aInfo.SetKindOfName(GEOMAlgo_KN_PARABOLA);
+    aInfo.SetKindOfBounds(GEOMAlgo_KB_TRIMMED);
+    aInfo.SetLocation(aP);
+    aInfo.SetPosition(aAx2);
+    aInfo.SetRadius1(aR1);
+    //
+    aGAC.D0(aT1, aP1);
+    aGAC.D0(aT2, aP2);
+    aInfo.SetPnt1(aP1);
+    aInfo.SetPnt2(aP2);
+    //
+  }// if (aCT==GeomAbs_Parabola) {
   //
   FillSubShapes(aS);
 }
@@ -807,7 +938,10 @@ Standard_Boolean GEOMAlgo_ShapeInfoFiller::IsAllowedType
     GeomAbs_Line,
     GeomAbs_Circle,
     GeomAbs_Ellipse,
-    GeomAbs_BSplineCurve 
+    GeomAbs_BSplineCurve,
+    GeomAbs_BezierCurve,
+    GeomAbs_Hyperbola,
+    GeomAbs_Parabola
   };
   //
   bRet=Standard_False;