0027596: Visualization, StdPrs_WFShape - pack isolines into single group of primitives
authorkgv <kgv@opencascade.com>
Tue, 14 Jun 2016 11:02:27 +0000 (14:02 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 16 Jun 2016 11:58:24 +0000 (14:58 +0300)
StdPrs_ShadedShape, computeFaceBoundaries() now does not create additional temporary buffer for edges.
StdPrs_Isolines::AddOnTriangulation() now reconstacts polylines from segments projected onto triangulation.

StdPrs_WFShape::Add() now packs isolines into single group in presentation (instead of per-face group).
Even more - StdPrs_WFShape now groups lines with the same aspects.

Prs3d_Drawer::UIsoAspect(), ::VIsoAspect(), ::VIsoAspect() - default width
has been changed from 0.5 to 1.0.

src/Aspect/Aspect_AspectLine.hxx
src/Graphic3d/Graphic3d_AspectLine3d.hxx
src/Prs3d/Prs3d.cxx
src/Prs3d/Prs3d.hxx
src/Prs3d/Prs3d_Drawer.cxx
src/StdPrs/StdPrs_DeflectionCurve.cxx
src/StdPrs/StdPrs_Isolines.cxx
src/StdPrs/StdPrs_Isolines.hxx
src/StdPrs/StdPrs_ShadedShape.cxx
src/StdPrs/StdPrs_WFShape.cxx
src/StdPrs/StdPrs_WFShape.hxx

index 0e81548..237e8a4 100644 (file)
@@ -81,7 +81,7 @@ protected:
 
 
 
-private:
+protected:
 
 
   Quantity_Color MyColor;
index 197269d..45dad22 100644 (file)
@@ -60,7 +60,19 @@ public:
   
   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& ShaderProgram() const;
 
-
+  //! Check for equality with another line aspect.
+  bool IsEqual (const Graphic3d_AspectLine3d& theOther)
+  {
+    if (this == &theOther)
+    {
+      return true;
+    }
+
+    return MyShaderProgram == theOther.MyShaderProgram
+        && MyType  == theOther.MyType
+        && MyColor == theOther.MyColor
+        && MyWidth == theOther.MyWidth;
+  }
 
 
   DEFINE_STANDARD_RTTIEXT(Graphic3d_AspectLine3d,Aspect_AspectLine)
index 9e6c855..ccd9cd5 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <Prs3d.hxx>
 
 #include <Bnd_Box.hxx>
 #include <BRepBndLib.hxx>
 #include <gp_Pnt.hxx>
-#include <Prs3d.hxx>
+#include <Graphic3d_Group.hxx>
 #include <Prs3d_Drawer.hxx>
+#include <Prs3d_LineAspect.hxx>
+#include <Prs3d_Root.hxx>
 #include <TopoDS_Shape.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
 
 //=======================================================================
 //function : MatchSegment
@@ -78,3 +82,56 @@ Standard_Real Prs3d::GetDeflection (const TopoDS_Shape&         theShape,
   }
   return aDeflection;
 }
+
+//==================================================================
+// function: PrimitivesFromPolylines
+// purpose:
+//==================================================================
+Handle(Graphic3d_ArrayOfPrimitives) Prs3d::PrimitivesFromPolylines (const Prs3d_NListOfSequenceOfPnt& thePoints)
+{
+  if (thePoints.IsEmpty())
+  {
+    return Handle(Graphic3d_ArrayOfPrimitives)();
+  }
+
+  Standard_Integer aNbVertices = 0;
+  for (Prs3d_NListOfSequenceOfPnt::Iterator anIt (thePoints); anIt.More(); anIt.Next())
+  {
+    aNbVertices += anIt.Value()->Length();
+  }
+  const Standard_Integer aSegmentEdgeNb = (aNbVertices - thePoints.Size()) * 2;
+  Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNbVertices, aSegmentEdgeNb);
+  for (Prs3d_NListOfSequenceOfPnt::Iterator anIt (thePoints); anIt.More(); anIt.Next())
+  {
+    const Handle(TColgp_HSequenceOfPnt)& aPoints = anIt.Value();
+
+    Standard_Integer aSegmentEdge = aSegments->VertexNumber() + 1;
+    aSegments->AddVertex (aPoints->First());
+    for (Standard_Integer aPntIter = aPoints->Lower() + 1; aPntIter <= aPoints->Upper(); ++aPntIter)
+    {
+      aSegments->AddVertex (aPoints->Value (aPntIter));
+      aSegments->AddEdge (  aSegmentEdge);
+      aSegments->AddEdge (++aSegmentEdge);
+    }
+  }
+
+  return aSegments;
+}
+
+//==================================================================
+// function: AddPrimitivesGroup
+// purpose:
+//==================================================================
+void Prs3d::AddPrimitivesGroup (const Handle(Prs3d_Presentation)& thePrs,
+                                const Handle(Prs3d_LineAspect)&   theAspect,
+                                Prs3d_NListOfSequenceOfPnt&       thePolylines)
+{
+  Handle(Graphic3d_ArrayOfPrimitives) aPrims = Prs3d::PrimitivesFromPolylines (thePolylines);
+  thePolylines.Clear();
+  if (!aPrims.IsNull())
+  {
+    Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePrs);
+    aGroup->SetPrimitivesAspect (theAspect->Aspect());
+    aGroup->AddPrimitiveArray (aPrims);
+  }
+}
index dc35305..ec8fc7d 100644 (file)
 #ifndef _Prs3d_HeaderFile
 #define _Prs3d_HeaderFile
 
+#include <Graphic3d_ArrayOfPrimitives.hxx>
 #include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
-
 #include <Standard_Boolean.hxx>
 #include <Quantity_Length.hxx>
 #include <Standard_Real.hxx>
 #include <Prs3d_Drawer.hxx>
-class gp_Pnt;
+#include <Prs3d_NListOfSequenceOfPnt.hxx>
+
 class TopoDS_Shape;
 class Prs3d_Presentation;
-class Prs3d_BasicAspect;
-class Prs3d_PointAspect;
-class Prs3d_LineAspect;
-class Prs3d_ShadingAspect;
-class Prs3d_TextAspect;
-class Prs3d_IsoAspect;
-class Prs3d_ArrowAspect;
-class Prs3d_PlaneAspect;
-class Prs3d_DimensionAspect;
-class Prs3d_DatumAspect;
-class Prs3d_Projector;
-class Prs3d_PlaneSet;
-class Prs3d_Root;
-class Prs3d_Text;
-class Prs3d_ShapeTool;
-class Prs3d_Arrow;
-
 
 //! The Prs3d package provides the following services
 //! -   a presentation object (the context for all
@@ -64,7 +48,6 @@ class Prs3d
 public:
 
   DEFINE_STANDARD_ALLOC
-
   
   //! draws an arrow at a given location, with respect
   //! to a given direction.
@@ -84,44 +67,16 @@ public:
   //! between different representations of the shape and undesirable visual artifacts.
   Standard_EXPORT static Standard_Real GetDeflection (const TopoDS_Shape& theShape, const Handle(Prs3d_Drawer)& theDrawer);
 
+  //! Assembles array of primitives for sequence of polylines.
+  //! @param thePoints [in] the polylines sequence
+  //! @return array of primitives
+  Standard_EXPORT static Handle(Graphic3d_ArrayOfPrimitives) PrimitivesFromPolylines (const Prs3d_NListOfSequenceOfPnt& thePoints);
 
-
-
-protected:
-
-
-
-
-
-private:
-
-
-
-
-friend class Prs3d_Presentation;
-friend class Prs3d_BasicAspect;
-friend class Prs3d_PointAspect;
-friend class Prs3d_LineAspect;
-friend class Prs3d_ShadingAspect;
-friend class Prs3d_TextAspect;
-friend class Prs3d_IsoAspect;
-friend class Prs3d_ArrowAspect;
-friend class Prs3d_PlaneAspect;
-friend class Prs3d_DimensionAspect;
-friend class Prs3d_DatumAspect;
-friend class Prs3d_Projector;
-friend class Prs3d_PlaneSet;
-friend class Prs3d_Root;
-friend class Prs3d_Text;
-friend class Prs3d_ShapeTool;
-friend class Prs3d_Arrow;
+  //! Add primitives into new group in presentation and clear the list of polylines.
+  Standard_EXPORT static void AddPrimitivesGroup (const Handle(Prs3d_Presentation)& thePrs,
+                                                  const Handle(Prs3d_LineAspect)&   theAspect,
+                                                  Prs3d_NListOfSequenceOfPnt&       thePolylines);
 
 };
 
-
-
-
-
-
-
 #endif // _Prs3d_HeaderFile
index b3bdcc7..374e32d 100644 (file)
@@ -474,7 +474,7 @@ const Handle(Prs3d_IsoAspect)& Prs3d_Drawer::UIsoAspect()
     }
     if (myUIsoAspect.IsNull())
     {
-      myUIsoAspect = new Prs3d_IsoAspect (Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 0.5, 1);
+      myUIsoAspect = new Prs3d_IsoAspect (Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 1.0, 1);
     }
   }
   return myUIsoAspect;
@@ -506,7 +506,7 @@ const Handle(Prs3d_IsoAspect)& Prs3d_Drawer::VIsoAspect()
     }
     if (myVIsoAspect.IsNull())
     {
-      myVIsoAspect = new Prs3d_IsoAspect (Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 0.5, 1);
+      myVIsoAspect = new Prs3d_IsoAspect (Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 1.0, 1);
     }
   }
   return myVIsoAspect;
@@ -827,7 +827,7 @@ const Handle(Prs3d_LineAspect)& Prs3d_Drawer::HiddenLineAspect()
     }
     if (myHiddenLineAspect.IsNull())
     {
-      myHiddenLineAspect = new Prs3d_LineAspect (Quantity_NOC_YELLOW, Aspect_TOL_DASH, 0.5);
+      myHiddenLineAspect = new Prs3d_LineAspect (Quantity_NOC_YELLOW, Aspect_TOL_DASH, 1.0);
     }
   }
   return myHiddenLineAspect;
index aa60e72..5111b19 100644 (file)
@@ -285,25 +285,26 @@ void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentati
                                   const Handle (Prs3d_Drawer)&       aDrawer,
                                   const Standard_Boolean theToDrawCurve)
 {
-  Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(aDrawer->LineAspect()->Aspect());
+  Handle(Graphic3d_Group) aGroup;
+  if (theToDrawCurve)
+  {
+    aGroup = Prs3d_Root::CurrentGroup(aPresentation);
+    aGroup->SetPrimitivesAspect (aDrawer->LineAspect()->Aspect());
+  }
 
   Standard_Real V1, V2;
   if (FindLimits(aCurve, aDrawer->MaximalParameterValue(), V1, V2))
   {
     TColgp_SequenceOfPnt Points;
-    Handle(Graphic3d_Group) aGroup;
-    if (theToDrawCurve)
-    {
-      aGroup = Prs3d_Root::CurrentGroup (aPresentation);
-    }
-
     drawCurve(aCurve,
               aGroup,
               GetDeflection(aCurve, V1, V2, aDrawer),
               aDrawer->DeviationAngle(),
               V1, V2, Points);
 
-    if (aDrawer->LineArrowDraw()) {
+    if (aDrawer->LineArrowDraw()
+    && !aGroup.IsNull())
+    {
       gp_Pnt Location;
       gp_Vec Direction;
       aCurve.D1(V2, Location,Direction);
@@ -348,7 +349,9 @@ void StdPrs_DeflectionCurve::Add (const Handle (Prs3d_Presentation)& aPresentati
             aDrawer->DeviationAngle(),
             V1 , V2, Points);
 
-  if (aDrawer->LineArrowDraw()) {
+  if (aDrawer->LineArrowDraw()
+  && !aGroup.IsNull())
+  {
     gp_Pnt Location;
     gp_Vec Direction;
     aCurve.D1(V2, Location,Direction);
index cc3211c..ad2b101 100644 (file)
 #include <Adaptor3d_IsoCurve.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Tool.hxx>
-#include <ElCLib.hxx>
-#include <ElSLib.hxx>
-#include <GCE2d_MakeLine.hxx>
-#include <gce_MakeLin2d.hxx>
-#include <gce_MakePln.hxx>
-#include <gce_MakeLin.hxx>
 #include <GCPnts_AbscissaPoint.hxx>
 #include <GCPnts_QuasiUniformDeflection.hxx>
 #include <Geom_BezierSurface.hxx>
 #include <Geom_Line.hxx>
 #include <Geom2d_Line.hxx>
 #include <Geom2dAdaptor_Curve.hxx>
-#include <Geom2dInt_GInter.hxx>
 #include <GeomAdaptor_Curve.hxx>
-#include <GeomAPI_IntCS.hxx>
-#include <GeomLib.hxx>
 #include <GeomLib_Tool.hxx>
 #include <gp_Lin2d.hxx>
-#include <Graphic3d_ArrayOfSegments.hxx>
-#include <Graphic3d_ArrayOfPolylines.hxx>
 #include <Hatch_Hatcher.hxx>
-#include <IntRes2d_IntersectionPoint.hxx>
-#include <NCollection_List.hxx>
-#include <NCollection_QuickSort.hxx>
-#include <ProjLib.hxx>
+#include <NCollection_Shared.hxx>
+#include <Prs3d.hxx>
 #include <Prs3d_IsoAspect.hxx>
-#include <Prs3d_NListOfSequenceOfPnt.hxx>
-#include <Prs3d_NListIteratorOfListOfSequenceOfPnt.hxx>
 #include <Poly_Array1OfTriangle.hxx>
 #include <Poly_Triangulation.hxx>
 #include <StdPrs_DeflectionCurve.hxx>
 #include <StdPrs_ToolRFace.hxx>
-#include <TColgp_Array1OfPnt.hxx>
 #include <TColgp_SequenceOfPnt2d.hxx>
 #include <Standard_ErrorHandler.hxx>
 #include <Geom_Surface.hxx>
 
-typedef NCollection_Sequence<Handle(TColgp_HSequenceOfPnt)> Prs3d_NSequenceOfSequenceOfPnt;
+#include <algorithm>
 
 namespace
 {
   const gp_Lin2d isoU (const Standard_Real theU) { return gp_Lin2d (gp_Pnt2d (theU, 0.0), gp::DY2d()); }
   const gp_Lin2d isoV (const Standard_Real theV) { return gp_Lin2d (gp_Pnt2d (0.0, theV), gp::DX2d()); }
 
-  //! Assembles array of primitives for sequence of polyine points.
-  //! @param thePoints [in] the polyline points.
-  //! @return array of primitives.
-  template <typename T>
-  inline Handle(T) primitivesForPolyline (const Prs3d_NSequenceOfSequenceOfPnt& thePoints)
+  typedef NCollection_Shared< NCollection_Vector<StdPrs_Isolines::SegOnIso> > VecOfSegments;
+  typedef NCollection_Sequence<Handle(VecOfSegments)> SeqOfVecOfSegments;
+
+  //! Pack isoline segments into polylines.
+  static void sortSegments (const SeqOfVecOfSegments&   theSegments,
+                            Prs3d_NListOfSequenceOfPnt& thePolylines)
   {
-    if (thePoints.IsEmpty())
+    for (SeqOfVecOfSegments::Iterator aLineIter (theSegments); aLineIter.More(); aLineIter.Next())
     {
-      return Handle(T)();
-    }
+      Handle(VecOfSegments)& anIsoSegs = aLineIter.ChangeValue();
+      std::stable_sort (anIsoSegs->begin(), anIsoSegs->end());
 
-    Standard_Integer aNbBounds   = thePoints.Size();
-    Standard_Integer aNbVertices = 0;
-    for (Prs3d_NSequenceOfSequenceOfPnt::Iterator anIt (thePoints); anIt.More(); anIt.Next())
-    {
-      aNbVertices += anIt.Value()->Length();
-    }
-    Handle(T) aPrimitives = new T (aNbVertices, aNbBounds);
-    for (NCollection_Sequence<Handle(TColgp_HSequenceOfPnt)>::Iterator anIt (thePoints); anIt.More(); anIt.Next())
-    {
-      const Handle(TColgp_HSequenceOfPnt)& aPoints = anIt.Value();
-      aPrimitives->AddBound (aPoints->Length());
-      for (Standard_Integer anI = 1; anI <= aPoints->Length(); ++anI)
+      Handle(TColgp_HSequenceOfPnt) aPolyline = new TColgp_HSequenceOfPnt();
+      thePolylines.Append (aPolyline);
+      Standard_Real aLast = 0.0;
+      for (VecOfSegments::Iterator aSegIter (*anIsoSegs); aSegIter.More(); aSegIter.Next())
       {
-        aPrimitives->AddVertex (aPoints->Value (anI));
+        if (!aPolyline->IsEmpty()
+         && Abs (aSegIter.Value()[0].Param - aLast) > Precision::PConfusion())
+        {
+          aPolyline = new TColgp_HSequenceOfPnt();
+          thePolylines.Append (aPolyline);
+        }
+
+        aPolyline->Append (aSegIter.Value()[0].Pnt);
+        aPolyline->Append (aSegIter.Value()[1].Pnt);
+        aLast = aSegIter.Value()[1].Param;
       }
     }
-
-    return aPrimitives;
   }
 
   //! Reoder and adjust to the limit a curve's parameter values.
@@ -164,6 +148,21 @@ void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& theP
                                           const TopoDS_Face&                theFace,
                                           const Handle(Prs3d_Drawer)&       theDrawer)
 {
+  Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
+  AddOnTriangulation (theFace, theDrawer, aUPolylines, aVPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
+}
+
+//==================================================================
+// function : AddOnTriangulation
+// purpose  :
+//==================================================================
+void StdPrs_Isolines::AddOnTriangulation (const TopoDS_Face&          theFace,
+                                          const Handle(Prs3d_Drawer)& theDrawer,
+                                          Prs3d_NListOfSequenceOfPnt& theUPolylines,
+                                          Prs3d_NListOfSequenceOfPnt& theVPolylines)
+{
   const Standard_Integer aNbIsoU = theDrawer->UIsoAspect()->Number();
   const Standard_Integer aNbIsoV = theDrawer->VIsoAspect()->Number();
   if (aNbIsoU < 1 && aNbIsoV < 1)
@@ -171,7 +170,7 @@ void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& theP
     return;
   }
 
-  // Evalute parameters for uv isolines.
+  // Evaluate parameters for uv isolines.
   TColStd_SequenceOfReal aUIsoParams;
   TColStd_SequenceOfReal aVIsoParams;
   UVIsoParameters (theFace, aNbIsoU, aNbIsoV, theDrawer->MaximalParameterValue(), aUIsoParams, aVIsoParams);
@@ -195,13 +194,7 @@ void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& theP
       aSurface->Transformed ((aLocSurface / aLocTriangulation).Transformation()));
   }
 
-  AddOnTriangulation (thePresentation,
-                      aTriangulation,
-                      aSurface,
-                      aLocTriangulation,
-                      theDrawer,
-                      aUIsoParams,
-                      aVIsoParams);
+  addOnTriangulation (aTriangulation, aSurface, aLocTriangulation, aUIsoParams, aVIsoParams, theUPolylines, theVPolylines);
 }
 
 //==================================================================
@@ -216,11 +209,28 @@ void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& theP
                                           const TColStd_SequenceOfReal&     theUIsoParams,
                                           const TColStd_SequenceOfReal&     theVIsoParams)
 {
+  Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
+  addOnTriangulation (theTriangulation, theSurface, theLocation, theUIsoParams, theVIsoParams, aUPolylines, aVPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
+}
+
+//==================================================================
+// function : addOnTriangulation
+// purpose  :
+//==================================================================
+void StdPrs_Isolines::addOnTriangulation (const Handle(Poly_Triangulation)& theTriangulation,
+                                          const Handle(Geom_Surface)&       theSurface,
+                                          const TopLoc_Location&            theLocation,
+                                          const TColStd_SequenceOfReal&     theUIsoParams,
+                                          const TColStd_SequenceOfReal&     theVIsoParams,
+                                          Prs3d_NListOfSequenceOfPnt&       theUPolylines,
+                                          Prs3d_NListOfSequenceOfPnt&       theVPolylines)
+{
   const Standard_Integer aNbIsoU = theUIsoParams.Length();
   const Standard_Integer aNbIsoV = theVIsoParams.Length();
 
-  Prs3d_NSequenceOfSequenceOfPnt aUPolylines;
-  Prs3d_NSequenceOfSequenceOfPnt aVPolylines;
+  SeqOfVecOfSegments aUPolylines, aVPolylines;
 
   const Poly_Array1OfTriangle& aTriangles = theTriangulation->Triangles();
   const TColgp_Array1OfPnt&    aNodes     = theTriangulation->Nodes();
@@ -245,66 +255,59 @@ void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& theP
     // Evaluate polyline points for u isolines.
     for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsoU; ++anIsoIdx)
     {
-      gp_Pnt aSegment[2];
+      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, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
+      if (!findSegmentOnTriangulation (theSurface, true, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
       {
         continue;
       }
 
       if (aUIsoIndexes.Value (anIsoIdx) == -1)
       {
-        aUPolylines.Append (new TColgp_HSequenceOfPnt());
+        aUPolylines.Append (new VecOfSegments());
         aUIsoIndexes.SetValue (anIsoIdx, aUPolylines.Size());
       }
 
-      Handle(TColgp_HSequenceOfPnt) anIsoPnts = aUPolylines.ChangeValue (aUIsoIndexes.Value (anIsoIdx));
-      anIsoPnts->Append (theLocation.IsIdentity() ? aSegment[0] : aSegment[0].Transformed (theLocation));
-      anIsoPnts->Append (theLocation.IsIdentity() ? aSegment[1] : aSegment[1].Transformed (theLocation));
+      Handle(VecOfSegments) anIsoPnts = aUPolylines.ChangeValue (aUIsoIndexes.Value (anIsoIdx));
+      if (!theLocation.IsIdentity())
+      {
+        aSegment[0].Pnt.Transform (theLocation);
+        aSegment[1].Pnt.Transform (theLocation);
+      }
+      anIsoPnts->Append (aSegment);
     }
 
     // Evaluate polyline points for v isolines.
     for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsoV; ++anIsoIdx)
     {
-      gp_Pnt aSegment[2];
+      SegOnIso aSegment;
       const gp_Lin2d anIsolineUV = isoV (theVIsoParams.Value (anIsoIdx));
 
-      if (!findSegmentOnTriangulation (theSurface, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
+      if (!findSegmentOnTriangulation (theSurface, false, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
       {
         continue;
       }
 
       if (aVIsoIndexes.Value (anIsoIdx) == -1)
       {
-        aVPolylines.Append (new TColgp_HSequenceOfPnt());
+        aVPolylines.Append (new VecOfSegments());
         aVIsoIndexes.SetValue (anIsoIdx, aVPolylines.Size());
       }
 
-      Handle(TColgp_HSequenceOfPnt) anIsoPnts = aVPolylines.ChangeValue (aVIsoIndexes.Value (anIsoIdx));
-      anIsoPnts->Append (theLocation.IsIdentity() ? aSegment[0] : aSegment[0].Transformed (theLocation));
-      anIsoPnts->Append (theLocation.IsIdentity() ? aSegment[1] : aSegment[1].Transformed (theLocation));
+      Handle(VecOfSegments) anIsoPnts = aVPolylines.ChangeValue (aVIsoIndexes.Value (anIsoIdx));
+      if (!theLocation.IsIdentity())
+      {
+        aSegment[0].Pnt.Transform (theLocation);
+        aSegment[1].Pnt.Transform (theLocation);
+      }
+      anIsoPnts->Append (aSegment);
     }
   }
 
-  // Add primitive arrays for isoline segments.
-  Handle(Graphic3d_ArrayOfSegments) aUPrimitives = primitivesForPolyline<Graphic3d_ArrayOfSegments> (aUPolylines);
-  Handle(Graphic3d_ArrayOfSegments) aVPrimitives = primitivesForPolyline<Graphic3d_ArrayOfSegments> (aVPolylines);
-
-  if (!aUPrimitives.IsNull())
-  {
-    Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
-    aGroup->SetPrimitivesAspect (theDrawer->UIsoAspect()->Aspect());
-    aGroup->AddPrimitiveArray (aUPrimitives);
-  }
-
-  if (!aVPrimitives.IsNull())
-  {
-    Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
-    aGroup->SetPrimitivesAspect (theDrawer->VIsoAspect()->Aspect());
-    aGroup->AddPrimitiveArray (aVPrimitives);
-  }
+  sortSegments (aUPolylines, theUPolylines);
+  sortSegments (aVPolylines, theVPolylines);
 }
 
 //==================================================================
@@ -316,6 +319,22 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)& thePresent
                                     const Handle(Prs3d_Drawer)&       theDrawer,
                                     const Standard_Real               theDeflection)
 {
+  Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
+  AddOnSurface (theFace, theDrawer, theDeflection, aUPolylines, aVPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
+}
+
+//==================================================================
+// function : AddOnSurface
+// purpose  :
+//==================================================================
+void StdPrs_Isolines::AddOnSurface (const TopoDS_Face&          theFace,
+                                    const Handle(Prs3d_Drawer)& theDrawer,
+                                    const Standard_Real         theDeflection,
+                                    Prs3d_NListOfSequenceOfPnt& theUPolylines,
+                                    Prs3d_NListOfSequenceOfPnt& theVPolylines)
+{
   const Standard_Integer aNbIsoU = theDrawer->UIsoAspect()->Number();
   const Standard_Integer aNbIsoV = theDrawer->VIsoAspect()->Number();
   if (aNbIsoU < 1 && aNbIsoV < 1)
@@ -323,18 +342,18 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)& thePresent
     return;
   }
 
-  // Evalute parameters for uv isolines.
-  TColStd_SequenceOfReal aUIsoParams;
-  TColStd_SequenceOfReal aVIsoParams;
+  // Evaluate parameters for uv isolines.
+  TColStd_SequenceOfReal aUIsoParams, aVIsoParams;
   UVIsoParameters (theFace, aNbIsoU, aNbIsoV, theDrawer->MaximalParameterValue(), aUIsoParams, aVIsoParams);
 
   BRepAdaptor_Surface aSurface (theFace);
-  AddOnSurface (thePresentation,
-                new BRepAdaptor_HSurface (aSurface),
+  addOnSurface (new BRepAdaptor_HSurface (aSurface),
                 theDrawer,
                 theDeflection,
                 aUIsoParams,
-                aVIsoParams);
+                aVIsoParams,
+                theUPolylines,
+                theVPolylines);
 }
 
 //==================================================================
@@ -348,6 +367,24 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)&   thePrese
                                     const TColStd_SequenceOfReal&       theUIsoParams,
                                     const TColStd_SequenceOfReal&       theVIsoParams)
 {
+  Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
+  addOnSurface (theSurface, theDrawer, theDeflection, theUIsoParams, theVIsoParams, aUPolylines, aVPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
+}
+
+//==================================================================
+// function : addOnSurface
+// purpose  :
+//==================================================================
+void StdPrs_Isolines::addOnSurface (const Handle(BRepAdaptor_HSurface)& theSurface,
+                                    const Handle(Prs3d_Drawer)&         theDrawer,
+                                    const Standard_Real                 theDeflection,
+                                    const TColStd_SequenceOfReal&       theUIsoParams,
+                                    const TColStd_SequenceOfReal&       theVIsoParams,
+                                    Prs3d_NListOfSequenceOfPnt&         theUPolylines,
+                                    Prs3d_NListOfSequenceOfPnt&         theVPolylines)
+{
   // Choose a deflection for sampling edge uv curves.
   Standard_Real aUVLimit = theDrawer->MaximalParameterValue();
   Standard_Real aUmin  = Max (theSurface->FirstUParameter(), -aUVLimit);
@@ -356,8 +393,6 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)&   thePrese
   Standard_Real aVmax  = Min (theSurface->LastVParameter(),   aUVLimit);
   Standard_Real aSamplerDeflection = Max (aUmax - aUmin, aVmax - aVmin) * theDrawer->DeviationCoefficient();
   Standard_Real aHatchingTolerance = RealLast();
-  Prs3d_NSequenceOfSequenceOfPnt aUPolylines;
-  Prs3d_NSequenceOfSequenceOfPnt aVPolylines;
 
   try
   {
@@ -522,7 +557,7 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)&   thePrese
           : (Adaptor3d_Curve*) &aBSurfaceCurve;
 
         Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
-        StdPrs_DeflectionCurve::Add (thePresentation,
+        StdPrs_DeflectionCurve::Add (Handle(Prs3d_Presentation)(),
                                      *aCurve,
                                      aSegmentP1,
                                      aSegmentP2,
@@ -537,11 +572,11 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)&   thePrese
 
         if (isIsoU)
         {
-          aUPolylines.Append (aPoints);
+          theUPolylines.Append (aPoints);
         }
         else
         {
-          aVPolylines.Append (aPoints);
+          theVPolylines.Append (aPoints);
         }
       }
     }
@@ -550,24 +585,6 @@ void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)&   thePrese
   {
     // ...
   }
-
-  // Add primitive arrays for isoline segments.
-  Handle(Graphic3d_ArrayOfPolylines) aUPrimitives = primitivesForPolyline<Graphic3d_ArrayOfPolylines> (aUPolylines);
-  Handle(Graphic3d_ArrayOfPolylines) aVPrimitives = primitivesForPolyline<Graphic3d_ArrayOfPolylines> (aVPolylines);
-
-  if (!aUPrimitives.IsNull())
-  {
-    Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
-    aGroup->SetPrimitivesAspect (theDrawer->UIsoAspect()->Aspect());
-    aGroup->AddPrimitiveArray (aUPrimitives);
-  }
-
-  if (!aVPrimitives.IsNull())
-  {
-    Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
-    aGroup->SetPrimitivesAspect (theDrawer->VIsoAspect()->Aspect());
-    aGroup->AddPrimitiveArray (aVPrimitives);
-  }
 }
 
 //==================================================================
@@ -630,10 +647,11 @@ void StdPrs_Isolines::UVIsoParameters (const TopoDS_Face&      theFace,
 // purpose  :
 //==================================================================
 Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_Surface)& theSurface,
+                                                              const bool                  theIsU,
                                                               const gp_Lin2d&             theIsoline,
                                                               const gp_Pnt*               theNodesXYZ,
                                                               const gp_Pnt2d*             theNodesUV,
-                                                              gp_Pnt*                     theSegment)
+                                                              SegOnIso&                   theSegment)
 {
   Standard_Integer aNPoints = 0;
 
@@ -660,15 +678,20 @@ Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_
     // Isoline crosses first point of an edge.
     if (Abs (aDistanceUV1) < Precision::PConfusion())
     {
-      theSegment[aNPoints++] = aNode1;
+      theSegment[aNPoints].Param = theIsU ? aNodeUV1.Y() : aNodeUV1.X();
+      theSegment[aNPoints].Pnt   = aNode1;
+      ++aNPoints;
       continue;
     }
 
     // Isoline crosses second point of an edge.
     if (Abs (aDistanceUV2) < Precision::PConfusion())
     {
-      theSegment[aNPoints++] = aNode2;
-      aLinkIter++;
+      theSegment[aNPoints].Param = theIsU ? aNodeUV2.Y() : aNodeUV2.X();
+      theSegment[aNPoints].Pnt   = aNode2;
+
+      ++aNPoints;
+      ++aLinkIter;
       continue;
     }
 
@@ -681,7 +704,9 @@ Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_
     // Isoline crosses degenerated link.
     if (aNode1.SquareDistance (aNode2) < Precision::PConfusion())
     {
-      theSegment[aNPoints++] = aNode1;
+      theSegment[aNPoints].Param = theIsU ? aNodeUV1.Y() : aNodeUV1.X();
+      theSegment[aNPoints].Pnt   = aNode1;
+      ++aNPoints;
       continue;
     }
 
@@ -692,12 +717,12 @@ Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_
     Standard_Real anAlpha = Abs (aDistanceUV1) / (Abs (aDistanceUV1) + Abs (aDistanceUV2));
 
     gp_Pnt aCross (0.0, 0.0, 0.0);
-
-    // Is surface definition available?
+    Standard_Real aCrossU = aNodeUV1.X() + anAlpha * (aNodeUV2.X() - aNodeUV1.X());
+    Standard_Real aCrossV = aNodeUV1.Y() + anAlpha * (aNodeUV2.Y() - aNodeUV1.Y());
+    Standard_Real aCrossParam = theIsU ? aCrossV : aCrossU;
     if (theSurface.IsNull())
     {
-      // Do linear interpolation of point coordinates using
-      // triangulation nodes.
+      // Do linear interpolation of point coordinates using triangulation nodes.
       aCross.SetX (aNode1.X() + anAlpha * (aNode2.X() - aNode1.X()));
       aCross.SetY (aNode1.Y() + anAlpha * (aNode2.Y() - aNode1.Y()));
       aCross.SetZ (aNode1.Z() + anAlpha * (aNode2.Z() - aNode1.Z()));
@@ -705,9 +730,6 @@ Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_
     else
     {
       // Do linear interpolation of point coordinates by triangulation nodes.
-      Standard_Real aCrossU = aNodeUV1.X() + anAlpha * (aNodeUV2.X() - aNodeUV1.X());
-      Standard_Real aCrossV = aNodeUV1.Y() + anAlpha * (aNodeUV2.Y() - aNodeUV1.Y());
-
       // Get 3d point on surface.
       Handle(Geom_Curve) anIso1, anIso2, anIso3;
       Standard_Real aPntOnNode1Iso = 0.0;
@@ -740,15 +762,29 @@ Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_
       Standard_Real aLength2 = GCPnts_AbscissaPoint::Length (aCurveAdaptor2, aPntOnNode2Iso, aPntOnNode3Iso, 1e-2);
       if (Abs (aLength1) < Precision::Confusion() || Abs (aLength2) < Precision::Confusion())
       {
-        theSegment[aNPoints++] = (aNode2.XYZ() - aNode1.XYZ()) * anAlpha + aNode1.XYZ();
+        theSegment[aNPoints].Param = aCrossParam;
+        theSegment[aNPoints].Pnt   = (aNode2.XYZ() - aNode1.XYZ()) * anAlpha + aNode1.XYZ();
+        ++aNPoints;
         continue;
       }
 
       aCross = (aNode2.XYZ() - aNode1.XYZ()) * (aLength1 / (aLength1 + aLength2)) + aNode1.XYZ();
     }
 
-    theSegment[aNPoints++] = aCross;
+    theSegment[aNPoints].Param = aCrossParam;
+    theSegment[aNPoints].Pnt   = aCross;
+    ++aNPoints;
+  }
+
+  if (aNPoints != 2
+   || Abs (theSegment[1].Param - theSegment[0].Param) <= Precision::PConfusion())
+  {
+    return false;
   }
 
-  return aNPoints == 2;
+  if (theSegment[1].Param < theSegment[0].Param)
+  {
+    std::swap (theSegment[0], theSegment[1]);
+  }
+  return true;
 }
index 0f6ae13..129abad 100644 (file)
@@ -24,6 +24,7 @@
 #include <Prs3d_Root.hxx>
 #include <Prs3d_NListOfSequenceOfPnt.hxx>
 #include <Poly_Triangulation.hxx>
+#include <StdPrs_DeflectionCurve.hxx>
 #include <StdPrs_ToolTriangulatedShape.hxx>
 #include <TColStd_Array1OfInteger.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
@@ -65,6 +66,29 @@ public:
     }
   }
 
+  //! Computes isolines presentation for a TopoDS face.
+  //! This method chooses proper version of isoline builder algorithm : on triangulation
+  //! or surface depending on the flag passed from Prs3d_Drawer attributes.
+  //! This method is a default way to display isolines for a given TopoDS face.
+  //! @param theFace [in] the face.
+  //! @param theDrawer [in] the display settings.
+  //! @param theDeflection [in] the deflection for isolines-on-surface version.
+  static void Add (const TopoDS_Face&          theFace,
+                   const Handle(Prs3d_Drawer)& theDrawer,
+                   const Standard_Real         theDeflection,
+                   Prs3d_NListOfSequenceOfPnt& theUPolylines,
+                   Prs3d_NListOfSequenceOfPnt& theVPolylines)
+  {
+    if (theDrawer->IsoOnTriangulation() && StdPrs_ToolTriangulatedShape::IsTriangulated (theFace))
+    {
+      AddOnTriangulation (theFace, theDrawer, theUPolylines, theVPolylines);
+    }
+    else
+    {
+      AddOnSurface (theFace, theDrawer, theDeflection, theUPolylines, theVPolylines);
+    }
+  }
+
   //! Computes isolines on triangulation and adds them to a presentation.
   //! @param thePresentation [in] the presentation.
   //! @param theFace [in] the face.
@@ -73,6 +97,16 @@ public:
                                                   const TopoDS_Face&                theFace,
                                                   const Handle(Prs3d_Drawer)&       theDrawer);
 
+  //! Computes isolines on triangulation.
+  //! @param theFace [in] the face.
+  //! @param theDrawer [in] the display settings.
+  //! @param theUPolylines [out] the sequence of result polylines
+  //! @param theVPolylines [out] the sequence of result polylines
+  Standard_EXPORT static void AddOnTriangulation (const TopoDS_Face&          theFace,
+                                                  const Handle(Prs3d_Drawer)& theDrawer,
+                                                  Prs3d_NListOfSequenceOfPnt& theUPolylines,
+                                                  Prs3d_NListOfSequenceOfPnt& theVPolylines);
+
   //! Computes isolines on triangulation and adds them to a presentation.
   //! @param thePresentation [in] the presentation.
   //! @param theTriangulation [in] the triangulation.
@@ -104,6 +138,18 @@ public:
                                             const Standard_Real               theDeflection);
 
   //! Computes isolines on surface and adds them to presentation.
+  //! @param theFace [in] the face
+  //! @param theDrawer [in] the display settings
+  //! @param theDeflection [in] the deflection value
+  //! @param theUPolylines [out] the sequence of result polylines
+  //! @param theVPolylines [out] the sequence of result polylines
+  Standard_EXPORT static void AddOnSurface (const TopoDS_Face&          theFace,
+                                            const Handle(Prs3d_Drawer)& theDrawer,
+                                            const Standard_Real         theDeflection,
+                                            Prs3d_NListOfSequenceOfPnt& theUPolylines,
+                                            Prs3d_NListOfSequenceOfPnt& theVPolylines);
+
+  //! Computes isolines on surface and adds them to presentation.
   //! @param thePresentation [in] the presentation.
   //! @param theSurface [in] the surface.
   //! @param theDrawer [in] the display settings.
@@ -131,20 +177,87 @@ public:
                                                TColStd_SequenceOfReal& theUIsoParams,
                                                TColStd_SequenceOfReal& theVIsoParams);
 
+public:
+
+  //! Auxiliary structure defining 3D point on isoline.
+  struct PntOnIso
+  {
+    gp_Pnt Pnt;   //!< 3D point
+    double Param; //!< parameter along the line (for sorting)
+  };
+
+  //! Auxiliary structure defining segment of isoline.
+  struct SegOnIso
+  {
+
+    PntOnIso Pnts[2];
+
+    operator       PntOnIso*()       { return Pnts; }
+    operator const PntOnIso*() const { return Pnts; }
+
+    bool operator< (const SegOnIso& theOther) const
+    {
+      return Pnts[1].Param < theOther.Pnts[0].Param;
+    }
+
+  };
+
 private:
 
+  //! Computes isolines on surface.
+  //! @param theSurface [in] the surface
+  //! @param theDrawer [in] the display settings
+  //! @param theDeflection [in] the deflection value
+  //! @param theUIsoParams [in] the parameters of u isolines to compute
+  //! @param theVIsoParams [in] the parameters of v isolines to compute
+  //! @param theUPolylines [out] the sequence of result polylines
+  //! @param theVPolylines [out] the sequence of result polylines
+  Standard_EXPORT static void addOnSurface (const Handle(BRepAdaptor_HSurface)& theSurface,
+                                            const Handle(Prs3d_Drawer)&         theDrawer,
+                                            const Standard_Real                 theDeflection,
+                                            const TColStd_SequenceOfReal&       theUIsoParams,
+                                            const TColStd_SequenceOfReal&       theVIsoParams,
+                                            Prs3d_NListOfSequenceOfPnt&         theUPolylines,
+                                            Prs3d_NListOfSequenceOfPnt&         theVPolylines);
+
+  //! Computes isolines on triangulation.
+  //! @param thePresentation [in] the presentation
+  //! @param theTriangulation [in] the triangulation
+  //! @param theSurface [in] the definition of triangulated surface. The surface
+  //!        adapter is used to precisely evaluate isoline points using surface
+  //!        law and fit them on triangulation. If NULL is passed, the method will
+  //!        use linear interpolation of triangle node's UV coordinates to evaluate
+  //!        isoline points
+  //! @param theLocation [in] the location transformation defined for triangulation (surface)
+  //! @param theDrawer [in] the display settings
+  //! @param theUIsoParams [in] the parameters of u isolines to compute
+  //! @param theVIsoParams [in] the parameters of v isolines to compute
+  //! @param theUPolylines [out] the sequence of result polylines
+  //! @param theVPolylines [out] the sequence of result polylines
+  Standard_EXPORT static void addOnTriangulation (const Handle(Poly_Triangulation)& theTriangulation,
+                                                  const Handle(Geom_Surface)&       theSurface,
+                                                  const TopLoc_Location&            theLocation,
+                                                  const TColStd_SequenceOfReal&     theUIsoParams,
+                                                  const TColStd_SequenceOfReal&     theVIsoParams,
+                                                  Prs3d_NListOfSequenceOfPnt&       theUPolylines,
+                                                  Prs3d_NListOfSequenceOfPnt&       theVPolylines);
+
   //! Find isoline segment on a triangle.
   //! @param theSurface [in] the surface.
+  //! @param theIsU     [in] when true than U isoline is specified, V isoline otherwise
   //! @param theIsoline [in] the isoline in uv coordinates.
   //! @param theNodesXYZ [in] the XYZ coordinates of triangle nodes.
   //! @param theNodesUV [in] the UV coordinates of triangle nodes.
   //! @param theSegment [out] the XYZ points of crossed triangle's links.
+  //!                         with U cross point parameter for V isoline
+  //!                         or V parameters for U isoline (depending on theIsU)
   //! @return TRUE if the isoline passes through the triangle.
   Standard_EXPORT static Standard_Boolean findSegmentOnTriangulation (const Handle(Geom_Surface)& theSurface,
+                                                                      const bool                  theIsU,
                                                                       const gp_Lin2d&             theIsoline,
                                                                       const gp_Pnt*               theNodesXYZ,
                                                                       const gp_Pnt2d*             theNodesUV,
-                                                                      gp_Pnt*                     theSegment);
+                                                                      SegOnIso&                   theSegment);
 };
 
 #endif // _StdPrs_Isolines_H__
index 98c6bcb..534d8a2 100644 (file)
@@ -309,110 +309,96 @@ namespace
     // for computing boundaries presentation
     NCollection_List<Handle(TColgp_HArray1OfPnt)> aNodeCollection;
     Standard_Integer aNodeNumber = 0;
+    Standard_Integer aNbPolylines = 0;
 
     TopLoc_Location aTrsf;
 
     // explore all boundary edges
     TopTools_IndexedDataMapOfShapeListOfShape anEdgesMap;
-    TopExp::MapShapesAndAncestors (
-      theShape, TopAbs_EDGE, TopAbs_FACE, anEdgesMap);
-
-    Standard_Integer anEdgeIdx = 1;
-    for ( ; anEdgeIdx <= anEdgesMap.Extent (); anEdgeIdx++)
+    TopExp::MapShapesAndAncestors (theShape, TopAbs_EDGE, TopAbs_FACE, anEdgesMap);
+    for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator anEdgeIter (anEdgesMap); anEdgeIter.More(); anEdgeIter.Next())
     {
       // reject free edges
-      const TopTools_ListOfShape& aFaceList = anEdgesMap.FindFromIndex (anEdgeIdx);
-      if (aFaceList.Extent() == 0)
+      if (anEdgeIter.Value().Extent() == 0)
+      {
         continue;
+      }
 
       // take one of the shared edges and get edge triangulation
-      const TopoDS_Face& aFace  = TopoDS::Face (aFaceList.First ());
-      const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgesMap.FindKey (anEdgeIdx));
+      const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First());
+      Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf);
+      if (aTriangulation.IsNull())
+      {
+        continue;
+      }
 
-      Handle(Poly_Triangulation) aTriangulation =
-        BRep_Tool::Triangulation (aFace, aTrsf);
+      const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key());
+      Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf);
+      if (!anEdgePoly.IsNull()
+        && anEdgePoly->Nodes().Length() >= 2)
+      {
+        aNodeNumber += anEdgePoly->Nodes().Length();
+        ++aNbPolylines;
+      }
+    }
+    if (aNodeNumber == 0)
+    {
+      return;
+    }
 
-      if (aTriangulation.IsNull ())
+    // create indexed segments array to pack polylines from different edges into single array
+    const Standard_Integer aSegmentEdgeNb = (aNodeNumber - aNbPolylines) * 2;
+    Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNodeNumber, aSegmentEdgeNb);
+    for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator anEdgeIter (anEdgesMap); anEdgeIter.More(); anEdgeIter.Next())
+    {
+      if (anEdgeIter.Value().Extent() == 0)
+      {
         continue;
+      }
 
-      Handle(Poly_PolygonOnTriangulation) anEdgePoly =
-        BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf);
+      const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First());
+      Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf);
+      if (aTriangulation.IsNull())
+      {
+        continue;
+      }
 
-      if (anEdgePoly.IsNull ())
+      const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key());
+      Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf);
+      if (anEdgePoly.IsNull()
+       || anEdgePoly->Nodes().Length () < 2)
+      {
         continue;
+      }
 
       // get edge nodes indexes from face triangulation
-      const TColgp_Array1OfPnt& aTriNodes = aTriangulation->Nodes ();
-      const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes ();
-
-      if (anEdgeNodes.Length () < 2)
-        continue;
+      const TColgp_Array1OfPnt&      aTriNodes   = aTriangulation->Nodes();
+      const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes();
 
       // collect the edge nodes
-      Handle(TColgp_HArray1OfPnt) aCollected =
-        new TColgp_HArray1OfPnt (anEdgeNodes.Lower (), anEdgeNodes.Upper ());
-
-      Standard_Integer aNodeIdx = anEdgeNodes.Lower ();
-      for ( ; aNodeIdx <= anEdgeNodes.Upper (); aNodeIdx++)
+      Standard_Integer aSegmentEdge = aSegments->VertexNumber() + 1;
+      for (Standard_Integer aNodeIdx = anEdgeNodes.Lower(); aNodeIdx <= anEdgeNodes.Upper(); ++aNodeIdx)
       {
         // node index in face triangulation
-        Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx);
-
         // get node and apply location transformation to the node
+        const Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx);
         gp_Pnt aTriNode = aTriNodes.Value (aTriIndex);
-        if (!aTrsf.IsIdentity ())
+        if (!aTrsf.IsIdentity())
+        {
           aTriNode.Transform (aTrsf);
+        }
 
-        // add node to the boundary array
-        aCollected->SetValue (aNodeIdx, aTriNode);
-      }
-
-      aNodeNumber += anEdgeNodes.Length ();
-      aNodeCollection.Append (aCollected);
-    }
-
-    // check if it possible to continue building the presentation
-    if (aNodeNumber == 0)
-      return;
-
-    // allocate polyline array for presentation
-    Standard_Integer aSegmentEdgeNb = 
-      (aNodeNumber - aNodeCollection.Extent()) * 2;
-
-    Handle(Graphic3d_ArrayOfSegments) aSegments = 
-      new Graphic3d_ArrayOfSegments (aNodeNumber, aSegmentEdgeNb);
-
-    // build presentation for edge bondaries
-    NCollection_List<Handle(TColgp_HArray1OfPnt)>::Iterator 
-      aCollIt (aNodeCollection);
-
-    // the edge index is increased in each iteration step to
-    // avoid contiguous segments between different face edges.
-    for ( ; aCollIt.More(); aCollIt.Next () )
-    {
-      const Handle(TColgp_HArray1OfPnt)& aNodeArray = aCollIt.Value ();
-
-      Standard_Integer aNodeIdx = aNodeArray->Lower ();
-
-      // add first node (this node is not shared with previous segment).
-      // for each face edge, indices for sharing nodes 
-      // between segments begin from the first added node.
-      Standard_Integer aSegmentEdge = 
-        aSegments->AddVertex (aNodeArray->Value (aNodeIdx));
-
-      // add subsequent nodes and provide edge indexes for sharing
-      // the nodes between the sequential segments.
-      for ( aNodeIdx++; aNodeIdx <= aNodeArray->Upper (); aNodeIdx++ )
-      {
-        aSegments->AddVertex (aNodeArray->Value (aNodeIdx));
-        aSegments->AddEdge (  aSegmentEdge);
-        aSegments->AddEdge (++aSegmentEdge);
+        aSegments->AddVertex (aTriNode);
+        if (aNodeIdx != anEdgeNodes.Lower())
+        {
+          aSegments->AddEdge (  aSegmentEdge);
+          aSegments->AddEdge (++aSegmentEdge);
+        }
       }
     }
 
     // set up aspect and add polyline data
-    Handle(Graphic3d_AspectLine3d) aBoundaryAspect = 
-      theDrawer->FaceBoundaryAspect ()->Aspect ();
+    Handle(Graphic3d_AspectLine3d) aBoundaryAspect = theDrawer->FaceBoundaryAspect()->Aspect();
 
     Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePrs);
     aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect);
index 96bcf82..878c4c3 100644 (file)
 #include <Standard_ErrorHandler.hxx>
 #include <Prs3d_ShapeTool.hxx>
 #include <Prs3d_IsoAspect.hxx>
-#include <Prs3d_NListOfSequenceOfPnt.hxx>
-#include <Prs3d_NListIteratorOfListOfSequenceOfPnt.hxx>
 #include <Prs3d.hxx>
 #include <Poly_Connect.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
 #include <Poly_Polygon3D.hxx>
 #include <Poly_Triangulation.hxx>
 #include <Graphic3d_AspectLine3d.hxx>
-#include <Graphic3d_ArrayOfPolylines.hxx>
 #include <Graphic3d_ArrayOfSegments.hxx>
 #include <Graphic3d_ArrayOfPoints.hxx>
 #include <gp_Pnt.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <NCollection_List.hxx>
-
-namespace
-{
-  typedef NCollection_List<Handle(TColgp_HSequenceOfPnt)> ListOfSequenceOfPnt;
-}
 
 // =========================================================================
 // function : Add
@@ -78,54 +69,106 @@ void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
     }
   }
 
-  TColgp_SequenceOfPnt aShapeVertices;
-  for (aTool.InitVertex(); aTool.MoreVertex(); aTool.NextVertex())
-  {
-    aShapeVertices.Append (BRep_Tool::Pnt (aTool.GetVertex()));
-  }
-
   Standard_Real aShapeDeflection = Prs3d::GetDeflection (theShape, theDrawer);
 
-  // Draw shape elements.
-  TopTools_ListOfShape aDiscreteFaces;
-  for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
+  // Draw shape elements
   {
-    if (!aTool.HasSurface())
+    TopTools_ListOfShape aDiscreteFaces;
+    for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
     {
-      aDiscreteFaces.Append (aTool.GetFace());
+      if (!aTool.HasSurface())
+      {
+        aDiscreteFaces.Append (aTool.GetFace());
+      }
     }
+    addEdgesOnTriangulation (thePresentation, aDiscreteFaces, theDrawer->FreeBoundaryAspect());
   }
-  addEdgesOnTriangulation (thePresentation, aDiscreteFaces, theDrawer->FreeBoundaryAspect());
 
-  if (!aLWire.IsEmpty() && theDrawer->WireDraw())
+  Prs3d_NListOfSequenceOfPnt aCommonPolylines;
+  const Handle(Prs3d_LineAspect)& aWireAspect = theDrawer->WireAspect();
+
+  // Draw isolines
   {
-    addEdges (thePresentation, aLWire, theDrawer->WireAspect(), theDrawer, aShapeDeflection);
+    Prs3d_NListOfSequenceOfPnt  aUPolylines, aVPolylines;
+    Prs3d_NListOfSequenceOfPnt* aUPolylinesPtr = &aUPolylines;
+    Prs3d_NListOfSequenceOfPnt* aVPolylinesPtr = &aVPolylines;
+
+    const Handle(Prs3d_LineAspect)& anIsoAspectU = theDrawer->UIsoAspect();
+    const Handle(Prs3d_LineAspect)& anIsoAspectV = theDrawer->VIsoAspect();
+    if (anIsoAspectV->Aspect()->IsEqual (*anIsoAspectU->Aspect()))
+    {
+      aVPolylinesPtr = aUPolylinesPtr;
+    }
+    if (anIsoAspectU->Aspect()->IsEqual (*aWireAspect->Aspect()))
+    {
+      aUPolylinesPtr = &aCommonPolylines;
+    }
+    if (anIsoAspectV->Aspect()->IsEqual (*aWireAspect->Aspect()))
+    {
+      aVPolylinesPtr = &aCommonPolylines;
+    }
+
+    for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
+    {
+      if (aTool.IsPlanarFace() && !theDrawer->IsoOnPlane())
+      {
+        continue;
+      }
+
+      StdPrs_Isolines::Add (aTool.GetFace(), theDrawer, aShapeDeflection, *aUPolylinesPtr, *aVPolylinesPtr);
+    }
+
+    Prs3d::AddPrimitivesGroup (thePresentation, anIsoAspectU, aUPolylines);
+    Prs3d::AddPrimitivesGroup (thePresentation, anIsoAspectV, aVPolylines);
   }
 
-  if (!aLFree.IsEmpty() && theDrawer->FreeBoundaryDraw())
+  if (!aLWire.IsEmpty() && theDrawer->WireDraw())
   {
-    addEdges (thePresentation, aLFree, theDrawer->FreeBoundaryAspect(), theDrawer, aShapeDeflection);
+    addEdges (aLWire, theDrawer, aShapeDeflection, aCommonPolylines);
   }
 
   if (!aLUnFree.IsEmpty() && theDrawer->UnFreeBoundaryDraw())
   {
-    addEdges (thePresentation, aLUnFree, theDrawer->UnFreeBoundaryAspect(), theDrawer, aShapeDeflection);
+    const Handle(Prs3d_LineAspect)& aLineAspect = theDrawer->UnFreeBoundaryAspect();
+    if (!aLineAspect->Aspect()->IsEqual (*aWireAspect->Aspect()))
+    {
+      Prs3d_NListOfSequenceOfPnt aPolylines;
+      addEdges (aLUnFree, theDrawer, aShapeDeflection, aPolylines);
+      Prs3d::AddPrimitivesGroup (thePresentation, aLineAspect, aPolylines);
+    }
+    else
+    {
+      addEdges (aLUnFree, theDrawer, aShapeDeflection, aCommonPolylines);
+    }
   }
 
-  if (!aShapeVertices.IsEmpty())
+  if (!aLFree.IsEmpty() && theDrawer->FreeBoundaryDraw())
   {
-    addVertices (thePresentation, aShapeVertices, theDrawer->PointAspect());
+    const Handle(Prs3d_LineAspect)& aLineAspect = theDrawer->FreeBoundaryAspect();
+    if (!aLineAspect->Aspect()->IsEqual (*aWireAspect->Aspect()))
+    {
+      Prs3d_NListOfSequenceOfPnt aPolylines;
+      addEdges (aLFree, theDrawer, aShapeDeflection, aPolylines);
+      Prs3d::AddPrimitivesGroup (thePresentation, aLineAspect, aPolylines);
+    }
+    else
+    {
+      addEdges (aLFree, theDrawer, aShapeDeflection, aCommonPolylines);
+    }
   }
 
-  // Draw isolines.
-  for (aTool.InitFace(); aTool.MoreFace(); aTool.NextFace())
+  Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->WireAspect(), aCommonPolylines);
+
   {
-    if (aTool.IsPlanarFace() && !theDrawer->IsoOnPlane())
+    TColgp_SequenceOfPnt aShapeVertices;
+    for (aTool.InitVertex(); aTool.MoreVertex(); aTool.NextVertex())
     {
-      continue;
+      aShapeVertices.Append (BRep_Tool::Pnt (aTool.GetVertex()));
+    }
+    if (!aShapeVertices.IsEmpty())
+    {
+      addVertices (thePresentation, aShapeVertices, theDrawer->PointAspect());
     }
-
-    StdPrs_Isolines::Add (thePresentation, aTool.GetFace(), theDrawer, aShapeDeflection);
   }
 }
 
@@ -133,14 +176,11 @@ void StdPrs_WFShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
 // function : AddEdges
 // purpose  :
 // =========================================================================
-void StdPrs_WFShape::addEdges (const Handle (Prs3d_Presentation)& thePresentation,
-                               const TopTools_ListOfShape&        theEdges,
-                               const Handle (Prs3d_LineAspect)&   theAspect,
-                               const Handle (Prs3d_Drawer)&       theDrawer,
-                               const Standard_Real                theShapeDeflection)
+void StdPrs_WFShape::addEdges (const TopTools_ListOfShape&  theEdges,
+                               const Handle (Prs3d_Drawer)& theDrawer,
+                               const Standard_Real          theShapeDeflection,
+                               Prs3d_NListOfSequenceOfPnt&  thePolylines)
 {
-  ListOfSequenceOfPnt aPointsOfEdges;
-
   TopTools_ListIteratorOfListOfShape anEdgesIter;
   for (anEdgesIter.Initialize (theEdges); anEdgesIter.More(); anEdgesIter.Next())
   {
@@ -204,7 +244,7 @@ void StdPrs_WFShape::addEdges (const Handle (Prs3d_Presentation)& thePresentatio
     {
       // Default presentation for edges without triangulation.
       BRepAdaptor_Curve aCurve (anEdge);
-      StdPrs_DeflectionCurve::Add (thePresentation,
+      StdPrs_DeflectionCurve::Add (Handle(Prs3d_Presentation)(),
                                    aCurve,
                                    theShapeDeflection,
                                    theDrawer,
@@ -214,40 +254,9 @@ void StdPrs_WFShape::addEdges (const Handle (Prs3d_Presentation)& thePresentatio
 
     if (!aPoints->IsEmpty())
     {
-      aPointsOfEdges.Append (aPoints);
-    }
-  }
-
-  Standard_Integer aNbBounds   = aPointsOfEdges.Size();
-  Standard_Integer aNbVertices = 0;
-
-  ListOfSequenceOfPnt::Iterator aPolylineIter;
-  for (aPolylineIter.Initialize (aPointsOfEdges); aPolylineIter.More(); aPolylineIter.Next())
-  {
-    aNbVertices += aPolylineIter.Value()->Length();
-  }
-
-  if (aNbBounds < 1 || aNbVertices < 2)
-  {
-    return;
-  }
-
-  // Construct array of primitives.
-  Handle(Graphic3d_ArrayOfPolylines) aPrimitiveArray = new Graphic3d_ArrayOfPolylines (aNbVertices, aNbBounds);
-  for (aPolylineIter.Initialize (aPointsOfEdges); aPolylineIter.More(); aPolylineIter.Next())
-  {
-    const Handle(TColgp_HSequenceOfPnt)& aPoints = aPolylineIter.Value();
-    aPrimitiveArray->AddBound (aPoints->Length());
-    for (Standard_Integer anI = 1; anI <= aPoints->Length(); ++anI)
-    {
-      aPrimitiveArray->AddVertex (aPoints->Value (anI));
+      thePolylines.Append (aPoints);
     }
   }
-
-  // Add array of primitives to presentation.
-  Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePresentation);
-  aGroup->SetPrimitivesAspect (theAspect->Aspect());
-  aGroup->AddPrimitiveArray (aPrimitiveArray);
 }
 
 // =========================================================================
@@ -342,11 +351,9 @@ void StdPrs_WFShape::addEdgesOnTriangulation (const Handle(Prs3d_Presentation)&
   }
 
   Standard_Integer aNbVertices = aSurfPoints.Length();
-  Standard_Integer aNbBounds   = aNbVertices / 2;
-  Handle(Graphic3d_ArrayOfSegments) aSurfArray = new Graphic3d_ArrayOfSegments (aNbVertices, aNbBounds);
+  Handle(Graphic3d_ArrayOfSegments) aSurfArray = new Graphic3d_ArrayOfSegments (aNbVertices);
   for (Standard_Integer anI = 1; anI <= aNbVertices; anI += 2)
   {
-    aSurfArray->AddBound (2);
     aSurfArray->AddVertex (aSurfPoints.Value (anI));
     aSurfArray->AddVertex (aSurfPoints.Value (anI + 1));
   }
index 0db67cf..8d27dbe 100755 (executable)
@@ -19,6 +19,7 @@
 #include <Prs3d_Presentation.hxx>
 #include <Prs3d_PointAspect.hxx>
 #include <Prs3d_LineAspect.hxx>
+#include <Prs3d_NListOfSequenceOfPnt.hxx>
 #include <TColgp_SequenceOfPnt.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopTools_ListOfShape.hxx>
@@ -39,16 +40,13 @@ public:
 private:
 
   //! Compute edge presentations for a shape.
-  //! @param thePresentation [in] the presentation.
   //! @param theEdges [in] the list of edges.
-  //! @param theAspect [in] the edge drawing aspect.
   //! @param theDrawer [in] the drawer settings.
   //! @param theShapeDeflection [in] the deflection for the wireframe shape.
-  static void addEdges (const Handle (Prs3d_Presentation)& thePresentation,
-                        const TopTools_ListOfShape&        theEdges,
-                        const Handle (Prs3d_LineAspect)&   theAspect,
-                        const Handle (Prs3d_Drawer)&       theDrawer,
-                        const Standard_Real                theShapeDeflection);
+  static void addEdges (const TopTools_ListOfShape& theEdges,
+                        const Handle(Prs3d_Drawer)& theDrawer,
+                        const Standard_Real         theShapeDeflection,
+                        Prs3d_NListOfSequenceOfPnt& thePolylines);
 
   //! Compute free and boundary edges on a triangulation of a face.
   //! @param thePresentation [in] the presentation.