+ make faster reading ply mesh files
This commit is contained in:
parent
0ea477b420
commit
dd9e8c5bb1
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "MeshKernel.h"
|
#include "MeshKernel.h"
|
||||||
#include "MeshIO.h"
|
#include "MeshIO.h"
|
||||||
|
#include "Algorithm.h"
|
||||||
#include "Builder.h"
|
#include "Builder.h"
|
||||||
|
|
||||||
#include <Base/Builder3D.h>
|
#include <Base/Builder3D.h>
|
||||||
|
@ -961,12 +962,16 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_rclMesh.Clear(); // remove all data before
|
this->_rclMesh.Clear(); // remove all data before
|
||||||
// Don't use Assign() because Merge() checks which points are really needed.
|
#if 1
|
||||||
// This method sets already the correct neighbourhood
|
MeshCleanup(meshPoints,meshFacets).RemoveInvalids();
|
||||||
|
MeshPointFacetAdjacency meshAdj(meshPoints.size(),meshFacets);
|
||||||
|
meshAdj.SetFacetNeighbourhood();
|
||||||
|
this->_rclMesh.Adopt(meshPoints,meshFacets);
|
||||||
|
#else
|
||||||
MeshKernel tmp;
|
MeshKernel tmp;
|
||||||
tmp.Adopt(meshPoints,meshFacets);
|
tmp.Adopt(meshPoints,meshFacets);
|
||||||
this->_rclMesh.Merge(tmp);
|
this->_rclMesh.Merge(tmp);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2448,3 +2453,164 @@ bool MeshOutput::SaveVRML (std::ostream &rstrOut) const
|
||||||
|
|
||||||
return true;
|
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;
|
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
|
} // namespace MeshCore
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user