0028788: Visualization, StdPrs_WFShape - Add option to compute Isolines using multipl...
authorkgv <kgv@opencascade.com>
Thu, 25 May 2017 14:36:10 +0000 (17:36 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 1 Jun 2017 07:18:34 +0000 (10:18 +0300)
StdPrs_WFShape::Add() now accepts new argument theIsParallel (FALSE by default)
for computing Isolines using multiple threads (if there is more then 1 Face).
StdPrs_Isolines::addOnTriangulation() - changed the iteration order (cosmetics).

src/Prs3d/Prs3d_ShapeTool.cxx
src/Prs3d/Prs3d_ShapeTool.hxx
src/StdPrs/StdPrs_Isolines.cxx
src/StdPrs/StdPrs_WFShape.cxx
src/StdPrs/StdPrs_WFShape.hxx

index edb8912..732f320 100644 (file)
@@ -142,11 +142,10 @@ Bnd_Box Prs3d_ShapeTool::FaceBound() const
 //purpose  : 
 //=======================================================================
 
-Standard_Boolean Prs3d_ShapeTool::IsPlanarFace() const 
+Standard_Boolean Prs3d_ShapeTool::IsPlanarFace (const TopoDS_Face& theFace)
 {
   TopLoc_Location l;
-  const TopoDS_Face& F = TopoDS::Face(myFaceExplorer.Current());
-  const Handle(Geom_Surface)& S = BRep_Tool::Surface(F, l);
+  const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace, l);
   if (S.IsNull())
   {
     return Standard_False;
index a8bae58..cd64f03 100644 (file)
 #ifndef _Prs3d_ShapeTool_HeaderFile
 #define _Prs3d_ShapeTool_HeaderFile
 
-#include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
-#include <Standard_Handle.hxx>
-
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
-#include <Standard_Integer.hxx>
-#include <Standard_Boolean.hxx>
 #include <TopTools_HSequenceOfShape.hxx>
-class TopoDS_Shape;
-class TopoDS_Face;
+
 class Bnd_Box;
 class TopoDS_Edge;
 class TopoDS_Vertex;
 class Poly_Triangulation;
-class TopLoc_Location;
 class Poly_PolygonOnTriangulation;
 class Poly_Polygon3D;
 
-
 //! describes the behaviour requested for a wireframe
 //! shape presentation.
 class Prs3d_ShapeTool 
 {
 public:
-
   DEFINE_STANDARD_ALLOC
 
-  
   //! Constructs the tool and initializes it using theShape and theAllVertices
   //! (optional) arguments. By default, only isolated and internal vertices are considered,
   //! however if theAllVertices argument is equal to True, all shape's vertices are taken into account.
@@ -62,9 +54,13 @@ public:
   Standard_EXPORT const TopoDS_Face& GetFace() const;
   
   Standard_EXPORT Bnd_Box FaceBound() const;
-  
-  Standard_EXPORT Standard_Boolean IsPlanarFace() const;
-  
+
+  Standard_Boolean IsPlanarFace() const
+  {
+    const TopoDS_Face& aFace = TopoDS::Face (myFaceExplorer.Current());
+    return IsPlanarFace (aFace);
+  }
+
   Standard_EXPORT void InitCurve();
   
   Standard_EXPORT Standard_Boolean MoreCurve() const;
@@ -97,19 +93,12 @@ public:
   
   Standard_EXPORT Handle(Poly_Polygon3D) Polygon3D (TopLoc_Location& l) const;
 
+public:
 
-
-
-protected:
-
-
-
-
+  Standard_EXPORT static Standard_Boolean IsPlanarFace (const TopoDS_Face& theFace);
 
 private:
 
-
-
   TopoDS_Shape myShape;
   TopExp_Explorer myFaceExplorer;
   TopTools_IndexedDataMapOfShapeListOfShape myEdgeMap;
@@ -117,13 +106,6 @@ private:
   Standard_Integer myEdge;
   Standard_Integer myVertex;
 
-
 };
 
-
-
-
-
-
-
 #endif // _Prs3d_ShapeTool_HeaderFile
index 15e7a4b..6df065a 100644 (file)
@@ -231,87 +231,67 @@ void StdPrs_Isolines::addOnTriangulation (const Handle(Poly_Triangulation)& theT
                                           Prs3d_NListOfSequenceOfPnt&       theUPolylines,
                                           Prs3d_NListOfSequenceOfPnt&       theVPolylines)
 {
-  const Standard_Integer aNbIsoU = theUIsoParams.Length();
-  const Standard_Integer aNbIsoV = theVIsoParams.Length();
-
-  SeqOfVecOfSegments aUPolylines, aVPolylines;
-
   const Poly_Array1OfTriangle& aTriangles = theTriangulation->Triangles();
   const TColgp_Array1OfPnt&    aNodes     = theTriangulation->Nodes();
   const TColgp_Array1OfPnt2d&  aUVNodes   = theTriangulation->UVNodes();
-
-  TColStd_Array1OfInteger aUIsoIndexes (1, aNbIsoU);
-  TColStd_Array1OfInteger aVIsoIndexes (1, aNbIsoV);
-  aUIsoIndexes.Init (-1);
-  aVIsoIndexes.Init (-1);
-
-  for (Standard_Integer anI = aTriangles.Lower(); anI <= aTriangles.Upper(); ++anI)
+  for (Standard_Integer anUVIter = 0; anUVIter < 2; ++anUVIter)
   {
-    Standard_Integer aNodeIdxs[3];
-    aTriangles.Value (anI).Get (aNodeIdxs[0], aNodeIdxs[1],aNodeIdxs[2]);
-    const gp_Pnt aNodesXYZ[3] = { aNodes.Value (aNodeIdxs[0]),
-                                  aNodes.Value (aNodeIdxs[1]),
-                                  aNodes.Value (aNodeIdxs[2]) };
-    const gp_Pnt2d aNodesUV[3] = { aUVNodes.Value (aNodeIdxs[0]),
-                                   aUVNodes.Value (aNodeIdxs[1]),
-                                   aUVNodes.Value (aNodeIdxs[2]) };
-
-    // Evaluate polyline points for u isolines.
-    for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsoU; ++anIsoIdx)
+    const Standard_Boolean        isUIso      = anUVIter == 0;
+    const TColStd_SequenceOfReal& anIsoParams = isUIso ? theUIsoParams : theVIsoParams;
+    const Standard_Integer aNbIsolines = anIsoParams.Length();
+    if (aNbIsolines == 0)
     {
-      SegOnIso aSegment;
-      const gp_Lin2d anIsolineUV = isoU (theUIsoParams.Value (anIsoIdx));
-
-      // Find intersections with triangle in uv space and its projection on triangulation.
-      if (!findSegmentOnTriangulation (theSurface, true, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
-      {
-        continue;
-      }
-
-      if (aUIsoIndexes.Value (anIsoIdx) == -1)
-      {
-        aUPolylines.Append (new VecOfSegments());
-        aUIsoIndexes.SetValue (anIsoIdx, aUPolylines.Size());
-      }
-
-      Handle(VecOfSegments) anIsoPnts = aUPolylines.ChangeValue (aUIsoIndexes.Value (anIsoIdx));
-      if (!theLocation.IsIdentity())
-      {
-        aSegment[0].Pnt.Transform (theLocation);
-        aSegment[1].Pnt.Transform (theLocation);
-      }
-      anIsoPnts->Append (aSegment);
+      continue;
     }
 
-    // Evaluate polyline points for v isolines.
-    for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsoV; ++anIsoIdx)
+    SeqOfVecOfSegments aPolylines;
+    TColStd_Array1OfInteger anIsoIndexes (1, aNbIsolines);
+    anIsoIndexes.Init (-1);
+    for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsolines; ++anIsoIdx)
     {
-      SegOnIso aSegment;
-      const gp_Lin2d anIsolineUV = isoV (theVIsoParams.Value (anIsoIdx));
-
-      if (!findSegmentOnTriangulation (theSurface, false, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
+      const gp_Lin2d anIsolineUV = isUIso ? isoU (anIsoParams.Value (anIsoIdx)) : isoV (anIsoParams.Value (anIsoIdx));
+      Handle(VecOfSegments) anIsoPnts;
+      if (anIsoIndexes.Value (anIsoIdx) != -1)
       {
-        continue;
+        anIsoPnts = aPolylines.ChangeValue (anIsoIndexes.Value (anIsoIdx));
       }
 
-      if (aVIsoIndexes.Value (anIsoIdx) == -1)
+      for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter)
       {
-        aVPolylines.Append (new VecOfSegments());
-        aVIsoIndexes.SetValue (anIsoIdx, aVPolylines.Size());
-      }
+        Standard_Integer aNodeIdxs[3];
+        aTriangles.Value (aTriIter).Get (aNodeIdxs[0], aNodeIdxs[1],aNodeIdxs[2]);
+        const gp_Pnt aNodesXYZ[3] = { aNodes.Value (aNodeIdxs[0]),
+                                      aNodes.Value (aNodeIdxs[1]),
+                                      aNodes.Value (aNodeIdxs[2]) };
+        const gp_Pnt2d aNodesUV[3] = { aUVNodes.Value (aNodeIdxs[0]),
+                                       aUVNodes.Value (aNodeIdxs[1]),
+                                       aUVNodes.Value (aNodeIdxs[2]) };
+
+        // Find intersections with triangle in uv space and its projection on triangulation.
+        SegOnIso aSegment;
+        if (!findSegmentOnTriangulation (theSurface, isUIso, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
+        {
+          continue;
+        }
 
-      Handle(VecOfSegments) anIsoPnts = aVPolylines.ChangeValue (aVIsoIndexes.Value (anIsoIdx));
-      if (!theLocation.IsIdentity())
-      {
-        aSegment[0].Pnt.Transform (theLocation);
-        aSegment[1].Pnt.Transform (theLocation);
+        if (anIsoPnts.IsNull())
+        {
+          aPolylines.Append (new VecOfSegments());
+          anIsoIndexes.SetValue (anIsoIdx, aPolylines.Size());
+          anIsoPnts = aPolylines.ChangeValue (anIsoIndexes.Value (anIsoIdx));
+        }
+
+        if (!theLocation.IsIdentity())
+        {
+          aSegment[0].Pnt.Transform (theLocation);
+          aSegment[1].Pnt.Transform (theLocation);
+        }
+        anIsoPnts->Append (aSegment);
       }
-      anIsoPnts->Append (aSegment);
     }
-  }
 
-  sortSegments (aUPolylines, theUPolylines);
-  sortSegments (aVPolylines, theVPolylines);
+    sortSegments (aPolylines, isUIso ? theUPolylines : theVPolylines);
+  }
 }
 
 //==================================================================
index f566250..418e0a3 100644 (file)
@@ -19,6 +19,7 @@
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepAdaptor_HSurface.hxx>
+#include <OSD_Parallel.hxx>
 #include <StdPrs_DeflectionCurve.hxx>
 #include <StdPrs_ToolTriangulatedShape.hxx>
 #include <StdPrs_Isolines.hxx>
 #include <TopoDS.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 
+//! Functor for executing StdPrs_Isolines in parallel threads.
+class StdPrs_WFShape_IsoFunctor
+{
+public:
+  StdPrs_WFShape_IsoFunctor (Prs3d_NListOfSequenceOfPnt& thePolylinesU,
+                             Prs3d_NListOfSequenceOfPnt& thePolylinesV,
+                             const std::vector<TopoDS_Face>& theFaces,
+                             const Handle(Prs3d_Drawer)& theDrawer,
+                             Standard_Real theShapeDeflection)
+  : myPolylinesU (thePolylinesU),
+    myPolylinesV (thePolylinesV),
+    myFaces (theFaces),
+    myDrawer (theDrawer),
+    myShapeDeflection (theShapeDeflection)
+  {
+    //
+  }
+
+  void operator()(const Standard_Integer& theIndex) const
+  {
+    Prs3d_NListOfSequenceOfPnt aPolylinesU, aPolylinesV;
+    const TopoDS_Face& aFace = myFaces[theIndex];
+    StdPrs_Isolines::Add (aFace, myDrawer, myShapeDeflection, aPolylinesU, aPolylinesV);
+    {
+      Standard_Mutex::Sentry aLock (myMutex);
+      myPolylinesU.Append (aPolylinesU);
+      myPolylinesV.Append (aPolylinesV);
+    }
+  }
+
+private:
+  StdPrs_WFShape_IsoFunctor operator= (StdPrs_WFShape_IsoFunctor& );
+private:
+  Prs3d_NListOfSequenceOfPnt&     myPolylinesU;
+  Prs3d_NListOfSequenceOfPnt&     myPolylinesV;
+  const std::vector<TopoDS_Face>& myFaces;
+  const Handle(Prs3d_Drawer)&     myDrawer;
+  mutable Standard_Mutex          myMutex;
+  const Standard_Real             myShapeDeflection;
+};
+
+
 // =========================================================================
 // function : Add
 // purpose  :
 // =========================================================================
-void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
-                          const TopoDS_Shape&                theShape,
-                          const Handle (Prs3d_Drawer)&       theDrawer)
+void StdPrs_WFShape::Add (const Handle(Prs3d_Presentation)& thePresentation,
+                          const TopoDS_Shape& theShape,
+                          const Handle(Prs3d_Drawer)& theDrawer,
+                          Standard_Boolean theIsParallel)
 {
   if (theShape.IsNull())
   {
@@ -106,14 +150,43 @@ void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
       aVPolylinesPtr = &aCommonPolylines;
     }
 
-    for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
+    bool isParallelIso = false;
+    if (theIsParallel)
     {
-      if (aTool.IsPlanarFace() && !theDrawer->IsoOnPlane())
+      Standard_Integer aNbFaces = 0;
+      for (TopExp_Explorer aFaceExplorer (theShape, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
       {
-        continue;
+        ++aNbFaces;
       }
+      if (aNbFaces > 1)
+      {
+        isParallelIso = true;
+        std::vector<TopoDS_Face> aFaces (aNbFaces);
+        aNbFaces = 0;
+        for (TopExp_Explorer aFaceExplorer (theShape, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
+        {
+          const TopoDS_Face& aFace = TopoDS::Face (aFaceExplorer.Current());
+          if (theDrawer->IsoOnPlane() || !Prs3d_ShapeTool::IsPlanarFace (aFace))
+          {
+            aFaces[aNbFaces++] = aFace;
+          }
+        }
+
+        StdPrs_WFShape_IsoFunctor anIsoFunctor (*aUPolylinesPtr, *aVPolylinesPtr, aFaces, theDrawer, aShapeDeflection);
+        OSD_Parallel::For (0, aNbFaces - 1, anIsoFunctor, aNbFaces < 2);
+      }
+    }
 
-      StdPrs_Isolines::Add (aTool.GetFace(), theDrawer, aShapeDeflection, *aUPolylinesPtr, *aVPolylinesPtr);
+    if (!isParallelIso)
+    {
+      for (TopExp_Explorer aFaceExplorer (theShape, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
+      {
+        const TopoDS_Face& aFace = TopoDS::Face (aFaceExplorer.Current());
+        if (theDrawer->IsoOnPlane() || !Prs3d_ShapeTool::IsPlanarFace (aFace))
+        {
+          StdPrs_Isolines::Add (aFace, theDrawer, aShapeDeflection, *aUPolylinesPtr, *aVPolylinesPtr);
+        }
+      }
     }
 
     Prs3d::AddPrimitivesGroup (thePresentation, anIsoAspectU, aUPolylines);
index db759de..de35127 100755 (executable)
@@ -33,9 +33,11 @@ public:
   //! @param thePresentation [in] the presentation.
   //! @param theShape [in] the shape.
   //! @param theDrawer [in] the draw settings.
-  Standard_EXPORT static void Add (const Handle (Prs3d_Presentation)& thePresentation,
-                                   const TopoDS_Shape&                theShape,
-                                   const Handle (Prs3d_Drawer)&       theDrawer);
+  //! @param theIsParallel [in] perform algorithm using multiple threads
+  Standard_EXPORT static void Add (const Handle(Prs3d_Presentation)& thePresentation,
+                                   const TopoDS_Shape& theShape,
+                                   const Handle(Prs3d_Drawer)& theDrawer,
+                                   Standard_Boolean theIsParallel = Standard_False);
 
   //! Compute free and boundary edges on a triangulation of each face in the given shape.
   //! @param theShape              [in] the list of triangulated faces