0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / BRepLib / BRepLib.cxx
index 1ff393d..d9934bf 100644 (file)
 #include <Approx_CurvilinearParameter.hxx>
 #include <Geom_BSplineSurface.hxx>
 
+#include <Poly_Triangulation.hxx>
+#include <TShort_HArray1OfShortReal.hxx>
+#include <GeomLProp_SLProps.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
 
 // TODO - not thread-safe static variables
 static Standard_Real thePrecision = Precision::Confusion();     
@@ -361,15 +365,9 @@ Standard_Boolean  BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
     Standard_Real First, Last;
 
     BRep_Builder B;
-    Standard_Boolean is_closed ;
-    is_closed = AnEdge.Closed() ;
-
     B.UpdateEdge(AnEdge,C3d,LocalLoc,0.0e0);
     BRep_Tool::Range(AnEdge, S, LC, First, Last);
     B.Range(AnEdge, First, Last); //Do not forget 3D range.(PRO6412)
-    TopoDS_Edge E = AnEdge ;
-    E.Closed(is_closed) ;
-
   }
   else {
     //
@@ -430,14 +428,10 @@ Standard_Boolean  BRepLib::BuildCurve3d(const TopoDS_Edge& AnEdge,
       max_deviation = Max( tolerance, Tolerance );
       if (NewCurvePtr.IsNull())
         return Standard_False;
-      Standard_Boolean is_closed ;
-      is_closed = AnEdge.Closed() ;
       B.UpdateEdge(TopoDS::Edge(AnEdge),
         NewCurvePtr,
         L[0],
         max_deviation) ;
-      TopoDS_Edge  E = AnEdge ;
-      E.Closed(is_closed) ;
       if (jj == 1 ) {
         //
         // if there is only one curve on surface attached to the edge
@@ -790,7 +784,13 @@ static void SetEdgeTol(const TopoDS_Edge& E,
     gp_Pnt Pc3d = HC->Value(u);
     gp_Pnt2d p2d = pc->Value(u);
     gp_Pnt Pcons = ElSLib::Value(p2d.X(),p2d.Y(),pln);
+    Standard_Real eps = Max(Pc3d.XYZ().SquareModulus(), Pcons.XYZ().SquareModulus());
+    eps = Epsilon(eps);
     Standard_Real temp = Pc3d.SquareDistance(Pcons);
+    if(temp <= eps)
+    {
+      temp = 0.;
+    }
     if(temp > d2) d2 = temp;
   }
   d2 = 1.5*sqrt(d2);
@@ -976,7 +976,7 @@ void BRepLib::SameParameter(const TopoDS_Edge&  AnEdge,
   Handle(Standard_Type) TheType = C3d->DynamicType();
   if( TheType == STANDARD_TYPE(Geom_TrimmedCurve))
   {
-    const Handle(Geom_Curve)& gtC = (*((Handle(Geom_TrimmedCurve)*)&C3d))->BasisCurve();
+    Handle(Geom_Curve) gtC (Handle(Geom_TrimmedCurve)::DownCast (C3d)->BasisCurve());
     m_TrimmedPeriodical = gtC->IsPeriodic();
   }
   // modified by NIZHNY-OCC486  Tue Aug 27 17:15:17 2002 .
@@ -1323,7 +1323,7 @@ void  BRepLib::UpdateTolerances(const TopoDS_Shape& aShape,
         aB.SetVoid();
         BRepBndLib::Add(curf,aB);
         if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
-          S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
+          S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
         }
         GeomAdaptor_Surface AS(S);
         switch (AS.GetType()) {
@@ -1661,6 +1661,146 @@ void BRepLib::EncodeRegularity(TopoDS_Edge& E,
   }
 }
 
+//=======================================================================
+// function : EnsureNormalConsistency
+// purpose  : Corrects the normals in Poly_Triangulation of faces.
+//              Returns TRUE if any correction is done.
+//=======================================================================
+Standard_Boolean BRepLib::
+            EnsureNormalConsistency(const TopoDS_Shape& theShape,
+                                    const Standard_Real theAngTol,
+                                    const Standard_Boolean theForceComputeNormals)
+{
+  const Standard_Real aThresDot = cos(theAngTol);
+
+  Standard_Boolean aRetVal = Standard_False, isNormalsFound = Standard_False;
+
+  // compute normals if they are absent
+  TopExp_Explorer anExpFace(theShape,TopAbs_FACE);
+  for (; anExpFace.More(); anExpFace.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(anExpFace.Current());
+    const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+    if(aSurf.IsNull())
+      continue;
+    TopLoc_Location aLoc;
+    const Handle(Poly_Triangulation)& aPT = BRep_Tool::Triangulation(aFace, aLoc);
+    if(aPT.IsNull())
+      continue;
+    if (!theForceComputeNormals && aPT->HasNormals())
+    {
+      isNormalsFound = Standard_True;
+      continue;
+    }
+
+    GeomLProp_SLProps aSLP(aSurf, 2, Precision::Confusion());
+    const Standard_Integer anArrDim = 3*aPT->NbNodes();
+    Handle(TShort_HArray1OfShortReal) aNormArr = new TShort_HArray1OfShortReal(1, anArrDim);
+    Standard_Integer anNormInd = aNormArr->Lower();
+    for(Standard_Integer i = aPT->UVNodes().Lower(); i <= aPT->UVNodes().Upper(); i++)
+    {
+      const gp_Pnt2d &aP2d = aPT->UVNodes().Value(i);
+      aSLP.SetParameters(aP2d.X(), aP2d.Y());
+
+      gp_XYZ aNorm(0.,0.,0.);
+      if(!aSLP.IsNormalDefined())
+      {
+#ifdef OCCT_DEBUG
+        cout << "BRepLib::EnsureNormalConsistency(): Cannot find normal!" << endl;
+#endif
+      }
+      else
+      {
+        aNorm = aSLP.Normal().XYZ();
+        if (aFace.Orientation() == TopAbs_REVERSED)
+          aNorm.Reverse();
+      }
+      aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.X());
+      aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Y());
+      aNormArr->ChangeValue(anNormInd++) = static_cast<Standard_ShortReal>(aNorm.Z());
+    }
+
+    aRetVal = Standard_True;
+    isNormalsFound = Standard_True;
+    aPT->SetNormals(aNormArr);
+  }
+
+  if(!isNormalsFound)
+  {
+    return aRetVal;
+  }
+
+  // loop by edges
+  TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+  TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,aMapEF);
+  for(Standard_Integer anInd = 1; anInd <= aMapEF.Extent(); anInd++)
+  {
+    const TopoDS_Edge& anEdg = TopoDS::Edge(aMapEF.FindKey(anInd));
+    const TopTools_ListOfShape& anEdgList = aMapEF.FindFromIndex(anInd);
+    if (anEdgList.Extent() != 2)
+      continue;
+    TopTools_ListIteratorOfListOfShape anItF(anEdgList);
+    const TopoDS_Face aFace1 = TopoDS::Face(anItF.Value());
+    anItF.Next();
+    const TopoDS_Face aFace2 = TopoDS::Face(anItF.Value());
+    TopLoc_Location aLoc1, aLoc2;
+    const Handle(Poly_Triangulation)& aPT1 = BRep_Tool::Triangulation(aFace1, aLoc1);
+    const Handle(Poly_Triangulation)& aPT2 = BRep_Tool::Triangulation(aFace2, aLoc2);
+
+    if(aPT1.IsNull() || aPT2.IsNull())
+      continue;
+
+    if(!aPT1->HasNormals() || !aPT2->HasNormals())
+      continue;
+
+    const Handle(Poly_PolygonOnTriangulation)& aPTEF1 = 
+                                BRep_Tool::PolygonOnTriangulation(anEdg, aPT1, aLoc1);
+    const Handle(Poly_PolygonOnTriangulation)& aPTEF2 = 
+                                BRep_Tool::PolygonOnTriangulation(anEdg, aPT2, aLoc2);
+
+    TShort_Array1OfShortReal& aNormArr1 = aPT1->ChangeNormals();
+    TShort_Array1OfShortReal& aNormArr2 = aPT2->ChangeNormals();
+
+    for(Standard_Integer anEdgNode = aPTEF1->Nodes().Lower();
+                         anEdgNode <= aPTEF1->Nodes().Upper(); anEdgNode++)
+    {
+      //Number of node
+      const Standard_Integer aFNodF1 = aPTEF1->Nodes().Value(anEdgNode);
+      const Standard_Integer aFNodF2 = aPTEF2->Nodes().Value(anEdgNode);
+
+      const Standard_Integer aFNorm1FirstIndex = aNormArr1.Lower() + 3*
+                                                    (aFNodF1 - aPT1->Nodes().Lower());
+      const Standard_Integer aFNorm2FirstIndex = aNormArr2.Lower() + 3*
+                                                    (aFNodF2 - aPT2->Nodes().Lower());
+
+      gp_XYZ aNorm1(aNormArr1.Value(aFNorm1FirstIndex),
+                    aNormArr1.Value(aFNorm1FirstIndex+1),
+                    aNormArr1.Value(aFNorm1FirstIndex+2));
+      gp_XYZ aNorm2(aNormArr2.Value(aFNorm2FirstIndex),
+                    aNormArr2.Value(aFNorm2FirstIndex+1),
+                    aNormArr2.Value(aFNorm2FirstIndex+2));
+      const Standard_Real aDot = aNorm1 * aNorm2;
+
+      if(aDot > aThresDot)
+      {
+        gp_XYZ aNewNorm = (aNorm1 + aNorm2).Normalized();
+        aNormArr1.ChangeValue(aFNorm1FirstIndex) =
+          aNormArr2.ChangeValue(aFNorm2FirstIndex) =
+          static_cast<Standard_ShortReal>(aNewNorm.X());
+        aNormArr1.ChangeValue(aFNorm1FirstIndex+1) =
+          aNormArr2.ChangeValue(aFNorm2FirstIndex+1) =
+          static_cast<Standard_ShortReal>(aNewNorm.Y());
+        aNormArr1.ChangeValue(aFNorm1FirstIndex+2) =
+          aNormArr2.ChangeValue(aFNorm2FirstIndex+2) =
+          static_cast<Standard_ShortReal>(aNewNorm.Z());
+        aRetVal = Standard_True;
+      }
+    }
+  }
+
+  return aRetVal;
+}
+
 //=======================================================================
 //function : SortFaces
 //purpose  : 
@@ -1680,7 +1820,7 @@ void  BRepLib::SortFaces (const TopoDS_Shape& Sh,
     S = BRep_Tool::Surface(F, l);
     if (!S.IsNull()) {
       if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
-        S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
+        S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
       }
       GeomAdaptor_Surface AS(S);
       switch (AS.GetType()) {
@@ -1738,7 +1878,7 @@ void  BRepLib::ReverseSortFaces (const TopoDS_Shape& Sh,
     S = BRep_Tool::Surface(F, l);
     if (!S.IsNull()) {
       if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
-        S = (*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface();
+        S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
       }
       GeomAdaptor_Surface AS(S);
       switch (AS.GetType()) {