diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp
index 074fdc870..71198287c 100644
--- a/src/Mod/Mesh/App/Core/MeshIO.cpp
+++ b/src/Mod/Mesh/App/Core/MeshIO.cpp
@@ -27,6 +27,7 @@
#include "MeshKernel.h"
#include "MeshIO.h"
+#include "Algorithm.h"
#include "Builder.h"
#include
@@ -961,12 +962,16 @@ bool MeshInput::LoadPLY (std::istream &inp)
}
this->_rclMesh.Clear(); // remove all data before
- // Don't use Assign() because Merge() checks which points are really needed.
- // This method sets already the correct neighbourhood
+#if 1
+ MeshCleanup(meshPoints,meshFacets).RemoveInvalids();
+ MeshPointFacetAdjacency meshAdj(meshPoints.size(),meshFacets);
+ meshAdj.SetFacetNeighbourhood();
+ this->_rclMesh.Adopt(meshPoints,meshFacets);
+#else
MeshKernel tmp;
tmp.Adopt(meshPoints,meshFacets);
this->_rclMesh.Merge(tmp);
-
+#endif
return true;
}
@@ -2448,3 +2453,164 @@ bool MeshOutput::SaveVRML (std::ostream &rstrOut) const
return true;
}
+
+// ----------------------------------------------------------------------------
+
+MeshCleanup::MeshCleanup(MeshPointArray& p, MeshFacetArray& f)
+ : pointArray(p)
+ , facetArray(f)
+{
+}
+
+MeshCleanup::~MeshCleanup()
+{
+}
+
+void MeshCleanup::RemoveInvalids()
+{
+ // first mark all points as invalid
+ pointArray.SetFlag(MeshPoint::INVALID);
+ std::size_t numPoints = pointArray.size();
+
+ // Now go through the facets and invalidate facets with wrong indices
+ // If a facet is valid all its referenced points are validated again
+ // Points that are not referenced are still invalid and thus can be deleted
+ for (MeshFacetArray::_TIterator it = facetArray.begin(); it != facetArray.end(); ++it) {
+ for (int i=0; i<3; i++) {
+ // vertex index out of range
+ if (it->_aulPoints[i] >= numPoints) {
+ it->SetInvalid();
+ break;
+ }
+ }
+
+ // validate referenced points
+ if (it->IsValid()) {
+ pointArray[it->_aulPoints[0]].ResetInvalid();
+ pointArray[it->_aulPoints[1]].ResetInvalid();
+ pointArray[it->_aulPoints[2]].ResetInvalid();
+ }
+ }
+
+ // Remove the invalid items
+ RemoveInvalidFacets();
+ RemoveInvalidPoints();
+}
+
+void MeshCleanup::RemoveInvalidFacets()
+{
+ std::size_t countInvalidFacets = std::count_if(facetArray.begin(), facetArray.end(),
+ std::bind2nd(MeshIsFlag(), MeshFacet::INVALID));
+ if (countInvalidFacets > 0) {
+ MeshFacetArray copy_facets(facetArray.size() - countInvalidFacets);
+ // copy all valid facets to the new array
+ std::remove_copy_if(facetArray.begin(), facetArray.end(), copy_facets.begin(),
+ std::bind2nd(MeshIsFlag(), MeshFacet::INVALID));
+ facetArray.swap(copy_facets);
+ }
+}
+
+void MeshCleanup::RemoveInvalidPoints()
+{
+ std::size_t countInvalidPoints = std::count_if(pointArray.begin(), pointArray.end(),
+ std::bind2nd(MeshIsFlag(), MeshPoint::INVALID));
+ if (countInvalidPoints > 0) {
+ // generate array of decrements
+ std::vector decrements;
+ decrements.resize(pointArray.size());
+ unsigned long decr = 0;
+
+ MeshPointArray::_TIterator p_end = pointArray.end();
+ std::vector::iterator decr_it = decrements.begin();
+ for (MeshPointArray::_TIterator p_it = pointArray.begin(); p_it != p_end; ++p_it, ++decr_it) {
+ *decr_it = decr;
+ if (!p_it->IsValid())
+ decr++;
+ }
+
+ // correct point indices of the facets
+ MeshFacetArray::_TIterator f_end = facetArray.end();
+ for (MeshFacetArray::_TIterator f_it = facetArray.begin(); f_it != f_end; ++f_it) {
+ f_it->_aulPoints[0] -= decrements[f_it->_aulPoints[0]];
+ f_it->_aulPoints[1] -= decrements[f_it->_aulPoints[1]];
+ f_it->_aulPoints[2] -= decrements[f_it->_aulPoints[2]];
+ }
+
+ // delete point, number of valid points
+ std::size_t validPoints = pointArray.size() - countInvalidPoints;
+ MeshPointArray copy_points(validPoints);
+ // copy all valid facets to the new array
+ std::remove_copy_if(pointArray.begin(), pointArray.end(), copy_points.begin(),
+ std::bind2nd(MeshIsFlag(), MeshPoint::INVALID));
+ pointArray.swap(copy_points);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+MeshPointFacetAdjacency::MeshPointFacetAdjacency(std::size_t p, MeshFacetArray& f)
+ : numPoints(p)
+ , facets(f)
+{
+ Build();
+}
+
+MeshPointFacetAdjacency::~MeshPointFacetAdjacency()
+{
+ std::size_t numPoints = pointFacetAdjacency.size();
+ for (std::size_t i = 0; i < numPoints; i++) {
+ pointFacetAdjacency[i].swap(std::vector());
+ }
+ pointFacetAdjacency.clear();
+}
+
+void MeshPointFacetAdjacency::Build()
+{
+ std::vector numFacetAdjacency(numPoints);
+ for (MeshFacetArray::iterator it = facets.begin(); it != facets.end(); ++it) {
+ numFacetAdjacency[it->_aulPoints[0]]++;
+ numFacetAdjacency[it->_aulPoints[1]]++;
+ numFacetAdjacency[it->_aulPoints[2]]++;
+ }
+
+ pointFacetAdjacency.resize(numPoints);
+ for (std::size_t i = 0; i < numPoints; i++)
+ pointFacetAdjacency[i].reserve(numFacetAdjacency[i]);
+
+ std::size_t numFacets = facets.size();
+ for (int i = 0; i < numFacets; i++) {
+ for (int j = 0; j < 3; j++) {
+ pointFacetAdjacency[facets[i]._aulPoints[j]].push_back(i);
+ }
+ }
+}
+
+void MeshPointFacetAdjacency::SetFacetNeighbourhood()
+{
+ std::size_t numFacets = facets.size();
+ std::size_t index = 0;
+ for (std::size_t index = 0; index < numFacets; index++) {
+ MeshFacet& facet1 = facets[index];
+ for (int i = 0; i < 3; i++) {
+ std::size_t n1 = facet1._aulPoints[i];
+ std::size_t n2 = facet1._aulPoints[(i+1)%3];
+
+ bool success = false;
+ const std::vector& refFacets = pointFacetAdjacency[n1];
+ for (std::vector::const_iterator it = refFacets.begin(); it != refFacets.end(); ++it) {
+ if (*it != index) {
+ MeshFacet& facet2 = facets[*it];
+ if (facet2.HasPoint(n2)) {
+ facet1._aulNeighbours[i] = *it;
+ success = true;
+ break;
+ }
+ }
+ }
+
+ if (!success) {
+ facet1._aulNeighbours[i] = ULONG_MAX;
+ }
+ }
+ }
+}
diff --git a/src/Mod/Mesh/App/Core/MeshIO.h b/src/Mod/Mesh/App/Core/MeshIO.h
index 1d225889d..04a9d2d37 100644
--- a/src/Mod/Mesh/App/Core/MeshIO.h
+++ b/src/Mod/Mesh/App/Core/MeshIO.h
@@ -176,6 +176,75 @@ protected:
static std::string stl_header;
};
+/*!
+ The MeshCleanup class is a helper class to remove points from the point array that are not
+ referenced by any facet. It also removes facet with point indices that are out of range.
+ */
+class MeshCleanup
+{
+public:
+ /*!
+ \brief Construction.
+ \param p -- the point array
+ \param f -- the facet array
+ */
+ MeshCleanup(MeshPointArray& p, MeshFacetArray& f);
+ ~MeshCleanup();
+
+ /*!
+ \brief Remove unreferenced and invalid facets.
+ */
+ void RemoveInvalids();
+
+private:
+ /*!
+ \brief Remove invalid facets.
+ */
+ void RemoveInvalidFacets();
+ /*!
+ \brief Remove invalid points.
+ */
+ void RemoveInvalidPoints();
+
+private:
+ MeshPointArray& pointArray;
+ MeshFacetArray& facetArray;
+};
+
+/*!
+ The MeshPointFacetAdjacency class is a helper class to get all facets per vertex
+ and set the neighbourhood of the facets.
+ At this point the MeshFacetArray only references the points but does not have set
+ the neighbourhood of two adjacent facets.
+ */
+class MeshPointFacetAdjacency
+{
+public:
+ /*!
+ \brief Construction.
+ \param p -- the number of points
+ \param f -- the facet array
+ */
+ MeshPointFacetAdjacency(std::size_t p, MeshFacetArray& f);
+ ~MeshPointFacetAdjacency();
+
+ /*!
+ \brief Set the neighbourhood of two adjacent facets.
+ */
+ void SetFacetNeighbourhood();
+
+private:
+ /*!
+ \brief Build up the adjacency information.
+ */
+ void Build();
+
+private:
+ std::size_t numPoints;
+ MeshFacetArray& facets;
+ std::vector< std::vector > pointFacetAdjacency;
+};
+
} // namespace MeshCore