+ make faster reading ply mesh files

This commit is contained in:
wmayer 2016-01-03 01:14:48 +01:00
parent 0ea477b420
commit dd9e8c5bb1
2 changed files with 238 additions and 3 deletions

View File

@ -27,6 +27,7 @@
#include "MeshKernel.h"
#include "MeshIO.h"
#include "Algorithm.h"
#include "Builder.h"
#include <Base/Builder3D.h>
@ -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>(), 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>(), MeshFacet::INVALID));
facetArray.swap(copy_facets);
}
}
void MeshCleanup::RemoveInvalidPoints()
{
std::size_t countInvalidPoints = std::count_if(pointArray.begin(), pointArray.end(),
std::bind2nd(MeshIsFlag<MeshPoint>(), MeshPoint::INVALID));
if (countInvalidPoints > 0) {
// generate array of decrements
std::vector<unsigned long> decrements;
decrements.resize(pointArray.size());
unsigned long decr = 0;
MeshPointArray::_TIterator p_end = pointArray.end();
std::vector<unsigned long>::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>(), 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<std::size_t>());
}
pointFacetAdjacency.clear();
}
void MeshPointFacetAdjacency::Build()
{
std::vector<std::size_t> 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<std::size_t>& refFacets = pointFacetAdjacency[n1];
for (std::vector<std::size_t>::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;
}
}
}
}

View File

@ -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<std::size_t> > pointFacetAdjacency;
};
} // namespace MeshCore