From 51171fd93248832aeaea4afc9a9438f86130376d Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Jul 2016 15:31:45 +0200 Subject: [PATCH] + implement modifier class to allow limited access to internals of mesh kernel class --- src/Mod/Mesh/App/Core/Algorithm.cpp | 39 ++++---- src/Mod/Mesh/App/Core/Degeneration.cpp | 122 ++++++++++++++----------- src/Mod/Mesh/App/Core/Elements.cpp | 4 +- src/Mod/Mesh/App/Core/Elements.h | 54 ++++++++++- src/Mod/Mesh/App/Core/MeshKernel.cpp | 7 ++ src/Mod/Mesh/App/Core/MeshKernel.h | 25 +++-- 6 files changed, 168 insertions(+), 83 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index f822dccfe..4da823560 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -43,29 +43,26 @@ using Base::BoundBox2D; using Base::Polygon2D; -bool MeshAlgorithm::IsVertexVisible (const Base::Vector3f &rcVertex, const Base::Vector3f &rcView, const MeshFacetGrid &rclGrid ) const +bool MeshAlgorithm::IsVertexVisible (const Base::Vector3f &rcVertex, const Base::Vector3f &rcView, const MeshFacetGrid &rclGrid) const { - Base::Vector3f cDirection = rcVertex-rcView; - float fDistance = cDirection.Length(); - Base::Vector3f cIntsct; unsigned long uInd; + Base::Vector3f cDirection = rcVertex - rcView; + float fDistance = cDirection.Length(); + Base::Vector3f cIntsct; unsigned long uInd; - // search for the nearest facet to rcView in direction to rcVertex - if ( NearestFacetOnRay( rcView, cDirection, /*1.2f*fDistance,*/ rclGrid, cIntsct, uInd) ) - { - // now check if the facet overlays the point - float fLen = Base::Distance( rcView, cIntsct ); - if ( fLen < fDistance ) - { - // is it the same point? - if ( Base::Distance(rcVertex, cIntsct) > 0.001f ) - { - // ok facet overlays the vertex - return false; - } + // search for the nearest facet to rcView in direction to rcVertex + if (NearestFacetOnRay(rcView, cDirection, /*1.2f*fDistance,*/ rclGrid, cIntsct, uInd)) { + // now check if the facet overlays the point + float fLen = Base::Distance(rcView, cIntsct); + if (fLen < fDistance) { + // is it the same point? + if (Base::Distance(rcVertex, cIntsct) > 0.001f) { + // ok facet overlays the vertex + return false; + } + } } - } - return true; // no facet between the two points + return true; // no facet between the two points } bool MeshAlgorithm::NearestFacetOnRay (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, Base::Vector3f &rclRes, @@ -226,10 +223,10 @@ bool MeshAlgorithm::FirstFacetToVertex(const Base::Vector3f &rPt, float fMaxDist } else { // if not then check the distance to the border of the triangle - Base::Vector3f res = rPt; + Base::Vector3f res; float fDist; unsigned short uSide; - cFacet.ProjectPointToPlane(res); + cFacet.ProjectPointToPlane(rPt, res); cFacet.NearestEdgeToPoint(res, fDist, uSide); if (fDist < fEps) { found = true; diff --git a/src/Mod/Mesh/App/Core/Degeneration.cpp b/src/Mod/Mesh/App/Core/Degeneration.cpp index 7e9c45fcd..5b1c47902 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.cpp +++ b/src/Mod/Mesh/App/Core/Degeneration.cpp @@ -516,8 +516,8 @@ unsigned long MeshFixDegeneratedFacets::RemoveEdgeTooSmall (float fMinEdgeLength { unsigned long ulCtLastLoop, ulCtFacets = _rclMesh.CountFacets(); - MeshFacetArray &rclFAry = _rclMesh._aclFacetArray; - MeshPointArray &rclPAry = _rclMesh._aclPointArray; + const MeshFacetArray &rclFAry = _rclMesh.GetFacets(); + const MeshPointArray &rclPAry = _rclMesh.GetPoints(); MeshFacetArray::_TConstIterator f_beg = rclFAry.begin(); // repeat until no facet van be removed @@ -891,11 +891,11 @@ bool MeshEvalFoldOversOnSurface::Evaluate() return this->indices.empty(); } - -// ---------------------------------------------------------------- - -bool MeshEvalBorderFacet::Evaluate() -{ + +// ---------------------------------------------------------------- + +bool MeshEvalBorderFacet::Evaluate() +{ const MeshCore::MeshFacetArray& facets = _rclMesh.GetFacets(); MeshCore::MeshFacetArray::_TConstIterator f_it, f_beg = facets.begin(), f_end = facets.end(); @@ -915,87 +915,107 @@ bool MeshEvalBorderFacet::Evaluate() if (ok) _facets.push_back(f_it-f_beg); } - - return _facets.empty(); -} + + return _facets.empty(); +} // ---------------------------------------------------------------------- bool MeshEvalRangeFacet::Evaluate() { - const MeshFacetArray& rFaces = _rclMesh.GetFacets(); - unsigned long ulCtFacets = rFaces.size(); + const MeshFacetArray& rFaces = _rclMesh.GetFacets(); + unsigned long ulCtFacets = rFaces.size(); - for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) { - for ( int i = 0; i < 3; i++ ) { - if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) { - return false; - } + for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it) { + for (int i = 0; i < 3; i++) { + if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) { + return false; + } + } } - } - return true; + return true; } std::vector MeshEvalRangeFacet::GetIndices() const { - std::vector aInds; - const MeshFacetArray& rFaces = _rclMesh.GetFacets(); - unsigned long ulCtFacets = rFaces.size(); + std::vector aInds; + const MeshFacetArray& rFaces = _rclMesh.GetFacets(); + unsigned long ulCtFacets = rFaces.size(); - unsigned long ind=0; - for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ ) - { - for ( int i = 0; i < 3; i++ ) { - if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) { - aInds.push_back(ind); - break; - } + unsigned long ind=0; + for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + for (int i = 0; i < 3; i++) { + if ((it->_aulNeighbours[i] >= ulCtFacets) && (it->_aulNeighbours[i] < ULONG_MAX)) { + aInds.push_back(ind); + break; + } + } } - } - return aInds; + return aInds; } bool MeshFixRangeFacet::Fixup() { - return false; + _rclMesh.RebuildNeighbours(); + return true; } // ---------------------------------------------------------------------- bool MeshEvalRangePoint::Evaluate() { - const MeshFacetArray& rFaces = _rclMesh.GetFacets(); - unsigned long ulCtPoints = _rclMesh.CountPoints(); + const MeshFacetArray& rFaces = _rclMesh.GetFacets(); + unsigned long ulCtPoints = _rclMesh.CountPoints(); - for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it ) { - if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal(), ulCtPoints)) < it->_aulPoints + 3) - return false; - } + for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it) { + if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal(), ulCtPoints)) < it->_aulPoints + 3) + return false; + } - return true; + return true; } std::vector MeshEvalRangePoint::GetIndices() const { - std::vector aInds; - const MeshFacetArray& rFaces = _rclMesh.GetFacets(); - unsigned long ulCtPoints = _rclMesh.CountPoints(); + std::vector aInds; + const MeshFacetArray& rFaces = _rclMesh.GetFacets(); + unsigned long ulCtPoints = _rclMesh.CountPoints(); - unsigned long ind=0; - for ( MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++ ) - { - if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal(), ulCtPoints)) < it->_aulPoints + 3) - aInds.push_back(ind); - } + unsigned long ind=0; + for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + if (std::find_if(it->_aulPoints, it->_aulPoints + 3, std::bind2nd(std::greater_equal(), ulCtPoints)) < it->_aulPoints + 3) + aInds.push_back(ind); + } - return aInds; + return aInds; } bool MeshFixRangePoint::Fixup() { - return false; + MeshEvalRangePoint eval(_rclMesh); + if (_rclMesh.CountPoints() == 0) { + // if no points are there but facets then the whole mesh can be cleared + _rclMesh.Clear(); + } + else { + // facets with point indices out of range cannot be directly deleted because + // 'DeleteFacets' will segfault. But setting all point indices to 0 works. + std::vector invalid = eval.GetIndices(); + if (!invalid.empty()) { + const MeshFacetArray& rFaces = _rclMesh.GetFacets(); + for (std::vector::iterator it = invalid.begin(); it != invalid.end(); ++it) { + MeshFacet& face = const_cast(rFaces[*it]); + face._aulPoints[0] = 0; + face._aulPoints[1] = 0; + face._aulPoints[2] = 0; + } + + _rclMesh.DeleteFacets(invalid); + } + } + return true; } // ---------------------------------------------------------------------- diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index bf99ffcfe..66b688ff5 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -349,9 +349,9 @@ bool MeshGeomFacet::Weights(const Base::Vector3f& rclP, float& w0, float& w1, fl return fabs(w0+w1+w2-1.0f)<0.001f; } -void MeshGeomFacet::ProjectPointToPlane (Base::Vector3f &rclPoint) const +void MeshGeomFacet::ProjectPointToPlane (const Base::Vector3f &rclPoint, Base::Vector3f &rclProj) const { - rclPoint.ProjectToPlane(_aclPoints[0], GetNormal()); + rclPoint.ProjectToPlane(_aclPoints[0], GetNormal(), rclProj); } void MeshGeomFacet::ProjectFacetToPlane (MeshGeomFacet &rclFacet) const diff --git a/src/Mod/Mesh/App/Core/Elements.h b/src/Mod/Mesh/App/Core/Elements.h index da6fbbb09..0da635cea 100644 --- a/src/Mod/Mesh/App/Core/Elements.h +++ b/src/Mod/Mesh/App/Core/Elements.h @@ -349,7 +349,7 @@ public: /** * Calculates the projection of a point onto the plane defined by the triangle. */ - void ProjectPointToPlane (Base::Vector3f &rclPoint) const; + void ProjectPointToPlane (const Base::Vector3f &rclPoint, Base::Vector3f &rclProj) const; /** * Calculates the projection of a facet onto the plane defined by the triangle. */ @@ -592,6 +592,58 @@ public: void DecrementIndices (unsigned long ulIndex); }; +/** + * MeshPointModifier is a helper class that allows to modify the + * point array of a mesh kernel but with limited access. + */ +class MeshExport MeshPointModifier +{ +public: + MeshPointModifier(MeshPointArray& points) + : rPoints(points) + { + } + + MeshPointModifier(const MeshPointModifier& c) + : rPoints(c.rPoints) + { + } + +private: + MeshPointArray& rPoints; +}; + +/** + * MeshFacetModifier is a helper class that allows to modify the + * facet array of a mesh kernel but with limited access. + */ +class MeshExport MeshFacetModifier +{ +public: + MeshFacetModifier(MeshFacetArray& facets) + : rFacets(facets) + { + } + + MeshFacetModifier(const MeshFacetModifier& c) + : rFacets(c.rFacets) + { + } + + /** + * Replaces the index of the corner point of the facet at position \a pos + * that is equal to \a old by \a now. If the facet does not have a corner + * point with this index nothing happens. + */ + void Transpose(unsigned long pos, unsigned long old, unsigned long now) + { + rFacets[pos].Transpose(old, now); + } + +private: + MeshFacetArray& rFacets; +}; + inline MeshPoint::MeshPoint (const Base::Vector3f &rclPt) #ifdef _MSC_VER : Vector3f(rclPt), diff --git a/src/Mod/Mesh/App/Core/MeshKernel.cpp b/src/Mod/Mesh/App/Core/MeshKernel.cpp index a737abb35..20bfcae21 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.cpp +++ b/src/Mod/Mesh/App/Core/MeshKernel.cpp @@ -43,6 +43,7 @@ #include "Evaluation.h" #include "Builder.h" #include "Smoothing.h" +#include "MeshIO.h" using namespace MeshCore; @@ -385,6 +386,12 @@ void MeshKernel::Merge(const MeshPointArray& rPoints, const MeshFacetArray& rFac RebuildNeighbours(countFacets); } +void MeshKernel::Cleanup() +{ + MeshCleanup meshCleanup(_aclPointArray, _aclFacetArray); + meshCleanup.RemoveInvalids(); +} + void MeshKernel::Clear (void) { _aclPointArray.clear(); diff --git a/src/Mod/Mesh/App/Core/MeshKernel.h b/src/Mod/Mesh/App/Core/MeshKernel.h index cceb4b122..1100c94a2 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.h +++ b/src/Mod/Mesh/App/Core/MeshKernel.h @@ -141,6 +141,12 @@ public: /** Returns the array of all data points. */ const MeshPointArray& GetPoints (void) const { return _aclPointArray; } + /** Returns a modifier for the point array */ + MeshPointModifier ModifyPoints() + { + return MeshPointModifier(_aclPointArray); + } + /** Returns the array of all facets */ const MeshFacetArray& GetFacets (void) const { return _aclFacetArray; } /** Returns an array of facets to the given indices. The indices @@ -148,6 +154,12 @@ public: */ MeshFacetArray GetFacets(const std::vector&) const; + /** Returns a modifier for the facet array */ + MeshFacetModifier ModifyFacets() + { + return MeshFacetModifier(_aclFacetArray); + } + /** Returns the array of all edges. * Notice: The Edgelist will be temporary generated. Changes on the mesh * structure does not affect the Edgelist @@ -351,8 +363,12 @@ public: * @note This method overwrites the free usable property of each mesh point. */ void DeletePoints (const std::vector &raulPoints); + /** Removes all as INVALID marked points and facets from the structure. */ + void RemoveInvalids (); /** Rebuilds the neighbour indices for all facets. */ void RebuildNeighbours (void); + /** Removes unreferenced points or facets with invalid indices from the mesh. */ + void Cleanup(); /** Clears the whole data structure. */ void Clear (void); /** Replaces the current data structure with the structure built up of the array @@ -385,7 +401,7 @@ public: inline void SetPoint (unsigned long ulPtIndex, const Base::Vector3f &rPoint); /** Sets the point at the given index to the new \a rPoint. */ inline void SetPoint (unsigned long ulPtIndex, float x, float y, float z); - /** Smothes the mesh kernel. */ + /** Smoothes the mesh kernel. */ void Smooth(int iterations, float d_max); /** * CheckFacets() is invoked within this method and all found facets get deleted from the mesh structure. @@ -405,8 +421,6 @@ public: protected: /** Rebuilds the neighbour indices for subset of all facets from index \a index on. */ void RebuildNeighbours (unsigned long); - /** Removes all as INVALID marked points and facets from the structure. */ - void RemoveInvalids (); /** Checks if this point is associated to no other facet and deletes if so. * The point indices of the facets get adjusted. * \a ulIndex is the index of the point to be deleted. \a ulFacetIndex is the index @@ -433,11 +447,6 @@ protected: friend class MeshFastFacetIterator; friend class MeshAlgorithm; friend class MeshTopoAlgorithm; - friend class MeshFixNeighbourhood; - friend class MeshFixDegenerations; - friend class MeshFixSingleFacet; - friend class MeshFixInvalids; - friend class MeshFixDegeneratedFacets; friend class MeshFixDuplicatePoints; friend class MeshBuilder; friend class MeshTrimming;