+ make faster reading ply mesh files
This commit is contained in:
parent
0ea477b420
commit
dd9e8c5bb1
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user