Mesh: Apply clang-format
This commit is contained in:
@@ -22,16 +22,16 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <queue>
|
||||
#include <queue>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Mod/Mesh/App/WildMagic4/Wm4Delaunay2.h>
|
||||
|
||||
#include "Triangulation.h"
|
||||
#include "Approximation.h"
|
||||
#include "MeshKernel.h"
|
||||
#include "Triangulation.h"
|
||||
|
||||
|
||||
using namespace MeshCore;
|
||||
@@ -47,8 +47,7 @@ bool TriangulationVerifier::Accept(const Base::Vector3f& n,
|
||||
return (ref_dist * tri_dist <= 0.0f);
|
||||
}
|
||||
|
||||
bool TriangulationVerifier::MustFlip(const Base::Vector3f& n1,
|
||||
const Base::Vector3f& n2) const
|
||||
bool TriangulationVerifier::MustFlip(const Base::Vector3f& n1, const Base::Vector3f& n2) const
|
||||
{
|
||||
return n1.Dot(n2) <= 0.0f;
|
||||
}
|
||||
@@ -65,8 +64,7 @@ bool TriangulationVerifierV2::Accept(const Base::Vector3f& n,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TriangulationVerifierV2::MustFlip(const Base::Vector3f& n1,
|
||||
const Base::Vector3f& n2) const
|
||||
bool TriangulationVerifierV2::MustFlip(const Base::Vector3f& n1, const Base::Vector3f& n2) const
|
||||
{
|
||||
float dot = n1.Dot(n2);
|
||||
(void)dot;
|
||||
@@ -101,8 +99,9 @@ void AbstractPolygonTriangulator::SetPolygon(const std::vector<Base::Vector3f>&
|
||||
{
|
||||
this->_points = raclPoints;
|
||||
if (!this->_points.empty()) {
|
||||
if (this->_points.front() == this->_points.back())
|
||||
if (this->_points.front() == this->_points.back()) {
|
||||
this->_points.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +114,12 @@ float AbstractPolygonTriangulator::GetLength() const
|
||||
{
|
||||
float len = 0.0f;
|
||||
if (_points.size() > 2) {
|
||||
for (std::vector<Base::Vector3f>::const_iterator it = _points.begin(); it != _points.end();++it) {
|
||||
for (std::vector<Base::Vector3f>::const_iterator it = _points.begin(); it != _points.end();
|
||||
++it) {
|
||||
std::vector<Base::Vector3f>::const_iterator jt = it + 1;
|
||||
if (jt == _points.end()) jt = _points.begin();
|
||||
if (jt == _points.end()) {
|
||||
jt = _points.begin();
|
||||
}
|
||||
len += Base::Distance(*it, *jt);
|
||||
}
|
||||
}
|
||||
@@ -130,19 +132,22 @@ std::vector<Base::Vector3f> AbstractPolygonTriangulator::AddedPoints() const
|
||||
// Apply the inverse transformation to project back to world coordinates
|
||||
std::vector<Base::Vector3f> added;
|
||||
added.reserve(_newpoints.size());
|
||||
for (auto point : _newpoints)
|
||||
for (auto point : _newpoints) {
|
||||
added.push_back(_inverse * point);
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
Base::Matrix4D AbstractPolygonTriangulator::GetTransformToFitPlane() const
|
||||
{
|
||||
PlaneFit planeFit;
|
||||
for (auto point : _points)
|
||||
for (auto point : _points) {
|
||||
planeFit.AddPoint(point);
|
||||
}
|
||||
|
||||
if (planeFit.Fit() >= FLOAT_MAX)
|
||||
if (planeFit.Fit() >= FLOAT_MAX) {
|
||||
throw Base::RuntimeError("Plane fit failed");
|
||||
}
|
||||
|
||||
Base::Vector3f bs = planeFit.GetBase();
|
||||
Base::Vector3f ex = planeFit.GetDirU();
|
||||
@@ -183,8 +188,9 @@ std::vector<Base::Vector3f> AbstractPolygonTriangulator::ProjectToFitPlane()
|
||||
Base::Vector3f ey(static_cast<float>(_inverse[0][1]),
|
||||
static_cast<float>(_inverse[1][1]),
|
||||
static_cast<float>(_inverse[2][1]));
|
||||
for (auto & jt : proj)
|
||||
for (auto& jt : proj) {
|
||||
jt.TransformToCoordinateSystem(bs, ex, ey);
|
||||
}
|
||||
return proj;
|
||||
}
|
||||
|
||||
@@ -211,8 +217,9 @@ void AbstractPolygonTriangulator::PostProcessing(const std::vector<Base::Vector3
|
||||
}
|
||||
|
||||
if (polyFit.CountPoints() >= uMinPts && polyFit.Fit() < FLOAT_MAX) {
|
||||
for (auto & newpoint : _newpoints)
|
||||
for (auto& newpoint : _newpoints) {
|
||||
newpoint.z = static_cast<float>(polyFit.Value(newpoint.x, newpoint.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,11 +237,15 @@ bool AbstractPolygonTriangulator::TriangulatePolygon()
|
||||
{
|
||||
try {
|
||||
if (!this->_indices.empty() && this->_points.size() != this->_indices.size()) {
|
||||
Base::Console().Log("Triangulation: %d points <> %d indices\n", _points.size(), _indices.size());
|
||||
Base::Console().Log("Triangulation: %d points <> %d indices\n",
|
||||
_points.size(),
|
||||
_indices.size());
|
||||
return false;
|
||||
}
|
||||
bool ok = Triangulate();
|
||||
if (ok) Done();
|
||||
if (ok) {
|
||||
Done();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
@@ -264,8 +275,7 @@ void AbstractPolygonTriangulator::Discard()
|
||||
}
|
||||
|
||||
void AbstractPolygonTriangulator::Reset()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void AbstractPolygonTriangulator::Done()
|
||||
{
|
||||
@@ -286,33 +296,34 @@ bool EarClippingTriangulator::Triangulate()
|
||||
std::vector<PointIndex> result;
|
||||
|
||||
// Invoke the triangulator to triangulate this polygon.
|
||||
Triangulate::Process(pts,result);
|
||||
Triangulate::Process(pts, result);
|
||||
|
||||
// print out the results.
|
||||
size_t tcount = result.size()/3;
|
||||
size_t tcount = result.size() / 3;
|
||||
|
||||
bool ok = tcount+2 == _points.size();
|
||||
if (tcount > _points.size())
|
||||
return false; // no valid triangulation
|
||||
bool ok = tcount + 2 == _points.size();
|
||||
if (tcount > _points.size()) {
|
||||
return false; // no valid triangulation
|
||||
}
|
||||
|
||||
MeshGeomFacet clFacet;
|
||||
MeshFacet clTopFacet;
|
||||
for (size_t i=0; i<tcount; i++) {
|
||||
for (size_t i = 0; i < tcount; i++) {
|
||||
if (Triangulate::_invert) {
|
||||
clFacet._aclPoints[0] = _points[result[i*3+0]];
|
||||
clFacet._aclPoints[2] = _points[result[i*3+1]];
|
||||
clFacet._aclPoints[1] = _points[result[i*3+2]];
|
||||
clTopFacet._aulPoints[0] = result[i*3+0];
|
||||
clTopFacet._aulPoints[2] = result[i*3+1];
|
||||
clTopFacet._aulPoints[1] = result[i*3+2];
|
||||
clFacet._aclPoints[0] = _points[result[i * 3 + 0]];
|
||||
clFacet._aclPoints[2] = _points[result[i * 3 + 1]];
|
||||
clFacet._aclPoints[1] = _points[result[i * 3 + 2]];
|
||||
clTopFacet._aulPoints[0] = result[i * 3 + 0];
|
||||
clTopFacet._aulPoints[2] = result[i * 3 + 1];
|
||||
clTopFacet._aulPoints[1] = result[i * 3 + 2];
|
||||
}
|
||||
else {
|
||||
clFacet._aclPoints[0] = _points[result[i*3+0]];
|
||||
clFacet._aclPoints[1] = _points[result[i*3+1]];
|
||||
clFacet._aclPoints[2] = _points[result[i*3+2]];
|
||||
clTopFacet._aulPoints[0] = result[i*3+0];
|
||||
clTopFacet._aulPoints[1] = result[i*3+1];
|
||||
clTopFacet._aulPoints[2] = result[i*3+2];
|
||||
clFacet._aclPoints[0] = _points[result[i * 3 + 0]];
|
||||
clFacet._aclPoints[1] = _points[result[i * 3 + 1]];
|
||||
clFacet._aclPoints[2] = _points[result[i * 3 + 2]];
|
||||
clTopFacet._aulPoints[0] = result[i * 3 + 0];
|
||||
clTopFacet._aulPoints[1] = result[i * 3 + 1];
|
||||
clTopFacet._aulPoints[2] = result[i * 3 + 2];
|
||||
}
|
||||
|
||||
_triangles.push_back(clFacet);
|
||||
@@ -322,45 +333,60 @@ bool EarClippingTriangulator::Triangulate()
|
||||
return ok;
|
||||
}
|
||||
|
||||
float EarClippingTriangulator::Triangulate::Area(const std::vector<Base::Vector3f> &contour)
|
||||
float EarClippingTriangulator::Triangulate::Area(const std::vector<Base::Vector3f>& contour)
|
||||
{
|
||||
int n = contour.size();
|
||||
|
||||
float A=0.0f;
|
||||
float A = 0.0f;
|
||||
|
||||
for(int p=n-1,q=0; q<n; p=q++) {
|
||||
A+= contour[p].x*contour[q].y - contour[q].x*contour[p].y;
|
||||
for (int p = n - 1, q = 0; q < n; p = q++) {
|
||||
A += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
|
||||
}
|
||||
return A*0.5f;
|
||||
return A * 0.5f;
|
||||
}
|
||||
|
||||
/*
|
||||
InsideTriangle decides if a point P is Inside of the triangle
|
||||
defined by A, B, C.
|
||||
*/
|
||||
bool EarClippingTriangulator::Triangulate::InsideTriangle(float Ax, float Ay, float Bx,
|
||||
float By, float Cx, float Cy,
|
||||
float Px, float Py)
|
||||
bool EarClippingTriangulator::Triangulate::InsideTriangle(float Ax,
|
||||
float Ay,
|
||||
float Bx,
|
||||
float By,
|
||||
float Cx,
|
||||
float Cy,
|
||||
float Px,
|
||||
float Py)
|
||||
{
|
||||
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||||
float cCROSSap, bCROSScp, aCROSSbp;
|
||||
|
||||
ax = Cx - Bx; ay = Cy - By;
|
||||
bx = Ax - Cx; by = Ay - Cy;
|
||||
cx = Bx - Ax; cy = By - Ay;
|
||||
apx= Px - Ax; apy= Py - Ay;
|
||||
bpx= Px - Bx; bpy= Py - By;
|
||||
cpx= Px - Cx; cpy= Py - Cy;
|
||||
ax = Cx - Bx;
|
||||
ay = Cy - By;
|
||||
bx = Ax - Cx;
|
||||
by = Ay - Cy;
|
||||
cx = Bx - Ax;
|
||||
cy = By - Ay;
|
||||
apx = Px - Ax;
|
||||
apy = Py - Ay;
|
||||
bpx = Px - Bx;
|
||||
bpy = Py - By;
|
||||
cpx = Px - Cx;
|
||||
cpy = Py - Cy;
|
||||
|
||||
aCROSSbp = ax*bpy - ay*bpx;
|
||||
cCROSSap = cx*apy - cy*apx;
|
||||
bCROSScp = bx*cpy - by*cpx;
|
||||
aCROSSbp = ax * bpy - ay * bpx;
|
||||
cCROSSap = cx * apy - cy * apx;
|
||||
bCROSScp = bx * cpy - by * cpx;
|
||||
|
||||
return ((aCROSSbp >= FLOAT_EPS) && (bCROSScp >= FLOAT_EPS) && (cCROSSap >= FLOAT_EPS));
|
||||
}
|
||||
|
||||
bool EarClippingTriangulator::Triangulate::Snip(const std::vector<Base::Vector3f> &contour,
|
||||
int u,int v,int w,int n,int *V)
|
||||
bool EarClippingTriangulator::Triangulate::Snip(const std::vector<Base::Vector3f>& contour,
|
||||
int u,
|
||||
int v,
|
||||
int w,
|
||||
int n,
|
||||
int* V)
|
||||
{
|
||||
int p;
|
||||
float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
|
||||
@@ -374,15 +400,19 @@ bool EarClippingTriangulator::Triangulate::Snip(const std::vector<Base::Vector3f
|
||||
Cx = contour[V[w]].x;
|
||||
Cy = contour[V[w]].y;
|
||||
|
||||
if (FLOAT_EPS > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))))
|
||||
if (FLOAT_EPS > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (p=0;p<n;p++) {
|
||||
if( (p == u) || (p == v) || (p == w) ) continue;
|
||||
for (p = 0; p < n; p++) {
|
||||
if ((p == u) || (p == v) || (p == w)) {
|
||||
continue;
|
||||
}
|
||||
Px = contour[V[p]].x;
|
||||
Py = contour[V[p]].y;
|
||||
if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py))
|
||||
if (InsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -390,70 +420,87 @@ bool EarClippingTriangulator::Triangulate::Snip(const std::vector<Base::Vector3f
|
||||
|
||||
bool EarClippingTriangulator::Triangulate::_invert = false;
|
||||
|
||||
bool EarClippingTriangulator::Triangulate::Process(const std::vector<Base::Vector3f> &contour,
|
||||
std::vector<PointIndex> &result)
|
||||
bool EarClippingTriangulator::Triangulate::Process(const std::vector<Base::Vector3f>& contour,
|
||||
std::vector<PointIndex>& result)
|
||||
{
|
||||
/* allocate and initialize list of Vertices in polygon */
|
||||
|
||||
int n = contour.size();
|
||||
if ( n < 3 )
|
||||
if (n < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int *V = new int[n];
|
||||
int* V = new int[n];
|
||||
|
||||
/* we want a counter-clockwise polygon in V */
|
||||
|
||||
if (0.0f < Area(contour)) {
|
||||
for (int v=0; v<n; v++) V[v] = v;
|
||||
for (int v = 0; v < n; v++) {
|
||||
V[v] = v;
|
||||
}
|
||||
_invert = true;
|
||||
}
|
||||
// for(int v=0; v<n; v++) V[v] = (n-1)-v;
|
||||
// for(int v=0; v<n; v++) V[v] = (n-1)-v;
|
||||
else {
|
||||
for(int v=0; v<n; v++) V[v] = (n-1)-v;
|
||||
for (int v = 0; v < n; v++) {
|
||||
V[v] = (n - 1) - v;
|
||||
}
|
||||
_invert = false;
|
||||
}
|
||||
|
||||
int nv = n;
|
||||
|
||||
/* remove nv-2 Vertices, creating 1 triangle every time */
|
||||
int count = 2*nv; /* error detection */
|
||||
int count = 2 * nv; /* error detection */
|
||||
|
||||
for(int v=nv-1; nv>2; ) {
|
||||
for (int v = nv - 1; nv > 2;) {
|
||||
/* if we loop, it is probably a non-simple polygon */
|
||||
if (0 >= (count--)) {
|
||||
//** Triangulate: ERROR - probable bad polygon!
|
||||
delete [] V;
|
||||
delete[] V;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* three consecutive vertices in current polygon, <u,v,w> */
|
||||
int u = v ; if (nv <= u) u = 0; /* previous */
|
||||
v = u+1; if (nv <= v) v = 0; /* new v */
|
||||
int w = v+1; if (nv <= w) w = 0; /* next */
|
||||
int u = v;
|
||||
if (nv <= u) {
|
||||
u = 0; /* previous */
|
||||
}
|
||||
v = u + 1;
|
||||
if (nv <= v) {
|
||||
v = 0; /* new v */
|
||||
}
|
||||
int w = v + 1;
|
||||
if (nv <= w) {
|
||||
w = 0; /* next */
|
||||
}
|
||||
|
||||
if (Snip(contour,u,v,w,nv,V)) {
|
||||
int a,b,c,s,t;
|
||||
if (Snip(contour, u, v, w, nv, V)) {
|
||||
int a, b, c, s, t;
|
||||
|
||||
/* true names of the vertices */
|
||||
a = V[u]; b = V[v]; c = V[w];
|
||||
a = V[u];
|
||||
b = V[v];
|
||||
c = V[w];
|
||||
|
||||
/* output Triangle */
|
||||
result.push_back( a );
|
||||
result.push_back( b );
|
||||
result.push_back( c );
|
||||
result.push_back(a);
|
||||
result.push_back(b);
|
||||
result.push_back(c);
|
||||
|
||||
/* remove v from remaining polygon */
|
||||
for(s=v,t=v+1;t<nv;s++,t++)
|
||||
for (s = v, t = v + 1; t < nv; s++, t++) {
|
||||
V[s] = V[t];
|
||||
}
|
||||
|
||||
nv--;
|
||||
|
||||
/* reset error detection counter */
|
||||
count = 2*nv;
|
||||
count = 2 * nv;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] V;
|
||||
delete[] V;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -464,27 +511,31 @@ QuasiDelaunayTriangulator::QuasiDelaunayTriangulator() = default;
|
||||
|
||||
bool QuasiDelaunayTriangulator::Triangulate()
|
||||
{
|
||||
if (!EarClippingTriangulator::Triangulate())
|
||||
return false; // no valid triangulation
|
||||
if (!EarClippingTriangulator::Triangulate()) {
|
||||
return false; // no valid triangulation
|
||||
}
|
||||
|
||||
// For each internal edge get the adjacent facets. When doing an edge swap we must update
|
||||
// this structure.
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex> > aEdge2Face;
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex>> aEdge2Face;
|
||||
for (std::vector<MeshFacet>::iterator pI = _facets.begin(); pI != _facets.end(); ++pI) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
PointIndex ulPt0 = std::min<PointIndex>(pI->_aulPoints[i], pI->_aulPoints[(i+1)%3]);
|
||||
PointIndex ulPt1 = std::max<PointIndex>(pI->_aulPoints[i], pI->_aulPoints[(i+1)%3]);
|
||||
PointIndex ulPt0 = std::min<PointIndex>(pI->_aulPoints[i], pI->_aulPoints[(i + 1) % 3]);
|
||||
PointIndex ulPt1 = std::max<PointIndex>(pI->_aulPoints[i], pI->_aulPoints[(i + 1) % 3]);
|
||||
// ignore borderlines of the polygon
|
||||
if ((ulPt1-ulPt0)%(_points.size()-1) > 1)
|
||||
aEdge2Face[std::pair<PointIndex, PointIndex>(ulPt0, ulPt1)].push_back(pI - _facets.begin());
|
||||
if ((ulPt1 - ulPt0) % (_points.size() - 1) > 1) {
|
||||
aEdge2Face[std::pair<PointIndex, PointIndex>(ulPt0, ulPt1)].push_back(
|
||||
pI - _facets.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill up this list with all internal edges and perform swap edges until this list is empty
|
||||
std::list<std::pair<PointIndex, PointIndex> > aEdgeList;
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex> >::iterator pE;
|
||||
for (pE = aEdge2Face.begin(); pE != aEdge2Face.end(); ++pE)
|
||||
std::list<std::pair<PointIndex, PointIndex>> aEdgeList;
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex>>::iterator pE;
|
||||
for (pE = aEdge2Face.begin(); pE != aEdge2Face.end(); ++pE) {
|
||||
aEdgeList.push_back(pE->first);
|
||||
}
|
||||
|
||||
// to be sure to avoid an endless loop
|
||||
size_t uMaxIter = 5 * aEdge2Face.size();
|
||||
@@ -497,80 +548,95 @@ bool QuasiDelaunayTriangulator::Triangulate()
|
||||
uMaxIter--;
|
||||
|
||||
// get the adjacent facets to this edge
|
||||
pE = aEdge2Face.find( aEdge );
|
||||
pE = aEdge2Face.find(aEdge);
|
||||
|
||||
// this edge has been removed some iterations before
|
||||
if (pE == aEdge2Face.end())
|
||||
if (pE == aEdge2Face.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MeshFacet& rF1 = _facets[pE->second[0]];
|
||||
MeshFacet& rF2 = _facets[pE->second[1]];
|
||||
unsigned short side1 = rF1.Side(aEdge.first, aEdge.second);
|
||||
|
||||
Base::Vector3f cP1 = _points[rF1._aulPoints[side1]];
|
||||
Base::Vector3f cP2 = _points[rF1._aulPoints[(side1+1)%3]];
|
||||
Base::Vector3f cP3 = _points[rF1._aulPoints[(side1+2)%3]];
|
||||
Base::Vector3f cP2 = _points[rF1._aulPoints[(side1 + 1) % 3]];
|
||||
Base::Vector3f cP3 = _points[rF1._aulPoints[(side1 + 2) % 3]];
|
||||
|
||||
unsigned short side2 = rF2.Side(aEdge.first, aEdge.second);
|
||||
Base::Vector3f cP4 = _points[rF2._aulPoints[(side2+2)%3]];
|
||||
Base::Vector3f cP4 = _points[rF2._aulPoints[(side2 + 2) % 3]];
|
||||
|
||||
MeshGeomFacet cT1(cP1, cP2, cP3); float fMax1 = cT1.MaximumAngle();
|
||||
MeshGeomFacet cT2(cP2, cP1, cP4); float fMax2 = cT2.MaximumAngle();
|
||||
MeshGeomFacet cT3(cP4, cP3, cP1); float fMax3 = cT3.MaximumAngle();
|
||||
MeshGeomFacet cT4(cP3, cP4, cP2); float fMax4 = cT4.MaximumAngle();
|
||||
MeshGeomFacet cT1(cP1, cP2, cP3);
|
||||
float fMax1 = cT1.MaximumAngle();
|
||||
MeshGeomFacet cT2(cP2, cP1, cP4);
|
||||
float fMax2 = cT2.MaximumAngle();
|
||||
MeshGeomFacet cT3(cP4, cP3, cP1);
|
||||
float fMax3 = cT3.MaximumAngle();
|
||||
MeshGeomFacet cT4(cP3, cP4, cP2);
|
||||
float fMax4 = cT4.MaximumAngle();
|
||||
|
||||
float fMax12 = std::max<float>(fMax1, fMax2);
|
||||
float fMax34 = std::max<float>(fMax3, fMax4);
|
||||
|
||||
// We must make sure that the two adjacent triangles builds a convex polygon, otherwise
|
||||
// the swap edge operation is illegal
|
||||
Base::Vector3f cU = cP2-cP1;
|
||||
Base::Vector3f cV = cP4-cP3;
|
||||
Base::Vector3f cU = cP2 - cP1;
|
||||
Base::Vector3f cV = cP4 - cP3;
|
||||
// build a helper plane through cP1 that must separate cP3 and cP4
|
||||
Base::Vector3f cN1 = (cU % cV) % cU;
|
||||
if (((cP3-cP1)*cN1)*((cP4-cP1)*cN1) >= 0.0f)
|
||||
continue; // not convex
|
||||
if (((cP3 - cP1) * cN1) * ((cP4 - cP1) * cN1) >= 0.0f) {
|
||||
continue; // not convex
|
||||
}
|
||||
// build a helper plane through cP3 that must separate cP1 and cP2
|
||||
Base::Vector3f cN2 = (cU % cV) % cV;
|
||||
if (((cP1-cP3)*cN2)*((cP2-cP3)*cN2) >= 0.0f)
|
||||
continue; // not convex
|
||||
if (((cP1 - cP3) * cN2) * ((cP2 - cP3) * cN2) >= 0.0f) {
|
||||
continue; // not convex
|
||||
}
|
||||
|
||||
// ok, here we should perform a swap edge to minimize the maximum angle
|
||||
if (fMax12 > fMax34) {
|
||||
rF1._aulPoints[(side1+1)%3] = rF2._aulPoints[(side2+2)%3];
|
||||
rF2._aulPoints[(side2+1)%3] = rF1._aulPoints[(side1+2)%3];
|
||||
rF1._aulPoints[(side1 + 1) % 3] = rF2._aulPoints[(side2 + 2) % 3];
|
||||
rF2._aulPoints[(side2 + 1) % 3] = rF1._aulPoints[(side1 + 2) % 3];
|
||||
|
||||
// adjust the edge list
|
||||
for (int i=0; i<3; i++) {
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex> >::iterator it;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::map<std::pair<PointIndex, PointIndex>, std::vector<FacetIndex>>::iterator it;
|
||||
// first facet
|
||||
PointIndex ulPt0 = std::min<PointIndex>(rF1._aulPoints[i], rF1._aulPoints[(i+1)%3]);
|
||||
PointIndex ulPt1 = std::max<PointIndex>(rF1._aulPoints[i], rF1._aulPoints[(i+1)%3]);
|
||||
it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
|
||||
PointIndex ulPt0 =
|
||||
std::min<PointIndex>(rF1._aulPoints[i], rF1._aulPoints[(i + 1) % 3]);
|
||||
PointIndex ulPt1 =
|
||||
std::max<PointIndex>(rF1._aulPoints[i], rF1._aulPoints[(i + 1) % 3]);
|
||||
it = aEdge2Face.find(std::make_pair(ulPt0, ulPt1));
|
||||
if (it != aEdge2Face.end()) {
|
||||
if (it->second[0] == pE->second[1])
|
||||
if (it->second[0] == pE->second[1]) {
|
||||
it->second[0] = pE->second[0];
|
||||
else if (it->second[1] == pE->second[1])
|
||||
}
|
||||
else if (it->second[1] == pE->second[1]) {
|
||||
it->second[1] = pE->second[0];
|
||||
}
|
||||
aEdgeList.push_back(it->first);
|
||||
}
|
||||
|
||||
// second facet
|
||||
ulPt0 = std::min<PointIndex>(rF2._aulPoints[i], rF2._aulPoints[(i+1)%3]);
|
||||
ulPt1 = std::max<PointIndex>(rF2._aulPoints[i], rF2._aulPoints[(i+1)%3]);
|
||||
it = aEdge2Face.find( std::make_pair(ulPt0, ulPt1) );
|
||||
ulPt0 = std::min<PointIndex>(rF2._aulPoints[i], rF2._aulPoints[(i + 1) % 3]);
|
||||
ulPt1 = std::max<PointIndex>(rF2._aulPoints[i], rF2._aulPoints[(i + 1) % 3]);
|
||||
it = aEdge2Face.find(std::make_pair(ulPt0, ulPt1));
|
||||
if (it != aEdge2Face.end()) {
|
||||
if (it->second[0] == pE->second[0])
|
||||
if (it->second[0] == pE->second[0]) {
|
||||
it->second[0] = pE->second[1];
|
||||
else if (it->second[1] == pE->second[0])
|
||||
}
|
||||
else if (it->second[1] == pE->second[0]) {
|
||||
it->second[1] = pE->second[1];
|
||||
}
|
||||
aEdgeList.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we must remove the edge and replace it through the new edge
|
||||
PointIndex ulPt0 = std::min<PointIndex>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
|
||||
PointIndex ulPt1 = std::max<PointIndex>(rF1._aulPoints[(side1+1)%3], rF2._aulPoints[(side2+1)%3]);
|
||||
PointIndex ulPt0 = std::min<PointIndex>(rF1._aulPoints[(side1 + 1) % 3],
|
||||
rF2._aulPoints[(side2 + 1) % 3]);
|
||||
PointIndex ulPt1 = std::max<PointIndex>(rF1._aulPoints[(side1 + 1) % 3],
|
||||
rF2._aulPoints[(side2 + 1) % 3]);
|
||||
std::pair<PointIndex, PointIndex> aNewEdge = std::make_pair(ulPt0, ulPt1);
|
||||
aEdge2Face[aNewEdge] = pE->second;
|
||||
aEdge2Face.erase(pE);
|
||||
@@ -582,8 +648,10 @@ bool QuasiDelaunayTriangulator::Triangulate()
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
namespace MeshCore {
|
||||
namespace Triangulation {
|
||||
namespace MeshCore
|
||||
{
|
||||
namespace Triangulation
|
||||
{
|
||||
struct Vertex2d_Less
|
||||
{
|
||||
bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const
|
||||
@@ -605,15 +673,16 @@ struct Vertex2d_EqualTo
|
||||
{
|
||||
bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const
|
||||
{
|
||||
if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1 &&
|
||||
fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1)
|
||||
if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1
|
||||
&& fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Triangulation
|
||||
} // namespace MeshCore
|
||||
|
||||
DelaunayTriangulator::DelaunayTriangulator() = default;
|
||||
|
||||
@@ -625,39 +694,44 @@ bool DelaunayTriangulator::Triangulate()
|
||||
// sort the points ascending x,y coordinates
|
||||
std::sort(aPoints.begin(), aPoints.end(), Triangulation::Vertex2d_Less());
|
||||
// if there are two adjacent points whose distance is less then an epsilon
|
||||
if (std::adjacent_find(aPoints.begin(), aPoints.end(),
|
||||
Triangulation::Vertex2d_EqualTo()) < aPoints.end())
|
||||
if (std::adjacent_find(aPoints.begin(), aPoints.end(), Triangulation::Vertex2d_EqualTo())
|
||||
< aPoints.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_facets.clear();
|
||||
_triangles.clear();
|
||||
|
||||
std::vector<Wm4::Vector2d> akVertex;
|
||||
akVertex.reserve(_points.size());
|
||||
for (const auto & point : _points) {
|
||||
for (const auto& point : _points) {
|
||||
akVertex.emplace_back(static_cast<double>(point.x), static_cast<double>(point.y));
|
||||
}
|
||||
|
||||
Wm4::Delaunay2d del(static_cast<int>(akVertex.size()), &(akVertex[0]), 0.001, false, Wm4::Query::QT_INT64);
|
||||
Wm4::Delaunay2d del(static_cast<int>(akVertex.size()),
|
||||
&(akVertex[0]),
|
||||
0.001,
|
||||
false,
|
||||
Wm4::Query::QT_INT64);
|
||||
int iTQuantity = del.GetSimplexQuantity();
|
||||
std::vector<int> aiTVertex(static_cast<size_t>(3*iTQuantity));
|
||||
std::vector<int> aiTVertex(static_cast<size_t>(3 * iTQuantity));
|
||||
|
||||
bool succeeded = false;
|
||||
if (iTQuantity > 0) {
|
||||
size_t uiSize = static_cast<size_t>(3*iTQuantity)*sizeof(int);
|
||||
Wm4::System::Memcpy(&(aiTVertex[0]),uiSize,del.GetIndices(),uiSize);
|
||||
size_t uiSize = static_cast<size_t>(3 * iTQuantity) * sizeof(int);
|
||||
Wm4::System::Memcpy(&(aiTVertex[0]), uiSize, del.GetIndices(), uiSize);
|
||||
|
||||
// If H is the number of hull edges and N is the number of vertices,
|
||||
// then the triangulation must have 2*N-2-H triangles and 3*N-3-H
|
||||
// edges.
|
||||
int iEQuantity = 0;
|
||||
int* aiIndex = nullptr;
|
||||
del.GetHull(iEQuantity,aiIndex);
|
||||
del.GetHull(iEQuantity, aiIndex);
|
||||
int iUniqueVQuantity = del.GetUniqueVertexQuantity();
|
||||
int iTVerify = 2*iUniqueVQuantity - 2 - iEQuantity;
|
||||
int iTVerify = 2 * iUniqueVQuantity - 2 - iEQuantity;
|
||||
(void)iTVerify; // avoid warning in release build
|
||||
succeeded = (iTVerify == iTQuantity);
|
||||
int iEVerify = 3*iUniqueVQuantity - 3 - iEQuantity;
|
||||
int iEVerify = 3 * iUniqueVQuantity - 3 - iEQuantity;
|
||||
(void)iEVerify; // avoid warning about unused variable
|
||||
delete[] aiIndex;
|
||||
}
|
||||
@@ -665,8 +739,8 @@ bool DelaunayTriangulator::Triangulate()
|
||||
MeshGeomFacet triangle;
|
||||
MeshFacet facet;
|
||||
for (int i = 0; i < iTQuantity; i++) {
|
||||
for (int j=0; j<3; j++) {
|
||||
size_t index = static_cast<size_t>(aiTVertex[static_cast<size_t>(3*i+j)]);
|
||||
for (int j = 0; j < 3; j++) {
|
||||
size_t index = static_cast<size_t>(aiTVertex[static_cast<size_t>(3 * i + j)]);
|
||||
facet._aulPoints[j] = static_cast<PointIndex>(index);
|
||||
triangle._aclPoints[j].x = static_cast<float>(akVertex[index].X());
|
||||
triangle._aclPoints[j].y = static_cast<float>(akVertex[index].Y());
|
||||
@@ -693,9 +767,9 @@ bool FlatTriangulator::Triangulate()
|
||||
// sort the points ascending x,y coordinates
|
||||
std::sort(tmp.begin(), tmp.end(), Triangulation::Vertex2d_Less());
|
||||
// if there are two adjacent points whose distance is less then an epsilon
|
||||
if (std::adjacent_find(tmp.begin(), tmp.end(),
|
||||
Triangulation::Vertex2d_EqualTo()) < tmp.end() )
|
||||
if (std::adjacent_find(tmp.begin(), tmp.end(), Triangulation::Vertex2d_EqualTo()) < tmp.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_facets.clear();
|
||||
_triangles.clear();
|
||||
@@ -711,13 +785,12 @@ bool FlatTriangulator::Triangulate()
|
||||
}
|
||||
|
||||
void FlatTriangulator::PostProcessing(const std::vector<Base::Vector3f>&)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
ConstraintDelaunayTriangulator::ConstraintDelaunayTriangulator(float area)
|
||||
: fMaxArea(area)
|
||||
: fMaxArea(area)
|
||||
{
|
||||
// silent warning: -Wunused-private-field
|
||||
(void)fMaxArea;
|
||||
@@ -733,9 +806,9 @@ bool ConstraintDelaunayTriangulator::Triangulate()
|
||||
// sort the points ascending x,y coordinates
|
||||
std::sort(tmp.begin(), tmp.end(), Triangulation::Vertex2d_Less());
|
||||
// if there are two adjacent points whose distance is less then an epsilon
|
||||
if (std::adjacent_find(tmp.begin(), tmp.end(),
|
||||
Triangulation::Vertex2d_EqualTo()) < tmp.end() )
|
||||
if (std::adjacent_find(tmp.begin(), tmp.end(), Triangulation::Vertex2d_EqualTo()) < tmp.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_facets.clear();
|
||||
_triangles.clear();
|
||||
|
||||
Reference in New Issue
Block a user