// Created on: 1995-03-06 // Created by: Laurent PAINNOT // Copyright (c) 1995-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. #ifndef _Poly_Triangulation_HeaderFile #define _Poly_Triangulation_HeaderFile #include "Bnd_Box.hxx" #include "Poly_Triangle.hxx" #include "NCollection_Array1.hxx" #include "NCollection_HArray1.hxx" #include "Poly_ArrayOfNodes.hxx" #include "Poly_ArrayOfUVNodes.hxx" #include "Poly_MeshPurpose.hxx" #include "gp_Pnt.hxx" #include "gp_Pnt2d.hxx" #include "Standard_ShortReal.hxx" #include #include class OSD_FileSystem; class Poly_Triangulation; class Poly_TriangulationParameters; //! Provides a triangulation for a surface, a set of surfaces, or more generally a shape. //! //! A triangulation consists of an approximate representation of the actual shape, //! using a collection of points and triangles. //! The points are located on the surface. //! The edges of the triangles connect adjacent points with a straight line that approximates the //! true curve on the surface. //! //! A triangulation comprises: //! - A table of 3D nodes (3D points on the surface). //! - A table of triangles. //! Each triangle (Poly_Triangle object) comprises a triplet of indices in the table of 3D nodes //! specific to the triangulation. //! - An optional table of 2D nodes (2D points), parallel to the table of 3D nodes. //! 2D point are the (u, v) parameters of the corresponding 3D point on the surface approximated //! by the triangulation. //! - An optional table of 3D vectors, parallel to the table of 3D nodes, defining normals to the //! surface at specified 3D point. //! - An optional deflection, which maximizes the distance from a point on the surface to the //! corresponding point on its approximate triangulation. //! //! In many cases, algorithms do not need to work with the exact representation of a surface. //! A triangular representation induces simpler and more robust adjusting, faster performances, and //! the results are as good. class Poly_Triangulation : public Standard_Transient { DEFINE_STANDARD_RTTIEXT(Poly_Triangulation, Standard_Transient) public: //! 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 specified number of nodes and triangles. //! @param[in] theNbNodes number of nodes to allocate //! @param[in] theNbTriangles number of triangles to allocate //! @param[in] theHasUVNodes indicates whether 2D nodes will be associated with 3D ones, //! (i.e. to enable a 2D representation) //! @param[in] theHasNormals indicates whether normals will be given and associated with nodes Standard_EXPORT Poly_Triangulation(const int theNbNodes, const int theNbTriangles, const bool theHasUVNodes, const bool theHasNormals = false); //! Constructs a triangulation from a set of triangles. The //! triangulation is initialized with 3D points from Nodes and triangles //! from Triangles. Standard_EXPORT Poly_Triangulation(const NCollection_Array1& Nodes, const NCollection_Array1& Triangles); //! Constructs a triangulation from a set of triangles. The //! triangulation is initialized with 3D points from Nodes, 2D points from //! UVNodes and triangles from Triangles, where //! coordinates of a 2D point from UVNodes are the //! (u, v) parameters of the corresponding 3D point //! from Nodes on the surface approximated by the //! constructed triangulation. Standard_EXPORT Poly_Triangulation(const NCollection_Array1& Nodes, const NCollection_Array1& UVNodes, const NCollection_Array1& Triangles); //! Destructor Standard_EXPORT ~Poly_Triangulation() override; //! Creates full copy of current triangulation Standard_EXPORT virtual occ::handle Copy() const; //! Copy constructor for triangulation. Standard_EXPORT Poly_Triangulation(const occ::handle& theTriangulation); //! Returns the deflection of this triangulation. double Deflection() const { return myDeflection; } //! Sets the deflection of this triangulation to theDeflection. //! See more on deflection in Polygon2D void Deflection(const double theDeflection) { myDeflection = theDeflection; } //! Returns initial set of parameters used to generate this triangulation. const occ::handle& Parameters() const { return myParams; } //! Updates initial set of parameters used to generate this triangulation. void Parameters(const occ::handle& theParams) { myParams = theParams; } //! Clears internal arrays of nodes and all attributes. Standard_EXPORT virtual void Clear(); //! Returns TRUE if triangulation has some geometry. virtual bool HasGeometry() const { return !myNodes.IsEmpty() && !myTriangles.IsEmpty(); } //! Returns the number of nodes for this triangulation. int NbNodes() const { return myNodes.Length(); } //! Returns the number of triangles for this triangulation. int NbTriangles() const { return myTriangles.Length(); } //! Returns true if 2D nodes are associated with 3D nodes for this triangulation. bool HasUVNodes() const { return !myUVNodes.IsEmpty(); } //! Returns true if nodal normals are defined. bool HasNormals() const { return !myNormals.IsEmpty(); } //! Returns a node at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @return 3D point coordinates gp_Pnt Node(int theIndex) const { return myNodes.Value(theIndex - 1); } //! Sets a node coordinates. //! @param[in] theIndex node index within [1, NbNodes()] range //! @param[in] thePnt 3D point coordinates void SetNode(int theIndex, const gp_Pnt& thePnt) { myNodes.SetValue(theIndex - 1, thePnt); } //! Returns UV-node at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @return 2D point defining UV coordinates gp_Pnt2d UVNode(int theIndex) const { return myUVNodes.Value(theIndex - 1); } //! Sets an UV-node coordinates. //! @param[in] theIndex node index within [1, NbNodes()] range //! @param[in] thePnt UV coordinates void SetUVNode(int theIndex, const gp_Pnt2d& thePnt) { myUVNodes.SetValue(theIndex - 1, thePnt); } //! Returns triangle at the given index. //! @param[in] theIndex triangle index within [1, NbTriangles()] range //! @return triangle node indices, with each node defined within [1, NbNodes()] range const Poly_Triangle& Triangle(int theIndex) const { return myTriangles.Value(theIndex); } //! Sets a triangle. //! @param[in] theIndex triangle index within [1, NbTriangles()] range //! @param[in] theTriangle triangle node indices, with each node defined within [1, NbNodes()] //! range void SetTriangle(int theIndex, const Poly_Triangle& theTriangle) { myTriangles.SetValue(theIndex, theTriangle); } //! Returns normal at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @return normalized 3D vector defining a surface normal gp_Dir Normal(int theIndex) const { const NCollection_Vec3& aNorm = myNormals.Value(theIndex - 1); return gp_Dir(aNorm.x(), aNorm.y(), aNorm.z()); } //! Returns normal at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @param[out] theVec3 3D vector defining a surface normal void Normal(int theIndex, NCollection_Vec3& theVec3) const { theVec3 = myNormals.Value(theIndex - 1); } //! Changes normal at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @param[in] theVec3 normalized 3D vector defining a surface normal void SetNormal(const int theIndex, const NCollection_Vec3& theNormal) { myNormals.SetValue(theIndex - 1, theNormal); } //! Changes normal at the given index. //! @param[in] theIndex node index within [1, NbNodes()] range //! @param[in] theNormal normalized 3D vector defining a surface normal void SetNormal(const int theIndex, const gp_Dir& theNormal) { SetNormal( theIndex, NCollection_Vec3(float(theNormal.X()), float(theNormal.Y()), float(theNormal.Z()))); } //! Returns mesh purpose bits. Poly_MeshPurpose MeshPurpose() const { return myPurpose; } //! Sets mesh purpose bits. void SetMeshPurpose(const Poly_MeshPurpose thePurpose) { myPurpose = thePurpose; } //! 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. bool HasCachedMinMax() const { return myCachedMinMax.load(std::memory_order_acquire) != nullptr; } //! 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[in][out] theBox bounding box to extend by this triangulation //! @param[in] theTrsf optional transformation //! @param[in] theIsAccurate 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 bool 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, int theDepth = -1) const; public: //! Returns TRUE if node positions are defined with double precision; TRUE by default. bool IsDoublePrecision() const { return myNodes.IsDoublePrecision(); } //! Set if node positions should be defined with double or single precision for 3D and UV nodes. //! Raises exception if data was already allocated. Standard_EXPORT void SetDoublePrecision(bool theIsDouble); //! Method resizing internal arrays of nodes (synchronously for all attributes). //! @param[in] theNbNodes new number of nodes //! @param[in] theToCopyOld copy old nodes into the new array Standard_EXPORT void ResizeNodes(int theNbNodes, bool theToCopyOld); //! Method resizing an internal array of triangles. //! @param[in] theNbTriangles new number of triangles //! @param[in] theToCopyOld copy old triangles into the new array Standard_EXPORT void ResizeTriangles(int theNbTriangles, bool theToCopyOld); //! If an array for UV coordinates is not allocated yet, do it now. Standard_EXPORT void AddUVNodes(); //! Deallocates the UV nodes array. Standard_EXPORT void RemoveUVNodes(); //! If an array for normals is not allocated yet, do it now. Standard_EXPORT void AddNormals(); //! Deallocates the normals array. Standard_EXPORT void RemoveNormals(); //! Compute smooth normals by averaging triangle normals. Standard_EXPORT void ComputeNormals(); public: //! Returns the table of 3D points for read-only access or NULL if nodes array is undefined. //! Poly_Triangulation::Node() should be used instead when possible. //! Returned object should not be used after Poly_Triangulation destruction. Standard_EXPORT occ::handle> MapNodeArray() const; //! Returns the triangle array for read-only access or NULL if triangle array is undefined. //! Poly_Triangulation::Triangle() should be used instead when possible. //! Returned object should not be used after Poly_Triangulation destruction. Standard_EXPORT occ::handle> MapTriangleArray() const; //! Returns the table of 2D nodes for read-only access or NULL if UV nodes array is undefined. //! Poly_Triangulation::UVNode() should be used instead when possible. //! Returned object should not be used after Poly_Triangulation destruction. Standard_EXPORT occ::handle> MapUVNodeArray() const; //! Returns the table of per-vertex normals for read-only access or NULL if normals array is //! undefined. Poly_Triangulation::Normal() should be used instead when possible. Returned object //! should not be used after Poly_Triangulation destruction. Standard_EXPORT occ::handle> MapNormalArray() const; public: //! Returns an internal array of triangles. //! Triangle()/SetTriangle() should be used instead in portable code. NCollection_Array1& InternalTriangles() { return myTriangles; } //! Returns an internal array of nodes. //! Node()/SetNode() should be used instead in portable code. Poly_ArrayOfNodes& InternalNodes() { return myNodes; } //! Returns an internal array of UV nodes. //! UBNode()/SetUVNode() should be used instead in portable code. Poly_ArrayOfUVNodes& InternalUVNodes() { return myUVNodes; } //! Return an internal array of normals. //! Normal()/SetNormal() should be used instead in portable code. NCollection_Array1>& InternalNormals() { return myNormals; } Standard_DEPRECATED("Deprecated method, SetNormal() should be used instead") Standard_EXPORT void SetNormals(const occ::handle>& theNormals); Standard_DEPRECATED("Deprecated method, Triangle() should be used instead") const NCollection_Array1& Triangles() const { return myTriangles; } Standard_DEPRECATED("Deprecated method, SetTriangle() should be used instead") NCollection_Array1& ChangeTriangles() { return myTriangles; } Standard_DEPRECATED("Deprecated method, SetTriangle() should be used instead") Poly_Triangle& ChangeTriangle(const int theIndex) { return myTriangles.ChangeValue(theIndex); } public: //! @name late-load deferred data interface //! Returns number of deferred nodes that can be loaded using LoadDeferredData(). //! Note: this is estimated values, which might be different from actually loaded values. //! Always check triangulation size of actually loaded data in code to avoid out-of-range issues. virtual int NbDeferredNodes() const { return 0; } //! Returns number of deferred triangles that can be loaded using LoadDeferredData(). //! Note: this is estimated values, which might be different from actually loaded values //! Always check triangulation size of actually loaded data in code to avoid out-of-range issues. virtual int NbDeferredTriangles() const { return 0; } //! Returns TRUE if there is some triangulation data that can be loaded using LoadDeferredData(). virtual bool HasDeferredData() const { return NbDeferredTriangles() > 0; } //! Loads triangulation data into itself //! from some deferred storage using specified shared input file system. Standard_EXPORT virtual bool LoadDeferredData( const occ::handle& theFileSystem = occ::handle()); //! Loads triangulation data into new Poly_Triangulation object //! from some deferred storage using specified shared input file system. Standard_EXPORT virtual occ::handle DetachedLoadDeferredData( const occ::handle& theFileSystem = occ::handle()) const; //! Releases triangulation data if it has connected deferred storage. Standard_EXPORT virtual bool UnloadDeferredData(); protected: //! Creates new triangulation object (can be inheritor of Poly_Triangulation). virtual occ::handle createNewEntity() const { return new Poly_Triangulation(); } //! Load triangulation data from deferred storage using specified shared input file system. virtual bool loadDeferredData(const occ::handle& theFileSystem, const occ::handle& theDestTriangulation) const { (void)theFileSystem; (void)theDestTriangulation; return false; } protected: //! Clears cached min - max range saved previously. Standard_EXPORT void unsetCachedMinMax(); //! Calculates bounding box of nodal data. //! @param[in] theTrsf optional transformation. Standard_EXPORT virtual Bnd_Box computeBoundingBox(const gp_Trsf& theTrsf) const; protected: mutable std::atomic myCachedMinMax{nullptr}; mutable std::shared_mutex myCachedMinMaxMutex; double myDeflection; Poly_ArrayOfNodes myNodes; NCollection_Array1 myTriangles; Poly_ArrayOfUVNodes myUVNodes; NCollection_Array1> myNormals; Poly_MeshPurpose myPurpose; occ::handle myParams; }; #endif // _Poly_Triangulation_HeaderFile