Mesh analyzing algorithms

This commit is contained in:
wmayer 2013-02-17 08:28:01 +01:00
parent 8079e6452b
commit 0abef4d4e3
13 changed files with 441 additions and 55 deletions

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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-

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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
*/

View File

@ -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();