Mesh analyzing algorithms
This commit is contained in:
parent
8079e6452b
commit
0abef4d4e3
|
@ -1538,7 +1538,6 @@ bool MeshAlgorithm::ConnectLines (std::list<std::pair<Base::Vector3f, Base::Vect
|
|||
rclLines.erase(pFront);
|
||||
}
|
||||
|
||||
|
||||
if (pEnd != rclLines.end())
|
||||
{
|
||||
if (bEndFirst == true)
|
||||
|
|
|
@ -701,7 +701,7 @@ bool MeshFixDeformedFacets::Fixup()
|
|||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnSurface::Evaluate()
|
||||
bool MeshEvalDentsOnSurface::Evaluate()
|
||||
{
|
||||
this->indices.clear();
|
||||
MeshRefPointToFacets clPt2Facets(_rclMesh);
|
||||
|
@ -749,14 +749,25 @@ bool MeshEvalFoldsOnSurface::Evaluate()
|
|||
return this->indices.empty();
|
||||
}
|
||||
|
||||
std::vector<unsigned long> MeshEvalFoldsOnSurface::GetIndices() const
|
||||
std::vector<unsigned long> MeshEvalDentsOnSurface::GetIndices() const
|
||||
{
|
||||
return this->indices;
|
||||
}
|
||||
|
||||
bool MeshFixFoldsOnSurface::Fixup()
|
||||
/*
|
||||
Forbidden is:
|
||||
+ two facets share a common point but not a common edge
|
||||
|
||||
Repair:
|
||||
+ store the point indices which can be projected on a face
|
||||
+ store the face indices on which a point can be projected
|
||||
+ remove faces with an edge length smaller than a certain threshold (e.g. 0.01) from the stored triangles or that reference one of the stored points
|
||||
+ for this edge merge the two points
|
||||
+ if a point of a face can be projected onto another face and they have a common point then split the second face if the distance is under a certain threshold
|
||||
*/
|
||||
bool MeshFixDentsOnSurface::Fixup()
|
||||
{
|
||||
MeshEvalFoldsOnSurface eval(_rclMesh);
|
||||
MeshEvalDentsOnSurface eval(_rclMesh);
|
||||
if (!eval.Evaluate()) {
|
||||
std::vector<unsigned long> inds = eval.GetIndices();
|
||||
_rclMesh.DeleteFacets(inds);
|
||||
|
@ -767,6 +778,44 @@ bool MeshFixFoldsOnSurface::Fixup()
|
|||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnSurface::Evaluate()
|
||||
{
|
||||
this->indices.clear();
|
||||
const MeshFacetArray& rFAry = _rclMesh.GetFacets();
|
||||
unsigned long ct=0;
|
||||
for (MeshFacetArray::const_iterator it = rFAry.begin(); it != rFAry.end(); ++it, ct++) {
|
||||
for (int i=0; i<3; i++) {
|
||||
unsigned long n1 = it->_aulNeighbours[i];
|
||||
unsigned long n2 = it->_aulNeighbours[(i+1)%3];
|
||||
Base::Vector3f v1 =_rclMesh.GetFacet(*it).GetNormal();
|
||||
if (n1 != ULONG_MAX && n2 != ULONG_MAX) {
|
||||
Base::Vector3f v2 = _rclMesh.GetFacet(n1).GetNormal();
|
||||
Base::Vector3f v3 = _rclMesh.GetFacet(n2).GetNormal();
|
||||
if (v2 * v3 > 0.0f) {
|
||||
if (v1 * v2 < -0.1f && v1 * v3 < -0.1f) {
|
||||
indices.push_back(n1);
|
||||
indices.push_back(n2);
|
||||
indices.push_back(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
std::sort(this->indices.begin(), this->indices.end());
|
||||
this->indices.erase(std::unique(this->indices.begin(),
|
||||
this->indices.end()), this->indices.end());
|
||||
return this->indices.empty();
|
||||
}
|
||||
|
||||
std::vector<unsigned long> MeshEvalFoldsOnSurface::GetIndices() const
|
||||
{
|
||||
return this->indices;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnBoundary::Evaluate()
|
||||
{
|
||||
// remove all boundary facets with two open edges and where
|
||||
|
|
|
@ -380,6 +380,37 @@ private:
|
|||
float fMaxAngle;
|
||||
};
|
||||
|
||||
/**
|
||||
* If an adjacent point (A) of a point (P) can be projected onto a triangle shared
|
||||
* by (P) but not by (A) then we have a local dent. The topology is not affected.
|
||||
*/
|
||||
class MeshExport MeshEvalDentsOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
MeshEvalDentsOnSurface (const MeshKernel &rclM) : MeshEvaluation( rclM ) { }
|
||||
~MeshEvalDentsOnSurface() {}
|
||||
|
||||
bool Evaluate();
|
||||
std::vector<unsigned long> GetIndices() const;
|
||||
|
||||
private:
|
||||
std::vector<unsigned long> indices;
|
||||
};
|
||||
|
||||
class MeshExport MeshFixDentsOnSurface : public MeshValidation
|
||||
{
|
||||
public:
|
||||
MeshFixDentsOnSurface (MeshKernel &rclM) : MeshValidation( rclM ) { }
|
||||
~MeshFixDentsOnSurface() {}
|
||||
|
||||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* If the angle between the adjacent triangles of a triangle is lower then 90 deg
|
||||
* but the angles between both of these adjacent triangles is higher than 90 deg
|
||||
* we have a fold. The topology is not affected but the geometry is broken.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldsOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
|
@ -393,15 +424,12 @@ private:
|
|||
std::vector<unsigned long> indices;
|
||||
};
|
||||
|
||||
class MeshExport MeshFixFoldsOnSurface : public MeshValidation
|
||||
{
|
||||
public:
|
||||
MeshFixFoldsOnSurface (MeshKernel &rclM) : MeshValidation( rclM ) { }
|
||||
~MeshFixFoldsOnSurface() {}
|
||||
|
||||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* Considers a boundary triangle with two open edges and an angle higher than
|
||||
* 60 deg with its adjacent triangle as a boundary fold.
|
||||
* The topology is not affected there but such triangles can lead to problems
|
||||
* on some hole-filling algorithms.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldsOnBoundary : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
|
@ -424,6 +452,10 @@ public:
|
|||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* Considers two adjacent triangles with an angle higher than 120 deg of their
|
||||
* normals as a fold-over. The topology is not affected there.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldOversOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -411,27 +411,26 @@ unsigned long MeshEvalTopology::CountManifolds() const
|
|||
|
||||
bool MeshFixTopology::Fixup ()
|
||||
{
|
||||
std::vector<unsigned long> indices;
|
||||
#if 0
|
||||
MeshEvalTopology eval(_rclMesh);
|
||||
if (!eval.Evaluate()) {
|
||||
eval.GetFacetManifolds(indices);
|
||||
eval.GetFacetManifolds(deletedFaces);
|
||||
|
||||
// remove duplicates
|
||||
std::sort(indices.begin(), indices.end());
|
||||
indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
|
||||
std::sort(deletedFaces.begin(), deletedFaces.end());
|
||||
deletedFaces.erase(std::unique(deletedFaces.begin(), deletedFaces.end()), deletedFaces.end());
|
||||
|
||||
_rclMesh.DeleteFacets(indices);
|
||||
_rclMesh.DeleteFacets(deletedFaces);
|
||||
}
|
||||
#else
|
||||
const MeshFacetArray& rFaces = _rclMesh.GetFacets();
|
||||
indices.reserve(3 * nonManifoldList.size()); // allocate some memory
|
||||
deletedFaces.reserve(3 * nonManifoldList.size()); // allocate some memory
|
||||
std::list<std::vector<unsigned long> >::const_iterator it;
|
||||
for (it = nonManifoldList.begin(); it != nonManifoldList.end(); ++it) {
|
||||
std::vector<unsigned long> non_mf;
|
||||
non_mf.reserve(it->size());
|
||||
for (std::vector<unsigned long>::const_iterator jt = it->begin(); jt != it->end(); ++jt) {
|
||||
// fscet is only connected with one edge and there causes a non-manifold
|
||||
// facet is only connected with one edge and there causes a non-manifold
|
||||
unsigned short numOpenEdges = rFaces[*jt].CountOpenEdges();
|
||||
if (numOpenEdges == 2)
|
||||
non_mf.push_back(*jt);
|
||||
|
@ -441,17 +440,17 @@ bool MeshFixTopology::Fixup ()
|
|||
|
||||
// are we able to repair the non-manifold edge by not removing all facets?
|
||||
if (it->size() - non_mf.size() == 2)
|
||||
indices.insert(indices.end(), non_mf.begin(), non_mf.end());
|
||||
deletedFaces.insert(deletedFaces.end(), non_mf.begin(), non_mf.end());
|
||||
else
|
||||
indices.insert(indices.end(), it->begin(), it->end());
|
||||
deletedFaces.insert(deletedFaces.end(), it->begin(), it->end());
|
||||
}
|
||||
|
||||
if (!indices.empty()) {
|
||||
if (!deletedFaces.empty()) {
|
||||
// remove duplicates
|
||||
std::sort(indices.begin(), indices.end());
|
||||
indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
|
||||
std::sort(deletedFaces.begin(), deletedFaces.end());
|
||||
deletedFaces.erase(std::unique(deletedFaces.begin(), deletedFaces.end()), deletedFaces.end());
|
||||
|
||||
_rclMesh.DeleteFacets(indices);
|
||||
_rclMesh.DeleteFacets(deletedFaces);
|
||||
_rclMesh.RebuildNeighbours();
|
||||
}
|
||||
#endif
|
||||
|
@ -461,6 +460,53 @@ bool MeshFixTopology::Fixup ()
|
|||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
bool MeshEvalPointManifolds::Evaluate ()
|
||||
{
|
||||
this->nonManifoldPoints.clear();
|
||||
this->facetsOfNonManifoldPoints.clear();
|
||||
|
||||
MeshCore::MeshRefPointToPoints vv_it(_rclMesh);
|
||||
MeshCore::MeshRefPointToFacets vf_it(_rclMesh);
|
||||
|
||||
unsigned long ctPoints = _rclMesh.CountPoints();
|
||||
for (unsigned long index=0; index < ctPoints; index++) {
|
||||
// get the local neighbourhood of the point
|
||||
const std::set<unsigned long>& nf = vf_it[index];
|
||||
const std::set<unsigned long>& np = vv_it[index];
|
||||
|
||||
std::set<unsigned long>::size_type sp, sf;
|
||||
sp = np.size();
|
||||
sf = nf.size();
|
||||
// for an inner point the number of adjacent points is equal to the number of shared faces
|
||||
// for a boundary point the number of adjacent points is higher by one than the number of shared faces
|
||||
// for a non-manifold point the number of adjacent points is higher by more than one than the number of shared faces
|
||||
if (sp > sf + 1) {
|
||||
nonManifoldPoints.push_back(index);
|
||||
std::vector<unsigned long> faces;
|
||||
faces.insert(faces.end(), nf.begin(), nf.end());
|
||||
this->facetsOfNonManifoldPoints.push_back(faces);
|
||||
}
|
||||
}
|
||||
|
||||
return this->nonManifoldPoints.empty();
|
||||
}
|
||||
|
||||
void MeshEvalPointManifolds::GetFacetIndices (std::vector<unsigned long> &facets) const
|
||||
{
|
||||
std::list<std::vector<unsigned long> >::const_iterator it;
|
||||
for (it = facetsOfNonManifoldPoints.begin(); it != facetsOfNonManifoldPoints.end(); ++it) {
|
||||
facets.insert(facets.end(), it->begin(), it->end());
|
||||
}
|
||||
|
||||
if (!facets.empty()) {
|
||||
// remove duplicates
|
||||
std::sort(facets.begin(), facets.end());
|
||||
facets.erase(std::unique(facets.begin(), facets.end()), facets.end());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
bool MeshEvalSingleFacet::Evaluate ()
|
||||
{
|
||||
// get all non-manifolds
|
||||
|
|
|
@ -214,12 +214,40 @@ public:
|
|||
virtual ~MeshFixTopology () {}
|
||||
bool Fixup();
|
||||
|
||||
const std::vector<unsigned long>& GetDeletedFaces() const { return deletedFaces; }
|
||||
|
||||
protected:
|
||||
std::vector<unsigned long> deletedFaces;
|
||||
const std::list<std::vector<unsigned long> >& nonManifoldList;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* The MeshEvalPointManifolds class checks for non-manifold points.
|
||||
* A point is considered non-manifold if two sets of triangles share
|
||||
* the point but are not topologically connected over a common edge.
|
||||
* Such mesh defects can lead to some very ugly folds on the surface.
|
||||
*/
|
||||
class MeshExport MeshEvalPointManifolds : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
MeshEvalPointManifolds (const MeshKernel &rclB) : MeshEvaluation(rclB) {}
|
||||
virtual ~MeshEvalPointManifolds () {}
|
||||
virtual bool Evaluate ();
|
||||
|
||||
void GetFacetIndices (std::vector<unsigned long> &facets) const;
|
||||
const std::list<std::vector<unsigned long> >& GetFacetIndices () const { return facetsOfNonManifoldPoints; }
|
||||
const std::vector<unsigned long>& GetIndices() const { return nonManifoldPoints; }
|
||||
unsigned long CountManifolds() const { return nonManifoldPoints.size(); }
|
||||
|
||||
protected:
|
||||
std::vector<unsigned long> nonManifoldPoints;
|
||||
std::list<std::vector<unsigned long> > facetsOfNonManifoldPoints;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* The MeshEvalSingleFacet class checks a special case of non-manifold edges as follows.
|
||||
* If an edge is shared by more than two facets and if all further facets causing this non-
|
||||
|
|
|
@ -50,16 +50,16 @@ void AbstractSmoothing::initialize(Component comp, Continuity cont)
|
|||
this->continuity = cont;
|
||||
}
|
||||
|
||||
MeshSmoothing::MeshSmoothing(MeshKernel& m)
|
||||
PlaneFitSmoothing::PlaneFitSmoothing(MeshKernel& m)
|
||||
: AbstractSmoothing(m)
|
||||
{
|
||||
}
|
||||
|
||||
MeshSmoothing::~MeshSmoothing()
|
||||
PlaneFitSmoothing::~PlaneFitSmoothing()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshSmoothing::Smooth(unsigned int iterations)
|
||||
void PlaneFitSmoothing::Smooth(unsigned int iterations)
|
||||
{
|
||||
MeshCore::MeshPoint center;
|
||||
MeshCore::MeshPointArray PointArray = kernel.GetPoints();
|
||||
|
@ -112,6 +112,60 @@ void MeshSmoothing::Smooth(unsigned int iterations)
|
|||
}
|
||||
}
|
||||
|
||||
void PlaneFitSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshPoint center;
|
||||
MeshCore::MeshPointArray PointArray = kernel.GetPoints();
|
||||
|
||||
MeshCore::MeshPointIterator v_it(kernel);
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshPointArray::_TConstIterator v_beg = kernel.GetPoints().begin();
|
||||
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Base::Vector3f N, L;
|
||||
for (std::vector<unsigned long>::const_iterator it = point_indices.begin(); it != point_indices.end(); ++it) {
|
||||
v_it.Set(*it);
|
||||
MeshCore::PlaneFit pf;
|
||||
pf.AddPoint(*v_it);
|
||||
center = *v_it;
|
||||
const std::set<unsigned long>& cv = vv_it[v_it.Position()];
|
||||
if (cv.size() < 3)
|
||||
continue;
|
||||
|
||||
std::set<unsigned long>::const_iterator cv_it;
|
||||
for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
|
||||
pf.AddPoint(v_beg[*cv_it]);
|
||||
center += v_beg[*cv_it];
|
||||
}
|
||||
|
||||
float scale = 1.0f/((float)cv.size()+1.0f);
|
||||
center.Scale(scale,scale,scale);
|
||||
|
||||
// get the mean plane of the current vertex with the surrounding vertices
|
||||
pf.Fit();
|
||||
N = pf.GetNormal();
|
||||
N.Normalize();
|
||||
|
||||
// look in which direction we should move the vertex
|
||||
L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z);
|
||||
if (N*L < 0.0)
|
||||
N.Scale(-1.0, -1.0, -1.0);
|
||||
|
||||
// maximum value to move is distance to mean plane
|
||||
float d = std::min<float>((float)fabs(this->tolerance),(float)fabs(N*L));
|
||||
N.Scale(d,d,d);
|
||||
|
||||
PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z);
|
||||
}
|
||||
|
||||
// assign values without affecting iterators
|
||||
unsigned long count = kernel.CountPoints();
|
||||
for (unsigned long idx = 0; idx < count; idx++) {
|
||||
kernel.SetPoint(idx, PointArray[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaplaceSmoothing::LaplaceSmoothing(MeshKernel& m)
|
||||
: AbstractSmoothing(m), lambda(0.6307)
|
||||
{
|
||||
|
@ -157,6 +211,41 @@ void LaplaceSmoothing::Umbrella(const MeshRefPointToPoints& vv_it,
|
|||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::Umbrella(const MeshRefPointToPoints& vv_it,
|
||||
const MeshRefPointToFacets& vf_it, double stepsize,
|
||||
const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
const MeshCore::MeshPointArray& points = kernel.GetPoints();
|
||||
MeshCore::MeshPointArray::_TConstIterator v_beg = points.begin();
|
||||
|
||||
for (std::vector<unsigned long>::const_iterator pos = point_indices.begin(); pos != point_indices.end(); ++pos) {
|
||||
const std::set<unsigned long>& cv = vv_it[*pos];
|
||||
if (cv.size() < 3)
|
||||
continue;
|
||||
if (cv.size() != vf_it[*pos].size()) {
|
||||
// do nothing for border points
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int n_count = cv.size();
|
||||
double w;
|
||||
w=1.0/double(n_count);
|
||||
|
||||
double delx=0.0,dely=0.0,delz=0.0;
|
||||
std::set<unsigned long>::const_iterator cv_it;
|
||||
for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
|
||||
delx += w*((v_beg[*cv_it]).x-(v_beg[*pos]).x);
|
||||
dely += w*((v_beg[*cv_it]).y-(v_beg[*pos]).y);
|
||||
delz += w*((v_beg[*cv_it]).z-(v_beg[*pos]).z);
|
||||
}
|
||||
|
||||
float x = (float)((v_beg[*pos]).x+stepsize*delx);
|
||||
float y = (float)((v_beg[*pos]).y+stepsize*dely);
|
||||
float z = (float)((v_beg[*pos]).z+stepsize*delz);
|
||||
kernel.SetPoint(*pos,x,y,z);
|
||||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::Smooth(unsigned int iterations)
|
||||
{
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
|
@ -167,6 +256,16 @@ void LaplaceSmoothing::Smooth(unsigned int iterations)
|
|||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshRefPointToFacets vf_it(kernel);
|
||||
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Umbrella(vv_it, vf_it, lambda, point_indices);
|
||||
}
|
||||
}
|
||||
|
||||
TaubinSmoothing::TaubinSmoothing(MeshKernel& m)
|
||||
: LaplaceSmoothing(m), micro(0.0424)
|
||||
{
|
||||
|
@ -189,3 +288,17 @@ void TaubinSmoothing::Smooth(unsigned int iterations)
|
|||
Umbrella(vv_it, vf_it, -(lambda+micro));
|
||||
}
|
||||
}
|
||||
|
||||
void TaubinSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshPointArray::_TConstIterator v_it;
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshRefPointToFacets vf_it(kernel);
|
||||
|
||||
// Theoretically Taubin does not shrink the surface
|
||||
iterations = (iterations+1)/2; // two steps per iteration
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Umbrella(vv_it, vf_it, lambda, point_indices);
|
||||
Umbrella(vv_it, vf_it, -(lambda+micro), point_indices);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef MESH_SMOOTHING_H
|
||||
#define MESH_SMOOTHING_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace MeshCore
|
||||
{
|
||||
class MeshKernel;
|
||||
|
@ -52,6 +54,7 @@ public:
|
|||
|
||||
/** Smooth the triangle mesh. */
|
||||
virtual void Smooth(unsigned int) = 0;
|
||||
virtual void SmoothPoints(unsigned int, const std::vector<unsigned long>&) = 0;
|
||||
|
||||
protected:
|
||||
MeshKernel& kernel;
|
||||
|
@ -61,12 +64,13 @@ protected:
|
|||
Continuity continuity;
|
||||
};
|
||||
|
||||
class MeshExport MeshSmoothing : public AbstractSmoothing
|
||||
class MeshExport PlaneFitSmoothing : public AbstractSmoothing
|
||||
{
|
||||
public:
|
||||
MeshSmoothing(MeshKernel&);
|
||||
virtual ~MeshSmoothing();
|
||||
PlaneFitSmoothing(MeshKernel&);
|
||||
virtual ~PlaneFitSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
};
|
||||
|
||||
class MeshExport LaplaceSmoothing : public AbstractSmoothing
|
||||
|
@ -75,11 +79,15 @@ public:
|
|||
LaplaceSmoothing(MeshKernel&);
|
||||
virtual ~LaplaceSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
void SetLambda(double l) { lambda = l;}
|
||||
|
||||
protected:
|
||||
void Umbrella(const MeshRefPointToPoints&,
|
||||
const MeshRefPointToFacets&, double);
|
||||
void Umbrella(const MeshRefPointToPoints&,
|
||||
const MeshRefPointToFacets&, double,
|
||||
const std::vector<unsigned long>&);
|
||||
|
||||
protected:
|
||||
double lambda;
|
||||
|
@ -91,6 +99,7 @@ public:
|
|||
TaubinSmoothing(MeshKernel&);
|
||||
virtual ~TaubinSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
void SetMicro(double m) { micro = m;}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1108,15 +1108,18 @@ bool MeshObject::hasNonManifolds() const
|
|||
|
||||
void MeshObject::removeNonManifolds()
|
||||
{
|
||||
unsigned long count = _kernel.CountFacets();
|
||||
MeshCore::MeshEvalTopology cMeshEval(_kernel);
|
||||
if (!cMeshEval.Evaluate()) {
|
||||
MeshCore::MeshFixTopology cMeshFix(_kernel, cMeshEval.GetFacets());
|
||||
cMeshFix.Fixup();
|
||||
MeshCore::MeshEvalTopology f_eval(_kernel);
|
||||
if (!f_eval.Evaluate()) {
|
||||
MeshCore::MeshFixTopology f_fix(_kernel, f_eval.GetFacets());
|
||||
f_fix.Fixup();
|
||||
deletedFacets(f_fix.GetDeletedFaces());
|
||||
}
|
||||
MeshCore::MeshEvalPointManifolds p_eval(_kernel);
|
||||
if (!p_eval.Evaluate()) {
|
||||
std::vector<unsigned long> faces;
|
||||
p_eval.GetFacetIndices(faces);
|
||||
deleteFacets(faces);
|
||||
}
|
||||
|
||||
if (_kernel.CountFacets() < count)
|
||||
this->_segments.clear();
|
||||
}
|
||||
|
||||
bool MeshObject::hasSelfIntersections() const
|
||||
|
|
|
@ -124,6 +124,7 @@ void MeshGuiExport initMeshGui()
|
|||
MeshGui::ViewProviderMeshDefects ::init();
|
||||
MeshGui::ViewProviderMeshOrientation ::init();
|
||||
MeshGui::ViewProviderMeshNonManifolds ::init();
|
||||
MeshGui::ViewProviderMeshNonManifoldPoints ::init();
|
||||
MeshGui::ViewProviderMeshDuplicatedFaces ::init();
|
||||
MeshGui::ViewProviderMeshDuplicatedPoints ::init();
|
||||
MeshGui::ViewProviderMeshDegenerations ::init();
|
||||
|
|
|
@ -478,29 +478,37 @@ void DlgEvaluateMeshImp::on_analyzeNonmanifoldsButton_clicked()
|
|||
qApp->setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
|
||||
MeshEvalTopology eval(rMesh);
|
||||
MeshEvalTopology f_eval(rMesh);
|
||||
MeshEvalPointManifolds p_eval(rMesh);
|
||||
bool ok1 = f_eval.Evaluate();
|
||||
bool ok2 = p_eval.Evaluate();
|
||||
|
||||
if (eval.Evaluate()) {
|
||||
if (ok1 && ok2) {
|
||||
checkNonmanifoldsButton->setText(tr("No non-manifolds"));
|
||||
checkNonmanifoldsButton->setChecked(false);
|
||||
repairNonmanifoldsButton->setEnabled(false);
|
||||
removeViewProvider("MeshGui::ViewProviderMeshNonManifolds");
|
||||
}
|
||||
else {
|
||||
checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(eval.CountManifolds()));
|
||||
checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(f_eval.CountManifolds()+p_eval.CountManifolds()));
|
||||
checkNonmanifoldsButton->setChecked(true);
|
||||
repairNonmanifoldsButton->setEnabled(true);
|
||||
repairAllTogether->setEnabled(true);
|
||||
const std::vector<std::pair<unsigned long, unsigned long> >& inds = eval.GetIndices();
|
||||
std::vector<unsigned long> indices;
|
||||
indices.reserve(2*inds.size());
|
||||
std::vector<std::pair<unsigned long, unsigned long> >::const_iterator it;
|
||||
for (it = inds.begin(); it != inds.end(); ++it) {
|
||||
indices.push_back(it->first);
|
||||
indices.push_back(it->second);
|
||||
}
|
||||
if (!ok1) {
|
||||
const std::vector<std::pair<unsigned long, unsigned long> >& inds = f_eval.GetIndices();
|
||||
std::vector<unsigned long> indices;
|
||||
indices.reserve(2*inds.size());
|
||||
std::vector<std::pair<unsigned long, unsigned long> >::const_iterator it;
|
||||
for (it = inds.begin(); it != inds.end(); ++it) {
|
||||
indices.push_back(it->first);
|
||||
indices.push_back(it->second);
|
||||
}
|
||||
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices);
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices);
|
||||
}
|
||||
if (!ok2) {
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifoldPoints", p_eval.GetIndices());
|
||||
}
|
||||
}
|
||||
|
||||
qApp->restoreOverrideCursor();
|
||||
|
@ -1124,9 +1132,9 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked()
|
|||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR MeshGui::DockEvaluateMeshImp */
|
||||
|
||||
/* TRANSLATOR MeshGui::DockEvaluateMeshImp */
|
||||
|
||||
#if 0 // needed for Qt's lupdate utility
|
||||
qApp->translate("QDockWidget", "Evaluate & Repair Mesh");
|
||||
#endif
|
||||
|
|
|
@ -59,6 +59,7 @@ using namespace MeshGui;
|
|||
PROPERTY_SOURCE_ABSTRACT(MeshGui::ViewProviderMeshDefects, Gui::ViewProviderDocumentObject)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshOrientation, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshNonManifolds, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshNonManifoldPoints, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDuplicatedFaces, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDuplicatedPoints, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDegenerations, MeshGui::ViewProviderMeshDefects)
|
||||
|
@ -234,6 +235,63 @@ void ViewProviderMeshNonManifolds::showDefects(const std::vector<unsigned long>&
|
|||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ViewProviderMeshNonManifoldPoints::ViewProviderMeshNonManifoldPoints()
|
||||
{
|
||||
pcPoints = new SoPointSet;
|
||||
pcPoints->ref();
|
||||
}
|
||||
|
||||
ViewProviderMeshNonManifoldPoints::~ViewProviderMeshNonManifoldPoints()
|
||||
{
|
||||
pcPoints->unref();
|
||||
}
|
||||
|
||||
void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* pcFeat)
|
||||
{
|
||||
ViewProviderDocumentObject::attach( pcFeat );
|
||||
|
||||
SoGroup* pcPointRoot = new SoGroup();
|
||||
pcDrawStyle->pointSize = 3;
|
||||
pcPointRoot->addChild(pcDrawStyle);
|
||||
|
||||
// Draw points
|
||||
SoSeparator* pointsep = new SoSeparator;
|
||||
SoBaseColor * basecol = new SoBaseColor;
|
||||
basecol->rgb.setValue( 1.0f, 0.5f, 0.0f );
|
||||
pointsep->addChild(basecol);
|
||||
pointsep->addChild(pcCoords);
|
||||
pointsep->addChild(pcPoints);
|
||||
pcPointRoot->addChild(pointsep);
|
||||
|
||||
// Draw markers
|
||||
SoBaseColor * markcol = new SoBaseColor;
|
||||
markcol->rgb.setValue( 1.0f, 1.0f, 0.0f );
|
||||
SoMarkerSet* marker = new SoMarkerSet;
|
||||
marker->markerIndex=SoMarkerSet::PLUS_7_7;
|
||||
pointsep->addChild(markcol);
|
||||
pointsep->addChild(marker);
|
||||
|
||||
addDisplayMaskMode(pcPointRoot, "Point");
|
||||
}
|
||||
|
||||
void ViewProviderMeshNonManifoldPoints::showDefects(const std::vector<unsigned long>& inds)
|
||||
{
|
||||
Mesh::Feature* f = dynamic_cast<Mesh::Feature*>(pcObject);
|
||||
const MeshCore::MeshKernel & rMesh = f->Mesh.getValue().getKernel();
|
||||
pcCoords->point.deleteValues(0);
|
||||
pcCoords->point.setNum(inds.size());
|
||||
MeshCore::MeshPointIterator cP(rMesh);
|
||||
unsigned long i = 0;
|
||||
for ( std::vector<unsigned long>::const_iterator it = inds.begin(); it != inds.end(); ++it ) {
|
||||
cP.Set(*it);
|
||||
pcCoords->point.set1Value(i++,cP->x,cP->y,cP->z);
|
||||
}
|
||||
|
||||
setDisplayMaskMode("Point");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ViewProviderMeshDuplicatedFaces::ViewProviderMeshDuplicatedFaces()
|
||||
{
|
||||
pcFaces = new SoFaceSet;
|
||||
|
|
|
@ -96,6 +96,24 @@ protected:
|
|||
SoLineSet* pcLines;
|
||||
};
|
||||
|
||||
/** The ViewProviderMeshNonManifoldPoints class displays non-manifold vertexes in red.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class MeshGuiExport ViewProviderMeshNonManifoldPoints : public ViewProviderMeshDefects
|
||||
{
|
||||
PROPERTY_HEADER(MeshGui::ViewProviderMeshNonManifoldPoints);
|
||||
|
||||
public:
|
||||
ViewProviderMeshNonManifoldPoints();
|
||||
virtual ~ViewProviderMeshNonManifoldPoints();
|
||||
|
||||
void attach(App::DocumentObject* pcFeature);
|
||||
void showDefects(const std::vector<unsigned long>&);
|
||||
|
||||
protected:
|
||||
SoPointSet* pcPoints;
|
||||
};
|
||||
|
||||
/** The ViewProviderMeshDuplicatedFaces class displays duplicated faces in red.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
|
|
|
@ -195,6 +195,28 @@ int TopoShapeFacePy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
|
||||
if (!wires.empty()) {
|
||||
BRepBuilderAPI_MakeFace mkFace(wires.front());
|
||||
if (!mkFace.IsDone()) {
|
||||
switch (mkFace.Error()) {
|
||||
case BRepBuilderAPI_NoFace:
|
||||
Standard_Failure::Raise("No face");
|
||||
break;
|
||||
case BRepBuilderAPI_NotPlanar:
|
||||
Standard_Failure::Raise("Not planar");
|
||||
break;
|
||||
case BRepBuilderAPI_CurveProjectionFailed:
|
||||
Standard_Failure::Raise("Curve projection failed");
|
||||
break;
|
||||
case BRepBuilderAPI_ParametersOutOfRange:
|
||||
Standard_Failure::Raise("Parameters out of range");
|
||||
break;
|
||||
case BRepBuilderAPI_SurfaceNotC2:
|
||||
Standard_Failure::Raise("Surface not C2");
|
||||
break;
|
||||
default:
|
||||
Standard_Failure::Raise("Unknown failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (std::vector<TopoDS_Wire>::iterator it = wires.begin()+1; it != wires.end(); ++it)
|
||||
mkFace.Add(*it);
|
||||
getTopoShapePtr()->_Shape = mkFace.Face();
|
||||
|
|
Loading…
Reference in New Issue
Block a user