const TopoDS_Face& F = TopoDS::Face(ex.Current());
const Handle(Poly_Triangulation)& T = BRep_Tool::Triangulation(F, l);
const Handle(Geom_Surface)& GS = BRep_Tool::Surface (F, aDummyLoc);
- if ((useTriangulation || GS.IsNull()) && !T.IsNull())
+ if ((useTriangulation || GS.IsNull()) && !T.IsNull() && T->MinMax (B, l))
{
- nbNodes = T->NbNodes();
- const TColgp_Array1OfPnt& Nodes = T->Nodes();
- for (i = 1; i <= nbNodes; i++) {
- if (l.IsIdentity()) B.Add(Nodes(i));
- else B.Add(Nodes(i).Transformed(l));
- }
// B.Enlarge(T->Deflection());
- B.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
+ B.Enlarge (T->Deflection() + BRep_Tool::Tolerance (F));
} else
{
if (!GS.IsNull()) {
{
const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
- if (!P3d.IsNull())
+ if (!P3d.IsNull() && P3d->NbNodes() > 0)
{
const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
nbNodes = P3d->NbNodes();
for (i = 1; i <= nbNodes; i++)
{
- if (l.IsIdentity()) B.Add(Nodes(i));
- else B.Add(Nodes(i).Transformed(l));
+ if (l.IsIdentity()) B.Add(Nodes[i]);
+ else B.Add(Nodes[i].Transformed(l));
}
// B.Enlarge(P3d->Deflection());
B.Enlarge(P3d->Deflection() + BRep_Tool::Tolerance(E));
else
{
BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
- if (useTriangulation && !Poly.IsNull())
+ if (useTriangulation && !Poly.IsNull() && !T.IsNull() && T->NbNodes() > 0)
{
const TColStd_Array1OfInteger& Indices = Poly->Nodes();
const TColgp_Array1OfPnt& Nodes = T->Nodes();
nbNodes = Indices.Length();
- for (i = 1; i <= nbNodes; i++)
+ if (l.IsIdentity())
{
- if (l.IsIdentity()) B.Add(Nodes(Indices(i)));
- else B.Add(Nodes(Indices(i)).Transformed(l));
+ for (i = 1; i <= nbNodes; i++)
+ {
+ B.Add(Nodes(Indices[i]));
+ }
+ }
+ else
+ {
+ for (i = 1; i <= nbNodes; i++)
+ {
+ B.Add(Nodes(Indices[i]).Transformed(l));
+ }
}
// B.Enlarge(T->Deflection());
B.Enlarge(Poly->Deflection() + BRep_Tool::Tolerance(E));
const TopoDS_Face& F = TopoDS::Face(ex.Current());
T = BRep_Tool::Triangulation(F, l);
Bnd_Box aLocBox;
- if (useTriangulation && !T.IsNull())
+ if (useTriangulation && !T.IsNull() && T->MinMax (aLocBox, l))
{
- nbNodes = T->NbNodes();
- const TColgp_Array1OfPnt& Nodes = T->Nodes();
- for (i = 1; i <= nbNodes; i++) {
- if (l.IsIdentity()) aLocBox.Add(Nodes(i));
- else aLocBox.Add(Nodes(i).Transformed(l));
- }
// B.Enlarge(T->Deflection());
aLocBox.Enlarge(T->Deflection() + BRep_Tool::Tolerance(F));
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
aLocBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
- }
+ }
else
{
const Handle(Geom_Surface)& GS = BRep_Tool::Surface(F, l);
const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
Bnd_Box aLocBox;
Handle(Poly_Polygon3D) P3d = BRep_Tool::Polygon3D(E, l);
- if (useTriangulation && (!P3d.IsNull()))
+ if (useTriangulation && !P3d.IsNull() && P3d->NbNodes() > 0)
{
const TColgp_Array1OfPnt& Nodes = P3d->Nodes();
nbNodes = P3d->NbNodes();
for (i = 1; i <= nbNodes; i++)
{
- if (l.IsIdentity()) aLocBox.Add(Nodes(i));
- else aLocBox.Add(Nodes(i).Transformed(l));
+ if (l.IsIdentity()) aLocBox.Add(Nodes[i]);
+ else aLocBox.Add(Nodes[i].Transformed(l));
}
Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
aLocBox.Enlarge(P3d->Deflection() + Tol);
else
{
BRep_Tool::PolygonOnTriangulation(E, Poly, T, l);
- if (useTriangulation && !Poly.IsNull())
+ if (useTriangulation && !Poly.IsNull() && !T.IsNull() && T->NbNodes() > 0)
{
const TColStd_Array1OfInteger& Indices = Poly->Nodes();
const TColgp_Array1OfPnt& Nodes = T->Nodes();
nbNodes = Indices.Length();
for (i = 1; i <= nbNodes; i++)
{
- if (l.IsIdentity()) aLocBox.Add(Nodes(Indices(i)));
- else aLocBox.Add(Nodes(Indices(i)).Transformed(l));
+ if (l.IsIdentity()) aLocBox.Add(Nodes(Indices[i]));
+ else aLocBox.Add(Nodes(Indices[i]).Transformed(l));
}
Standard_Real Tol = useShapeTolerance? BRep_Tool::Tolerance(E) : 0.;
aLocBox.Enlarge(Poly->Deflection() + Tol);
{
if (thePts)
{
- const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr(i) :
- aNodesArr(i).Transformed(aLoc);
+ const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr[i] :
+ aNodesArr[i].Transformed(aLoc);
(*thePts)(aRetVal) = aP;
}
{
if (thePts)
{
- const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr(i) :
- aNodesArr(i).Transformed(aLoc);
+ const gp_Pnt aP = aLoc.IsIdentity() ? aNodesArr[i] :
+ aNodesArr[i].Transformed(aLoc);
(*thePts)(aRetVal) = aP;
}
TopLoc_Location aLocDummy;
const Handle(Poly_Triangulation)& aTri =
BRep_Tool::Triangulation(TopoDS::Face(aF), aLocDummy);
- if (!aTri.IsNull())
+ if (!aTri.IsNull() && aTri->NbNodes() > 0)
{
xyz = aTri->Node(1).XYZ();
if (!aLocDummy.IsIdentity())
NoSurf = Standard_True;
}
const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
- if (aTri.IsNull())
+ if (aTri.IsNull() || aTri->NbNodes() == 0 || aTri->NbTriangles() == 0)
{
NoTri = Standard_True;
}
NoSurf = Standard_True;
}
const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation(F, aLocDummy);
- if (aTri.IsNull())
+ if (aTri.IsNull() || aTri->NbNodes() == 0 || aTri->NbTriangles() == 0)
{
NoTri = Standard_True;
}
const TopLoc_Location& theLoc,
const TopAbs_Orientation theOri)
{
+ if (theMesh.IsNull() || theMesh->NbNodes() == 0 || theMesh->NbTriangles() == 0)
+ {
+ return;
+ }
if (theLoc.IsIdentity())
{
Perform(theMesh->Nodes(), theMesh->Triangles(), theOri);
const Poly_Array1OfTriangle& theTriangles,
const TopAbs_Orientation theOri)
{
+ if (theNodes.IsEmpty() || theTriangles.IsEmpty())
+ {
+ return;
+ }
//
// Gauss points for barycentriche coordinates
static const Standard_Real GPtsWg[] =
IMPLEMENT_STANDARD_RTTIEXT (Poly_Triangulation, Standard_Transient)
+//=======================================================================
+//function : Poly_Triangulation
+//purpose :
+//=======================================================================
+Poly_Triangulation::Poly_Triangulation()
+: myCachedMinMax (NULL),
+ myDeflection (0)
+{
+}
+
//=======================================================================
//function : Poly_Triangulation
//purpose :
Poly_Triangulation::Poly_Triangulation(const Standard_Integer theNbNodes,
const Standard_Integer theNbTriangles,
const Standard_Boolean theHasUVNodes)
-: myDeflection(0),
- myNodes (1, theNbNodes),
- myTriangles (1, theNbTriangles)
+: myCachedMinMax (NULL),
+ myDeflection (0),
+ myNodes (1, theNbNodes),
+ myTriangles (1, theNbTriangles)
{
if (theHasUVNodes) myUVNodes = new TColgp_HArray1OfPnt2d(1, theNbNodes);
}
//=======================================================================
Poly_Triangulation::Poly_Triangulation(const TColgp_Array1OfPnt& theNodes,
const Poly_Array1OfTriangle& theTriangles)
-: myDeflection(0),
- myNodes (1, theNodes.Length()),
- myTriangles (1, theTriangles.Length())
+: myCachedMinMax (NULL),
+ myDeflection (0),
+ myNodes (1, theNodes.Length()),
+ myTriangles (1, theTriangles.Length())
{
myNodes = theNodes;
myTriangles = theTriangles;
Poly_Triangulation::Poly_Triangulation(const TColgp_Array1OfPnt& theNodes,
const TColgp_Array1OfPnt2d& theUVNodes,
const Poly_Array1OfTriangle& theTriangles)
-: myDeflection(0),
- myNodes (1, theNodes.Length()),
- myTriangles (1, theTriangles.Length())
+: myCachedMinMax (NULL),
+ myDeflection (0),
+ myNodes (1, theNodes.Length()),
+ myTriangles (1, theTriangles.Length())
{
myNodes = theNodes;
myTriangles = theTriangles;
myUVNodes->ChangeArray1() = theUVNodes;
}
+//=======================================================================
+//function : ~Poly_Triangulation
+//purpose :
+//=======================================================================
+Poly_Triangulation::~Poly_Triangulation()
+{
+ delete myCachedMinMax;
+}
+
//=======================================================================
//function : Copy
//purpose :
Handle(Poly_Triangulation) Poly_Triangulation::Copy() const
{
- Handle(Poly_Triangulation) aCopy;
- if (HasUVNodes())
- aCopy = new Poly_Triangulation(Nodes(), UVNodes(), Triangles());
- else
- aCopy = new Poly_Triangulation(Nodes(), Triangles());
- aCopy->Deflection(myDeflection);
- if (HasNormals())
- aCopy->myNormals = new TShort_HArray1OfShortReal(myNormals->Array1());
-
- return aCopy;
+ return new Poly_Triangulation (this);
}
//=======================================================================
//=======================================================================
Poly_Triangulation::Poly_Triangulation (const Handle(Poly_Triangulation)& theTriangulation)
-: myDeflection ( theTriangulation->myDeflection ),
+: myCachedMinMax(NULL),
+ myDeflection(theTriangulation->myDeflection),
myNodes(theTriangulation->Nodes()),
myTriangles(theTriangulation->Triangles())
{
+ SetCachedMinMax (theTriangulation->CachedMinMax());
if (theTriangulation->HasUVNodes())
{
myUVNodes = new TColgp_HArray1OfPnt2d(theTriangulation->myUVNodes->Array1());
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNormals->Size())
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTriangles.Size())
}
+
+// =======================================================================
+// function : CachedMinMax
+// purpose :
+// =======================================================================
+const Bnd_Box& Poly_Triangulation::CachedMinMax() const
+{
+ static const Bnd_Box anEmptyBox;
+ return (myCachedMinMax == NULL) ? anEmptyBox : *myCachedMinMax;
+}
+
+// =======================================================================
+// function : SetCachedMinMax
+// purpose :
+// =======================================================================
+void Poly_Triangulation::SetCachedMinMax (const Bnd_Box& theBox)
+{
+ if (theBox.IsVoid())
+ {
+ unsetCachedMinMax();
+ return;
+ }
+ if (myCachedMinMax == NULL)
+ {
+ myCachedMinMax = new Bnd_Box();
+ }
+ *myCachedMinMax = theBox;
+}
+
+// =======================================================================
+// function : unsetCachedMinMax
+// purpose :
+// =======================================================================
+void Poly_Triangulation::unsetCachedMinMax()
+{
+ if (myCachedMinMax != NULL)
+ {
+ delete myCachedMinMax;
+ myCachedMinMax = NULL;
+ }
+}
+
+// =======================================================================
+// function : MinMax
+// purpose :
+// =======================================================================
+Standard_Boolean Poly_Triangulation::MinMax (Bnd_Box& theBox, const gp_Trsf& theTrsf, const bool theIsAccurate) const
+{
+ Bnd_Box aBox;
+ if (HasCachedMinMax() &&
+ (!HasGeometry() || !theIsAccurate ||
+ theTrsf.Form() == gp_Identity || theTrsf.Form() == gp_Translation ||
+ theTrsf.Form() == gp_PntMirror || theTrsf.Form() == gp_Scale))
+ {
+ aBox = myCachedMinMax->Transformed (theTrsf);
+ }
+ else
+ {
+ aBox = computeBoundingBox (theTrsf);
+ }
+ if (aBox.IsVoid())
+ {
+ return Standard_False;
+ }
+ theBox.Add (aBox);
+ return Standard_True;
+}
+
+// =======================================================================
+// function : computeBoundingBox
+// purpose :
+// =======================================================================
+Bnd_Box Poly_Triangulation::computeBoundingBox (const gp_Trsf& theTrsf) const
+{
+ Bnd_Box aBox;
+ if (theTrsf.Form() == gp_Identity)
+ {
+ for (Standard_Integer aNodeIdx = 1; aNodeIdx <= NbNodes(); aNodeIdx++)
+ {
+ aBox.Add (myNodes[aNodeIdx]);
+ }
+ }
+ else
+ {
+ for (Standard_Integer aNodeIdx = 1; aNodeIdx <= NbNodes(); aNodeIdx++)
+ {
+ aBox.Add (myNodes[aNodeIdx].Transformed (theTrsf));
+ }
+ }
+ return aBox;
+}
#ifndef _Poly_Triangulation_HeaderFile
#define _Poly_Triangulation_HeaderFile
+#include <Bnd_Box.hxx>
#include <Standard.hxx>
#include <Standard_DefineHandle.hxx>
#include <Standard_Real.hxx>
DEFINE_STANDARD_RTTIEXT(Poly_Triangulation, Standard_Transient)
+ //! Constructs an empty triangulation.
+ Standard_EXPORT Poly_Triangulation();
+
//! Constructs a triangulation from a set of triangles. The
//! triangulation is initialized without a triangle or a node, but capable of
//! containing nbNodes nodes, and nbTriangles
//! constructed triangulation.
Standard_EXPORT Poly_Triangulation(const TColgp_Array1OfPnt& Nodes, const TColgp_Array1OfPnt2d& UVNodes, const Poly_Array1OfTriangle& Triangles);
+ //! Destructor
+ Standard_EXPORT virtual ~Poly_Triangulation();
+
//! Creates full copy of current triangulation
Standard_EXPORT virtual Handle(Poly_Triangulation) Copy() const;
//! Deallocates the UV nodes.
Standard_EXPORT void RemoveUVNodes();
+ //! Returns TRUE if triangulation has some geometry.
+ virtual Standard_Boolean HasGeometry() const { return !myNodes.IsEmpty() && !myTriangles.IsEmpty(); }
+
//! Returns the number of nodes for this triangulation.
Standard_Integer NbNodes() const { return myNodes.Length(); }
Standard_EXPORT void SetNormal (const Standard_Integer theIndex,
const gp_Dir& theNormal);
+ //! Returns cached min - max range of triangulation data,
+ //! which is VOID by default (e.g, no cached information).
+ Standard_EXPORT const Bnd_Box& CachedMinMax() const;
+
+ //! Sets a cached min - max range of this triangulation.
+ //! The bounding box should exactly match actual range of triangulation data
+ //! without a gap or transformation, or otherwise undefined behavior will be observed.
+ //! Passing a VOID range invalidates the cache.
+ Standard_EXPORT void SetCachedMinMax (const Bnd_Box& theBox);
+
+ //! Returns TRUE if there is some cached min - max range of this triangulation.
+ Standard_EXPORT Standard_Boolean HasCachedMinMax() const { return myCachedMinMax != NULL; }
+
+ //! Updates cached min - max range of this triangulation with bounding box of nodal data.
+ void UpdateCachedMinMax()
+ {
+ Bnd_Box aBox;
+ MinMax (aBox, gp_Trsf(), true);
+ SetCachedMinMax (aBox);
+ }
+
+ //! Extends the passed box with bounding box of this triangulation.
+ //! Uses cached min - max range when available and:
+ //! - input transformation theTrsf has no rotation part;
+ //! - theIsAccurate is set to FALSE;
+ //! - no triangulation data available (e.g. it is deferred and not loaded).
+ //! @param theBox [in] [out] bounding box to extend by this triangulation
+ //! @param theTrsf [in] optional transformation
+ //! @param theIsAccurate [in] when FALSE, allows using a cached min - max range of this triangulation
+ //! even for non-identity transformation.
+ //! @return FALSE if there is no any data to extend the passed box (no both triangulation and cached min - max range).
+ Standard_EXPORT Standard_Boolean MinMax (Bnd_Box& theBox, const gp_Trsf& theTrsf, const bool theIsAccurate = false) const;
+
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
protected:
+ //! Clears cached min - max range saved previously.
+ Standard_EXPORT void unsetCachedMinMax();
+
+ //! Calculates bounding box of nodal data.
+ //! @param theTrsf [in] optional transformation.
+ Standard_EXPORT virtual Bnd_Box computeBoundingBox (const gp_Trsf& theTrsf) const;
+
+protected:
+
+ Bnd_Box* myCachedMinMax;
Standard_Real myDeflection;
TColgp_Array1OfPnt myNodes;
Handle(TColgp_HArray1OfPnt2d) myUVNodes;
isValidMinMax = false;
break;
}
- aMinPnt.SetCoord (anIter + 1, aMinVal.GetDouble());
- aMinPnt.SetCoord (anIter + 1, aMaxVal.GetDouble());
+ double aMinDVal = aMinVal.GetDouble();
+ double aMaxDVal = aMaxVal.GetDouble();
+ if (aMinDVal > aMaxDVal)
+ {
+ reportGltfWarning ("Accessor '" + theName + "' defines invalid min/max value.");
+ isValidMinMax = false;
+ break;
+ }
+ aMinPnt.SetCoord (anIter + 1, aMinDVal);
+ aMaxPnt.SetCoord (anIter + 1, aMaxDVal);
}
if (isValidMinMax)
{
aBox.Add (aMinPnt);
aBox.Add (aMaxPnt);
- theMeshData->SetBoundingBox (aBox);
+ theMeshData->SetCachedMinMax (aBox);
}
}
}
// =======================================================================
RWGltf_GltfLatePrimitiveArray::RWGltf_GltfLatePrimitiveArray (const TCollection_AsciiString& theId,
const TCollection_AsciiString& theName)
-: Poly_Triangulation (3, 1, false),
+: Poly_Triangulation(),
myId (theId),
myName (theName),
myPrimMode (RWGltf_GltfPrimitiveMode_UNKNOWN)
{
- SetBoundingBox (Bnd_Box());
}
// =======================================================================
return myData.ChangeLast();
}
}
-
-// =======================================================================
-// function : SetBoundingBox
-// purpose :
-// =======================================================================
-void RWGltf_GltfLatePrimitiveArray::SetBoundingBox (const Bnd_Box& theBox)
-{
- myBox = theBox;
-
- if (theBox.IsVoid())
- {
- Poly_Triangulation::myNodes = TColgp_Array1OfPnt();
- Poly_Triangulation::myTriangles = Poly_Array1OfTriangle();
- return;
- }
-
- // define 8 nodes so that AABB will be huge enough to include mesh even with transformation applied
- Poly_Triangulation::myNodes.Resize (1, 8, false);
- const gp_Pnt aMin = theBox.CornerMin();
- const gp_Pnt aMax = theBox.CornerMax();
- Poly_Triangulation::ChangeNode(1).SetCoord(aMin.X(), aMin.Y(), aMin.Z());
- Poly_Triangulation::ChangeNode(2).SetCoord(aMax.X(), aMax.Y(), aMax.Z());
- Poly_Triangulation::ChangeNode(3).SetCoord(aMin.X(), aMin.Y(), aMax.Z());
- Poly_Triangulation::ChangeNode(4).SetCoord(aMin.X(), aMax.Y(), aMax.Z());
- Poly_Triangulation::ChangeNode(5).SetCoord(aMax.X(), aMax.Y(), aMin.Z());
- Poly_Triangulation::ChangeNode(6).SetCoord(aMax.X(), aMin.Y(), aMin.Z());
- Poly_Triangulation::ChangeNode(7).SetCoord(aMin.X(), aMax.Y(), aMin.Z());
- Poly_Triangulation::ChangeNode(8).SetCoord(aMax.X(), aMin.Y(), aMax.Z());
-
- Poly_Triangulation::myTriangles.Resize (1, 1, false);
- Poly_Triangulation::ChangeTriangle (1).Set (1, 2, 1);
- //Poly_Triangulation::myTriangles = Poly_Array1OfTriangle();
-}
#ifndef _RWGltf_GltfLatePrimitiveArray_HeaderFile
#define _RWGltf_GltfLatePrimitiveArray_HeaderFile
-#include <Bnd_Box.hxx>
#include <NCollection_Sequence.hxx>
#include <Poly_Triangulation.hxx>
#include <RWGltf_GltfPrimArrayData.hxx>
//! Add primitive array data element.
Standard_EXPORT RWGltf_GltfPrimArrayData& AddPrimArrayData (RWGltf_GltfArrayType theType);
- //! Return bounding box defined within glTF file, or VOID if not specified.
- const Bnd_Box& BoundingBox() const { return myBox; }
-
- //! This method sets input bounding box and assigns a FAKE data to underlying Poly_Triangulation
- //! as Min/Max corners of bounding box, so that standard tools like BRepBndLib::Add()
- //! can be used transparently for computing bounding box of this face.
- Standard_EXPORT void SetBoundingBox (const Bnd_Box& theBox);
-
protected:
NCollection_Sequence<RWGltf_GltfPrimArrayData> myData;
Handle(RWGltf_MaterialMetallicRoughness) myMaterialPbr; //!< PBR material
Handle(RWGltf_MaterialCommon) myMaterialCommon; //!< common (obsolete) material
- Bnd_Box myBox; //!< bounding box
TCollection_AsciiString myId; //!< entity id
TCollection_AsciiString myName; //!< entity name
RWGltf_GltfPrimitiveMode myPrimMode; //!< type of primitive array