-// File: StdPrs_ShadedShape.cxx
-// Created: 23 Sep 1993
-// Author: Jean-Louis FRENKEL
-// Copyright: OPEN CASCADE 2012
+// Created on: 1993-09-23
+// Created by: Jean-Louis FRENKEL
+// Copyright (c) 1993-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
#include <StdPrs_ShadedShape.hxx>
#include <Bnd_Box.hxx>
-#include <BRep_Builder.hxx>
-#include <BRepBndLib.hxx>
-#include <BRepMesh_DiscretFactory.hxx>
-#include <BRepMesh_DiscretRoot.hxx>
#include <BRepTools.hxx>
+#include <BRepBndLib.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_ArrayOfTriangles.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <Graphic3d_Group.hxx>
#include <gp_Dir.hxx>
#include <gp_Vec.hxx>
#include <gp_Pnt.hxx>
+#include <NCollection_List.hxx>
#include <Precision.hxx>
#include <Prs3d_Drawer.hxx>
+#include <Prs3d_IsoAspect.hxx>
+#include <Prs3d_LineAspect.hxx>
#include <Prs3d_Presentation.hxx>
#include <Prs3d_ShadingAspect.hxx>
#include <Poly_Connect.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
-#include <StdPrs_ToolShadedShape.hxx>
+#include <StdPrs_ToolTriangulatedShape.hxx>
#include <StdPrs_WFShape.hxx>
-#include <TopoDS_Shape.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
#include <TColgp_Array1OfDir.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
-#include <TopoDS_Compound.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-#include <TopExp.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <NCollection_List.hxx>
-#include <Graphic3d_ArrayOfSegments.hxx>
-#include <Prs3d_LineAspect.hxx>
-#include <TColgp_HArray1OfPnt.hxx>
-#include <Aspect_PolygonOffsetMode.hxx>
-
-#define MAX2(X, Y) (Abs(X) > Abs(Y) ? Abs(X) : Abs(Y))
-#define MAX3(X, Y, Z) (MAX2 (MAX2 (X, Y), Z))
namespace
{
- // =======================================================================
- // function : GetDeflection
- // purpose :
- // =======================================================================
- static Standard_Real GetDeflection (const TopoDS_Shape& theShape,
- const Handle(Prs3d_Drawer)& theDrawer)
+
+ //! Computes wireframe presentation for free wires and vertices
+ void wireframeFromShape (const Handle (Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle (Prs3d_Drawer)& theDrawer)
+ {
+ Standard_Boolean aDrawAllVerticesFlag = (theDrawer->VertexDrawMode() == Prs3d_VDM_All);
+
+ if (!aDrawAllVerticesFlag && theShape.ShapeType() != TopAbs_COMPOUND)
+ {
+ return;
+ }
+
+ TopExp_Explorer aShapeIter (theShape, TopAbs_FACE);
+ if (!aShapeIter.More())
+ {
+ // compound contains no shaded elements at all
+ StdPrs_WFShape::Add (thePrs, theShape, theDrawer);
+ return;
+ }
+
+ // We have to create a compound and collect all subshapes not drawn by the shading algo.
+ // This includes:
+ // - isolated edges
+ // - isolated vertices, if aDrawAllVerticesFlag == Standard_False
+ // - all shape's vertices, if aDrawAllVerticesFlag == Standard_True
+ TopoDS_Compound aCompoundWF;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound (aCompoundWF);
+ Standard_Boolean hasElement = Standard_False;
+
+ // isolated edges
+ for (aShapeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); aShapeIter.More(); aShapeIter.Next())
+ {
+ hasElement = Standard_True;
+ aBuilder.Add (aCompoundWF, aShapeIter.Current());
+ }
+ // isolated or all vertices
+ aShapeIter.Init (theShape, TopAbs_VERTEX, aDrawAllVerticesFlag ? TopAbs_SHAPE : TopAbs_EDGE);
+ for (; aShapeIter.More(); aShapeIter.Next())
+ {
+ hasElement = Standard_True;
+ aBuilder.Add (aCompoundWF, aShapeIter.Current());
+ }
+ if (hasElement)
+ {
+ StdPrs_WFShape::Add (thePrs, aCompoundWF, theDrawer);
+ }
+ }
+
+ //! Computes special wireframe presentation for faces without triangulation.
+ void wireframeNoTriangFacesFromShape (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer)
{
- Standard_Real aDeflection = theDrawer->MaximalChordialDeviation();
- if (theDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE)
+ TopoDS_Compound aCompoundWF;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound (aCompoundWF);
+ TopLoc_Location aLoc;
+ Standard_Boolean hasElement = Standard_False;
+
+ for (TopExp_Explorer aShapeIter(theShape, TopAbs_FACE); aShapeIter.More(); aShapeIter.Next())
{
- Bnd_Box aBndBox;
- BRepBndLib::Add (theShape, aBndBox, Standard_False);
- if (!aBndBox.IsVoid())
+ const TopoDS_Face& aFace = TopoDS::Face (aShapeIter.Current());
+ const Handle(Poly_Triangulation) aTriang = BRep_Tool::Triangulation (aFace, aLoc);
+ if (aTriang.IsNull())
{
- Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
- aBndBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
- aDeflection = MAX3 (aXmax-aXmin, aYmax-aYmin, aZmax-aZmin) * theDrawer->DeviationCoefficient() * 4.0;
+ hasElement = Standard_True;
+ aBuilder.Add (aCompoundWF, aFace);
}
}
- return aDeflection;
+
+ if (hasElement)
+ {
+ Standard_Integer aPrevUIsoNb = theDrawer->UIsoAspect()->Number();
+ Standard_Integer aPrevVIsoNb = theDrawer->VIsoAspect()->Number();
+ theDrawer->UIsoAspect()->SetNumber (5);
+ theDrawer->VIsoAspect()->SetNumber (5);
+
+ StdPrs_WFShape::Add (thePrs, aCompoundWF, theDrawer);
+
+ theDrawer->UIsoAspect()->SetNumber (aPrevUIsoNb);
+ theDrawer->VIsoAspect()->SetNumber (aPrevVIsoNb);
+ }
}
- // =======================================================================
- // function : ShadeFromShape
- // purpose :
- // =======================================================================
- static Standard_Boolean ShadeFromShape (const TopoDS_Shape& theShape,
- const Handle (Prs3d_Presentation)& thePresentation,
- const Handle (Prs3d_Drawer)& theDrawer,
- const Standard_Boolean theHasTexels,
- const gp_Pnt2d& theUVOrigin,
- const gp_Pnt2d& theUVRepeat,
- const gp_Pnt2d& theUVScale)
+ //! Gets triangulation of every face of shape and fills output array of triangles
+ static Handle(Graphic3d_ArrayOfTriangles) fillTriangles (const TopoDS_Shape& theShape,
+ const Standard_Boolean theHasTexels,
+ const gp_Pnt2d& theUVOrigin,
+ const gp_Pnt2d& theUVRepeat,
+ const gp_Pnt2d& theUVScale)
{
- StdPrs_ToolShadedShape SST;
- Handle(Poly_Triangulation) T;
+ Handle(Poly_Triangulation) aT;
TopLoc_Location aLoc;
- gp_Pnt p;
- Standard_Integer decal;
- Standard_Integer t[3], n[3];
- Standard_Integer nbTriangles = 0, nbVertices = 0;
- Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0);
+ gp_Pnt aPoint;
+ Standard_Integer aNbTriangles = 0;
+ Standard_Integer aNbVertices = 0;
- // precision for compare square distances
- const double aPreci = Precision::SquareConfusion();
+ // Precision for compare square distances
+ const Standard_Real aPreci = Precision::SquareConfusion();
- if (!theDrawer->ShadingAspectGlobal())
+ TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
+ for (; aFaceIt.More(); aFaceIt.Next())
{
- Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect();
- if (StdPrs_ToolShadedShape::IsClosed (theShape))
+ const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+ aT = BRep_Tool::Triangulation (aFace, aLoc);
+ if (!aT.IsNull())
{
- anAsp->SuppressBackFace();
+ aNbTriangles += aT->NbTriangles();
+ aNbVertices += aT->NbNodes();
}
- else
- {
- anAsp->AllowBackFace();
- }
- Prs3d_Root::CurrentGroup (thePresentation)->SetGroupPrimitivesAspect (anAsp);
+ }
+ if (aNbVertices < 3 || aNbTriangles <= 0)
+ {
+ return Handle(Graphic3d_ArrayOfTriangles)();
}
- for (SST.Init (theShape); SST.MoreFace(); SST.NextFace())
+ Handle(Graphic3d_ArrayOfTriangles) anArray = new Graphic3d_ArrayOfTriangles (aNbVertices, 3 * aNbTriangles,
+ Standard_True, Standard_False, theHasTexels);
+ Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0);
+ for (aFaceIt.Init (theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
- const TopoDS_Face& aFace = SST.CurrentFace();
- T = SST.Triangulation (aFace, aLoc);
- if (!T.IsNull())
+ const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
+ aT = BRep_Tool::Triangulation (aFace, aLoc);
+ if (aT.IsNull())
{
- nbTriangles += T->NbTriangles();
- nbVertices += T->NbNodes();
+ continue;
}
- }
+ const gp_Trsf& aTrsf = aLoc.Transformation();
- if (nbVertices > 2 && nbTriangles > 0)
- {
- Handle(Graphic3d_ArrayOfTriangles) aPArray
- = new Graphic3d_ArrayOfTriangles (nbVertices, 3 * nbTriangles,
- Standard_True, Standard_False, theHasTexels, Standard_True);
- for (SST.Init (theShape); SST.MoreFace(); SST.NextFace())
+ // Determinant of transform matrix less then 0 means that mirror transform applied.
+ Standard_Boolean isMirrored = aTrsf.VectorialPart().Determinant() < 0;
+
+ Poly_Connect aPolyConnect (aT);
+ // Extracts vertices & normals from nodes
+ const TColgp_Array1OfPnt& aNodes = aT->Nodes();
+ const TColgp_Array1OfPnt2d& aUVNodes = aT->UVNodes();
+ TColgp_Array1OfDir aNormals (aNodes.Lower(), aNodes.Upper());
+ StdPrs_ToolTriangulatedShape::Normal (aFace, aPolyConnect, aNormals);
+
+ if (theHasTexels)
+ {
+ BRepTools::UVBounds (aFace, aUmin, aUmax, aVmin, aVmax);
+ dUmax = (aUmax - aUmin);
+ dVmax = (aVmax - aVmin);
+ }
+
+ const Standard_Integer aDecal = anArray->VertexNumber();
+ for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
{
- const TopoDS_Face& aFace = SST.CurrentFace();
- T = SST.Triangulation (aFace, aLoc);
- if (T.IsNull())
+ aPoint = aNodes (aNodeIter);
+ if (!aLoc.IsIdentity())
{
- continue;
+ aPoint.Transform (aTrsf);
+
+ aNormals (aNodeIter) = aNormals (aNodeIter).Transformed (aTrsf);
+ }
+
+ if (theHasTexels && aUVNodes.Upper() == aNodes.Upper())
+ {
+ const gp_Pnt2d aTexel = gp_Pnt2d ((-theUVOrigin.X() + (theUVRepeat.X() * (aUVNodes (aNodeIter).X() - aUmin)) / dUmax) / theUVScale.X(),
+ (-theUVOrigin.Y() + (theUVRepeat.Y() * (aUVNodes (aNodeIter).Y() - aVmin)) / dVmax) / theUVScale.Y());
+ anArray->AddVertex (aPoint, aNormals (aNodeIter), aTexel);
}
- const gp_Trsf& aTrsf = aLoc.Transformation();
- Poly_Connect pc (T);
- // Extracts vertices & normals from nodes
- const TColgp_Array1OfPnt& aNodes = T->Nodes();
- const TColgp_Array1OfPnt2d& aUVNodes = T->UVNodes();
- TColgp_Array1OfDir aNormals (aNodes.Lower(), aNodes.Upper());
- SST.Normal (aFace, pc, aNormals);
-
- if (theHasTexels)
+ else
{
- BRepTools::UVBounds (aFace, aUmin, aUmax, aVmin, aVmax);
- dUmax = (aUmax - aUmin);
- dVmax = (aVmax - aVmin);
+ anArray->AddVertex (aPoint, aNormals (aNodeIter));
}
+ }
- decal = aPArray->VertexNumber();
- for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+ // Fill array with vertex and edge visibility info
+ const Poly_Array1OfTriangle& aTriangles = aT->Triangles();
+ Standard_Integer anIndex[3];
+ for (Standard_Integer aTriIter = 1; aTriIter <= aT->NbTriangles(); ++aTriIter)
+ {
+ if ((aFace.Orientation() == TopAbs_REVERSED) ^ isMirrored)
+ {
+ aTriangles (aTriIter).Get (anIndex[0], anIndex[2], anIndex[1]);
+ }
+ else
{
- p = aNodes (aNodeIter);
- if (!aLoc.IsIdentity())
- {
- p.Transform (aTrsf);
- aNormals (aNodeIter).Transform (aTrsf);
- }
-
- if (theHasTexels && aUVNodes.Upper() == aNodes.Upper())
- {
- const gp_Pnt2d aTexel = gp_Pnt2d ((-theUVOrigin.X() + (theUVRepeat.X() * (aUVNodes (aNodeIter).X() - aUmin)) / dUmax) / theUVScale.X(),
- (-theUVOrigin.Y() + (theUVRepeat.Y() * (aUVNodes (aNodeIter).Y() - aVmin)) / dVmax) / theUVScale.Y());
- aPArray->AddVertex (p, aNormals (aNodeIter), aTexel);
- }
- else
- {
- aPArray->AddVertex (p, aNormals (aNodeIter));
- }
+ aTriangles (aTriIter).Get (anIndex[0], anIndex[1], anIndex[2]);
}
- // Fill parray with vertex and edge visibillity info
- const Poly_Array1OfTriangle& aTriangles = T->Triangles();
- for (Standard_Integer aTriIter = 1; aTriIter <= T->NbTriangles(); ++aTriIter)
+ gp_Pnt aP1 = aNodes (anIndex[0]);
+ gp_Pnt aP2 = aNodes (anIndex[1]);
+ gp_Pnt aP3 = aNodes (anIndex[2]);
+
+ gp_Vec aV1 (aP1, aP2);
+ if (aV1.SquareMagnitude() <= aPreci)
+ {
+ continue;
+ }
+ gp_Vec aV2 (aP2, aP3);
+ if (aV2.SquareMagnitude() <= aPreci)
+ {
+ continue;
+ }
+ gp_Vec aV3 (aP3, aP1);
+ if (aV3.SquareMagnitude() <= aPreci)
+ {
+ continue;
+ }
+ aV1.Normalize();
+ aV2.Normalize();
+ aV1.Cross (aV2);
+ if (aV1.SquareMagnitude() > aPreci)
{
- pc.Triangles (aTriIter, t[0], t[1], t[2]);
- if (SST.Orientation (aFace) == TopAbs_REVERSED)
- aTriangles (aTriIter).Get (n[0], n[2], n[1]);
- else
- aTriangles (aTriIter).Get (n[0], n[1], n[2]);
-
- gp_Pnt P1 = aNodes (n[0]);
- gp_Pnt P2 = aNodes (n[1]);
- gp_Pnt P3 = aNodes (n[2]);
-
- gp_Vec V1 (P1, P2);
- if (V1.SquareMagnitude() <= aPreci)
- {
- continue;
- }
- gp_Vec V2 (P2, P3);
- if (V2.SquareMagnitude() <= aPreci)
- {
- continue;
- }
- gp_Vec V3 (P3, P1);
- if (V3.SquareMagnitude() <= aPreci)
- {
- continue;
- }
- V1.Normalize();
- V2.Normalize();
- V1.Cross (V2);
- if (V1.SquareMagnitude() > aPreci)
- {
- aPArray->AddEdge (n[0] + decal, t[0] == 0);
- aPArray->AddEdge (n[1] + decal, t[1] == 0);
- aPArray->AddEdge (n[2] + decal, t[2] == 0);
- }
+ anArray->AddEdge (anIndex[0] + aDecal);
+ anArray->AddEdge (anIndex[1] + aDecal);
+ anArray->AddEdge (anIndex[2] + aDecal);
}
}
- Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPArray);
}
+ return anArray;
+ }
+
+ //! Prepare shaded presentation for specified shape
+ static Standard_Boolean shadeFromShape (const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Handle(Prs3d_Drawer)& theDrawer,
+ const Standard_Boolean theHasTexels,
+ const gp_Pnt2d& theUVOrigin,
+ const gp_Pnt2d& theUVRepeat,
+ const gp_Pnt2d& theUVScale,
+ const bool theIsClosed)
+ {
+ Handle(Graphic3d_ArrayOfTriangles) aPArray = fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale);
+ if (aPArray.IsNull())
+ {
+ return Standard_False;
+ }
+
+ Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePrs);
+ aGroup->SetClosed (theIsClosed);
+ aGroup->SetGroupPrimitivesAspect (theDrawer->ShadingAspect()->Aspect());
+ aGroup->AddPrimitiveArray (aPArray);
return Standard_True;
}
- // =======================================================================
- // function : ComputeFaceBoundaries
- // purpose : Compute boundary presentation for faces of the shape.
- // =======================================================================
- static void ComputeFaceBoundaries (const TopoDS_Shape& theShape,
- const Handle (Prs3d_Presentation)& thePresentation,
- const Handle (Prs3d_Drawer)& theDrawer)
+ //! Compute boundary presentation for faces of the shape.
+ static Handle(Graphic3d_ArrayOfSegments) fillFaceBoundaries (const TopoDS_Shape& theShape)
{
// collection of all triangulation nodes on edges
// 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 Handle(Graphic3d_ArrayOfSegments)();
+ }
- 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);
+ aSegments->AddVertex (aTriNode);
+ if (aNodeIdx != anEdgeNodes.Lower())
+ {
+ aSegments->AddEdge ( aSegmentEdge);
+ aSegments->AddEdge (++aSegmentEdge);
+ }
}
-
- aNodeNumber += anEdgeNodes.Length ();
- aNodeCollection.Append (aCollected);
}
+ return aSegments;
+ }
- // 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);
+} // anonymous namespace
- // build presentation for edge bondaries
- NCollection_List<Handle(TColgp_HArray1OfPnt)>::Iterator
- aCollIt (aNodeCollection);
+// =======================================================================
+// function : ExploreSolids
+// purpose :
+// =======================================================================
+void StdPrs_ShadedShape::ExploreSolids (const TopoDS_Shape& theShape,
+ const BRep_Builder& theBuilder,
+ TopoDS_Compound& theClosed,
+ TopoDS_Compound& theOpened,
+ const Standard_Boolean theIgnore1DSubShape)
+{
+ if (theShape.IsNull())
+ {
+ return;
+ }
- // the edge index is increased in each iteration step to
- // avoid contiguous segments between different face edges.
- for ( ; aCollIt.More(); aCollIt.Next () )
+ switch (theShape.ShapeType())
+ {
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID:
{
- 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++ )
+ for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
+ {
+ ExploreSolids (anIter.Value(), theBuilder, theClosed, theOpened, theIgnore1DSubShape);
+ }
+ return;
+ }
+ case TopAbs_SOLID:
+ {
+ for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
{
- aSegments->AddVertex (aNodeArray->Value (aNodeIdx));
- aSegments->AddEdge ( aSegmentEdge);
- aSegments->AddEdge (++aSegmentEdge);
+ const TopoDS_Shape& aSubShape = anIter.Value();
+ const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL &&
+ BRep_Tool::IsClosed (aSubShape) &&
+ StdPrs_ToolTriangulatedShape::IsTriangulated (aSubShape);
+ theBuilder.Add (isClosed ? theClosed : theOpened, aSubShape);
}
+ return;
}
-
- // set up aspect and add polyline data
- Handle(Graphic3d_AspectLine3d) aBoundaryAspect =
- theDrawer->FaceBoundaryAspect ()->Aspect ();
-
- Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePresentation);
- aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect);
- aPrsGrp->AddPrimitiveArray (aSegments);
+ case TopAbs_SHELL:
+ case TopAbs_FACE:
+ {
+ theBuilder.Add (theOpened, theShape);
+ return;
+ }
+ case TopAbs_WIRE:
+ case TopAbs_EDGE:
+ case TopAbs_VERTEX:
+ {
+ if (!theIgnore1DSubShape)
+ {
+ theBuilder.Add (theOpened, theShape);
+ }
+ return;
+ }
+ case TopAbs_SHAPE:
+ default:
+ return;
}
-};
+}
// =======================================================================
// function : Add
// purpose :
// =======================================================================
-void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePresentation,
- const TopoDS_Shape& theShape,
- const Handle(Prs3d_Drawer)& theDrawer)
+void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer,
+ const StdPrs_Volume theVolume)
{
gp_Pnt2d aDummy;
- StdPrs_ShadedShape::Add (thePresentation, theShape, theDrawer,
- Standard_False, aDummy, aDummy, aDummy);
+ StdPrs_ShadedShape::Add (thePrs, theShape, theDrawer,
+ Standard_False, aDummy, aDummy, aDummy, theVolume);
}
// =======================================================================
// function : Add
// purpose :
// =======================================================================
-void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePresentation,
+void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs,
const TopoDS_Shape& theShape,
const Handle (Prs3d_Drawer)& theDrawer,
const Standard_Boolean theHasTexels,
const gp_Pnt2d& theUVOrigin,
const gp_Pnt2d& theUVRepeat,
- const gp_Pnt2d& theUVScale)
+ const gp_Pnt2d& theUVScale,
+ const StdPrs_Volume theVolume)
{
if (theShape.IsNull())
{
return;
}
- if (theShape.ShapeType() == TopAbs_COMPOUND)
+ // add wireframe presentation for isolated edges and vertices
+ wireframeFromShape (thePrs, theShape, theDrawer);
+
+ // Use automatic re-triangulation with deflection-check logic only if this feature is enable
+ if (theDrawer->IsAutoTriangulation())
{
- TopExp_Explorer ex;
- ex.Init (theShape, TopAbs_FACE);
- if (ex.More())
- {
- TopoDS_Compound CO;
- BRep_Builder aBuilder;
- aBuilder.MakeCompound (CO);
- Standard_Boolean hasElement = Standard_False;
+ // Triangulation completeness is important for "open-closed" analysis - perform tessellation beforehand
+ StdPrs_ToolTriangulatedShape::Tessellate (theShape, theDrawer);
+ }
- // il faut presenter les edges isoles.
- for (ex.Init (theShape, TopAbs_EDGE, TopAbs_FACE); ex.More(); ex.Next())
- {
- hasElement = Standard_True;
- aBuilder.Add (CO, ex.Current());
- }
- // il faut presenter les vertex isoles.
- for (ex.Init (theShape, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next())
- {
- hasElement = Standard_True;
- aBuilder.Add (CO, ex.Current());
- }
- if (hasElement)
- {
- StdPrs_WFShape::Add (thePresentation, CO, theDrawer);
- }
+ // add special wireframe presentation for faces without triangulation
+ wireframeNoTriangFacesFromShape (thePrs, theShape, theDrawer);
+
+ // The shape types listed below need advanced analysis as potentially containing
+ // both closed and open parts. Solids are also included, because they might
+ // contain non-manifold parts inside (internal open shells)
+ if ((theShape.ShapeType() == TopAbs_COMPOUND
+ || theShape.ShapeType() == TopAbs_COMPSOLID
+ || theShape.ShapeType() == TopAbs_SOLID)
+ && theVolume == StdPrs_Volume_Autodetection)
+ {
+ // collect two compounds: for opened and closed (solid) sub-shapes
+ TopoDS_Compound anOpened, aClosed;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound (aClosed);
+ aBuilder.MakeCompound (anOpened);
+ ExploreSolids (theShape, aBuilder, aClosed, anOpened, Standard_True);
+
+ TopoDS_Iterator aShapeIter (aClosed);
+ if (aShapeIter.More())
+ {
+ shadeFromShape (aClosed, thePrs, theDrawer,
+ theHasTexels, theUVOrigin, theUVRepeat, theUVScale, true);
}
- else
+
+ aShapeIter.Initialize (anOpened);
+ if (aShapeIter.More())
{
- StdPrs_WFShape::Add (thePresentation, theShape, theDrawer);
+ shadeFromShape (anOpened, thePrs, theDrawer,
+ theHasTexels, theUVOrigin, theUVRepeat, theUVScale, false);
}
}
- Standard_Real aDeflection = GetDeflection (theShape, theDrawer);
-
- // Check if it is possible to avoid unnecessary recomputation
- // of shape triangulation
- if (!BRepTools::Triangulation (theShape, aDeflection))
+ else
{
- BRepTools::Clean (theShape);
-
- // retrieve meshing tool from Factory
- Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (theShape,
- aDeflection,
- theDrawer->HLRAngle());
- if (!aMeshAlgo.IsNull())
- aMeshAlgo->Perform();
+ // if the shape type is not compound, composolid or solid, use autodetection back-facing filled
+ shadeFromShape (theShape, thePrs, theDrawer,
+ theHasTexels, theUVOrigin, theUVRepeat, theUVScale,
+ theVolume == StdPrs_Volume_Closed);
}
- ShadeFromShape (theShape, thePresentation, theDrawer,
- theHasTexels, theUVOrigin, theUVRepeat, theUVScale);
-
- if (theDrawer->IsFaceBoundaryDraw ())
+ if (theDrawer->FaceBoundaryDraw())
{
- ComputeFaceBoundaries (theShape, thePresentation, theDrawer);
+ Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape);
+ if (!aBndSegments.IsNull())
+ {
+ Handle(Graphic3d_AspectLine3d) aBoundaryAspect = theDrawer->FaceBoundaryAspect()->Aspect();
+ Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePrs);
+ aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect);
+ aPrsGrp->AddPrimitiveArray (aBndSegments);
+ }
}
}
+
+// =======================================================================
+// function : FillTriangles
+// purpose :
+// =======================================================================
+Handle(Graphic3d_ArrayOfTriangles) StdPrs_ShadedShape::FillTriangles (const TopoDS_Shape& theShape,
+ const Standard_Boolean theHasTexels,
+ const gp_Pnt2d& theUVOrigin,
+ const gp_Pnt2d& theUVRepeat,
+ const gp_Pnt2d& theUVScale)
+{
+ return fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale);
+}
+
+// =======================================================================
+// function : FillFaceBoundaries
+// purpose :
+// =======================================================================
+Handle(Graphic3d_ArrayOfSegments) StdPrs_ShadedShape::FillFaceBoundaries (const TopoDS_Shape& theShape)
+{
+ return fillFaceBoundaries (theShape);
+}
+
+// =======================================================================
+// function : AddWireframeForFreeElements
+// purpose :
+// =======================================================================
+void StdPrs_ShadedShape::AddWireframeForFreeElements (const Handle (Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle (Prs3d_Drawer)& theDrawer)
+{
+ wireframeFromShape (thePrs, theShape, theDrawer);
+}
+
+// =======================================================================
+// function : AddWireframeForFacesWithoutTriangles
+// purpose :
+// =======================================================================
+void StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer)
+{
+ wireframeNoTriangFacesFromShape (thePrs, theShape, theDrawer);
+}