123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/ETManifoldMesh.h>
- #include <Mathematics/PrimalQuery2.h>
- #include <Mathematics/Line.h>
- #include <set>
- namespace WwiseGTE
- {
- template <typename InputType, typename ComputeType>
- class Delaunay2
- {
- public:
-
-
- virtual ~Delaunay2() = default;
- Delaunay2()
- :
- mEpsilon((InputType)0),
- mDimension(0),
- mLine(Vector2<InputType>::Zero(), Vector2<InputType>::Zero()),
- mNumVertices(0),
- mNumUniqueVertices(0),
- mNumTriangles(0),
- mVertices(nullptr),
- mIndex{ { { 0, 1 }, { 1, 2 }, { 2, 0 } } }
- {
- }
-
-
-
-
-
-
- bool operator()(int numVertices, Vector2<InputType> const* vertices, InputType epsilon)
- {
- mEpsilon = std::max(epsilon, (InputType)0);
- mDimension = 0;
- mLine.origin = Vector2<InputType>::Zero();
- mLine.direction = Vector2<InputType>::Zero();
- mNumVertices = numVertices;
- mNumUniqueVertices = 0;
- mNumTriangles = 0;
- mVertices = vertices;
- mGraph.Clear();
- mIndices.clear();
- mAdjacencies.clear();
- mDuplicates.resize(std::max(numVertices, 3));
- int i, j;
- if (mNumVertices < 3)
- {
-
- return false;
- }
- IntrinsicsVector2<InputType> info(mNumVertices, vertices, mEpsilon);
- if (info.dimension == 0)
- {
-
- return false;
- }
- if (info.dimension == 1)
- {
-
- mDimension = 1;
- mLine = Line2<InputType>(info.origin, info.direction[0]);
- return false;
- }
- mDimension = 2;
-
- mComputeVertices.resize(mNumVertices);
- mQuery.Set(mNumVertices, &mComputeVertices[0]);
- for (i = 0; i < mNumVertices; ++i)
- {
- for (j = 0; j < 2; ++j)
- {
- mComputeVertices[i][j] = vertices[i][j];
- }
- }
-
-
-
- if (!info.extremeCCW)
- {
- std::swap(info.extreme[1], info.extreme[2]);
- }
- if (!mGraph.Insert(info.extreme[0], info.extreme[1], info.extreme[2]))
- {
- return false;
- }
-
-
-
- std::set<ProcessedVertex> processed;
- for (i = 0; i < 3; ++i)
- {
- j = info.extreme[i];
- processed.insert(ProcessedVertex(vertices[j], j));
- mDuplicates[j] = j;
- }
- for (i = 0; i < mNumVertices; ++i)
- {
- ProcessedVertex v(vertices[i], i);
- auto iter = processed.find(v);
- if (iter == processed.end())
- {
- if (!Update(i))
- {
-
-
- return false;
- }
- processed.insert(v);
- mDuplicates[i] = i;
- }
- else
- {
- mDuplicates[i] = iter->location;
- }
- }
- mNumUniqueVertices = static_cast<int>(processed.size());
-
- std::map<std::shared_ptr<Triangle>, int> permute;
- i = -1;
- permute[nullptr] = i++;
- for (auto const& element : mGraph.GetTriangles())
- {
- permute[element.second] = i++;
- }
-
- mNumTriangles = static_cast<int>(mGraph.GetTriangles().size());
- int numindices = 3 * mNumTriangles;
- if (numindices > 0)
- {
- mIndices.resize(numindices);
- mAdjacencies.resize(numindices);
- i = 0;
- for (auto const& element : mGraph.GetTriangles())
- {
- std::shared_ptr<Triangle> tri = element.second;
- for (j = 0; j < 3; ++j, ++i)
- {
- mIndices[i] = tri->V[j];
- mAdjacencies[i] = permute[tri->T[j].lock()];
- }
- }
- }
- return true;
- }
-
-
-
-
- inline InputType GetEpsilon() const
- {
- return mEpsilon;
- }
- inline int GetDimension() const
- {
- return mDimension;
- }
- inline Line2<InputType> const& GetLine() const
- {
- return mLine;
- }
-
- inline int GetNumVertices() const
- {
- return mNumVertices;
- }
- inline int GetNumUniqueVertices() const
- {
- return mNumUniqueVertices;
- }
- inline int GetNumTriangles() const
- {
- return mNumTriangles;
- }
- inline Vector2<InputType> const* GetVertices() const
- {
- return mVertices;
- }
- inline PrimalQuery2<ComputeType> const& GetQuery() const
- {
- return mQuery;
- }
- inline ETManifoldMesh const& GetGraph() const
- {
- return mGraph;
- }
- inline std::vector<int> const& GetIndices() const
- {
- return mIndices;
- }
- inline std::vector<int> const& GetAdjacencies() const
- {
- return mAdjacencies;
- }
-
-
-
- inline std::vector<int> const& GetDuplicates() const
- {
- return mDuplicates;
- }
-
-
-
-
-
-
- bool GetHull(std::vector<int>& hull) const
- {
- if (mDimension == 2)
- {
-
-
- int numEdges = 0;
- for (auto adj : mAdjacencies)
- {
- if (adj == -1)
- {
- ++numEdges;
- }
- }
- if (numEdges > 0)
- {
-
- hull.resize(2 * numEdges);
- int current = 0, i = 0;
- for (auto adj : mAdjacencies)
- {
- if (adj == -1)
- {
- int tri = i / 3, j = i % 3;
- hull[current++] = mIndices[3 * tri + j];
- hull[current++] = mIndices[3 * tri + ((j + 1) % 3)];
- }
- ++i;
- }
- return true;
- }
- else
- {
- LogError("Unexpected. There must be at least one triangle.");
- }
- }
- else
- {
- LogError("The dimension must be 2.");
- }
- }
-
-
-
-
- bool GetIndices(int i, std::array<int, 3>& indices) const
- {
- if (mDimension == 2)
- {
- int numTriangles = static_cast<int>(mIndices.size() / 3);
- if (0 <= i && i < numTriangles)
- {
- indices[0] = mIndices[3 * i];
- indices[1] = mIndices[3 * i + 1];
- indices[2] = mIndices[3 * i + 2];
- return true;
- }
- }
- else
- {
- LogError("The dimension must be 2.");
- }
- return false;
- }
-
-
-
-
- bool GetAdjacencies(int i, std::array<int, 3>& adjacencies) const
- {
- if (mDimension == 2)
- {
- int numTriangles = static_cast<int>(mIndices.size() / 3);
- if (0 <= i && i < numTriangles)
- {
- adjacencies[0] = mAdjacencies[3 * i];
- adjacencies[1] = mAdjacencies[3 * i + 1];
- adjacencies[2] = mAdjacencies[3 * i + 2];
- return true;
- }
- }
- else
- {
- LogError("The dimension must be 2.");
- }
- return false;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- struct SearchInfo
- {
- int initialTriangle;
- int numPath;
- std::vector<int> path;
- int finalTriangle;
- std::array<int, 3> finalV;
- };
- int GetContainingTriangle(Vector2<InputType> const& p, SearchInfo& info) const
- {
- if (mDimension == 2)
- {
- Vector2<ComputeType> test{ p[0], p[1] };
- int numTriangles = static_cast<int>(mIndices.size() / 3);
- info.path.resize(numTriangles);
- info.numPath = 0;
- int triangle;
- if (0 <= info.initialTriangle && info.initialTriangle < numTriangles)
- {
- triangle = info.initialTriangle;
- }
- else
- {
- info.initialTriangle = 0;
- triangle = 0;
- }
-
- for (int i = 0; i < numTriangles; ++i)
- {
- int ibase = 3 * triangle;
- int const* v = &mIndices[ibase];
- info.path[info.numPath++] = triangle;
- info.finalTriangle = triangle;
- info.finalV[0] = v[0];
- info.finalV[1] = v[1];
- info.finalV[2] = v[2];
- if (mQuery.ToLine(test, v[0], v[1]) > 0)
- {
- triangle = mAdjacencies[ibase];
- if (triangle == -1)
- {
- info.finalV[0] = v[0];
- info.finalV[1] = v[1];
- info.finalV[2] = v[2];
- return -1;
- }
- continue;
- }
- if (mQuery.ToLine(test, v[1], v[2]) > 0)
- {
- triangle = mAdjacencies[ibase + 1];
- if (triangle == -1)
- {
- info.finalV[0] = v[1];
- info.finalV[1] = v[2];
- info.finalV[2] = v[0];
- return -1;
- }
- continue;
- }
- if (mQuery.ToLine(test, v[2], v[0]) > 0)
- {
- triangle = mAdjacencies[ibase + 2];
- if (triangle == -1)
- {
- info.finalV[0] = v[2];
- info.finalV[1] = v[0];
- info.finalV[2] = v[1];
- return -1;
- }
- continue;
- }
- return triangle;
- }
- }
- else
- {
- LogError("The dimension must be 2.");
- }
- return -1;
- }
- protected:
-
- typedef ETManifoldMesh::Triangle Triangle;
- bool GetContainingTriangle(int i, std::shared_ptr<Triangle>& tri) const
- {
- int numTriangles = static_cast<int>(mGraph.GetTriangles().size());
- for (int t = 0; t < numTriangles; ++t)
- {
- int j;
- for (j = 0; j < 3; ++j)
- {
- int v0 = tri->V[mIndex[j][0]];
- int v1 = tri->V[mIndex[j][1]];
- if (mQuery.ToLine(i, v0, v1) > 0)
- {
-
- auto adjTri = tri->T[j].lock();
- if (adjTri)
- {
-
- tri = adjTri;
- break;
- }
- else
- {
-
-
-
-
- return false;
- }
- }
- }
- if (j == 3)
- {
-
-
- return true;
- }
- }
- LogError("Unexpected termination of loop.");
- }
- bool GetAndRemoveInsertionPolygon(int i, std::set<std::shared_ptr<Triangle>>& candidates,
- std::set<EdgeKey<true>>& boundary)
- {
-
- ETManifoldMesh polygon;
- while (candidates.size() > 0)
- {
- std::shared_ptr<Triangle> tri = *candidates.begin();
- candidates.erase(candidates.begin());
- for (int j = 0; j < 3; ++j)
- {
- auto adj = tri->T[j].lock();
- if (adj && candidates.find(adj) == candidates.end())
- {
- int a0 = adj->V[0];
- int a1 = adj->V[1];
- int a2 = adj->V[2];
- if (mQuery.ToCircumcircle(i, a0, a1, a2) <= 0)
- {
-
- candidates.insert(adj);
- }
- }
- }
- if (!polygon.Insert(tri->V[0], tri->V[1], tri->V[2]))
- {
- return false;
- }
- if (!mGraph.Remove(tri->V[0], tri->V[1], tri->V[2]))
- {
- return false;
- }
- }
-
- for (auto const& element : polygon.GetTriangles())
- {
- std::shared_ptr<Triangle> tri = element.second;
- for (int j = 0; j < 3; ++j)
- {
- if (!tri->T[j].lock())
- {
- boundary.insert(EdgeKey<true>(tri->V[mIndex[j][0]], tri->V[mIndex[j][1]]));
- }
- }
- }
- return true;
- }
- bool Update(int i)
- {
-
-
-
- auto const& tmap = mGraph.GetTriangles();
- std::shared_ptr<Triangle> tri = tmap.begin()->second;
- if (GetContainingTriangle(i, tri))
- {
-
-
-
-
-
- std::set<std::shared_ptr<Triangle>> candidates;
- candidates.insert(tri);
-
-
-
- std::set<EdgeKey<true>> boundary;
- if (!GetAndRemoveInsertionPolygon(i, candidates, boundary))
- {
- return false;
- }
-
-
- for (auto const& key : boundary)
- {
- int v0 = key.V[0];
- int v1 = key.V[1];
- if (mQuery.ToLine(i, v0, v1) < 0)
- {
- if (!mGraph.Insert(i, v0, v1))
- {
- return false;
- }
- }
-
-
- }
- }
- else
- {
-
-
-
-
-
- std::set<EdgeKey<true>> hull;
- for (auto const& element : tmap)
- {
- std::shared_ptr<Triangle> t = element.second;
- for (int j = 0; j < 3; ++j)
- {
- if (!t->T[j].lock())
- {
- hull.insert(EdgeKey<true>(t->V[mIndex[j][0]], t->V[mIndex[j][1]]));
- }
- }
- }
-
-
-
- auto const& emap = mGraph.GetEdges();
- std::set<std::shared_ptr<Triangle>> candidates;
- std::set<EdgeKey<true>> visible;
- for (auto const& key : hull)
- {
- int v0 = key.V[0];
- int v1 = key.V[1];
- if (mQuery.ToLine(i, v0, v1) > 0)
- {
- auto iter = emap.find(EdgeKey<false>(v0, v1));
- if (iter != emap.end() && iter->second->T[1].lock() == nullptr)
- {
- auto adj = iter->second->T[0].lock();
- if (adj && candidates.find(adj) == candidates.end())
- {
- int a0 = adj->V[0];
- int a1 = adj->V[1];
- int a2 = adj->V[2];
- if (mQuery.ToCircumcircle(i, a0, a1, a2) <= 0)
- {
-
- candidates.insert(adj);
- }
- else
- {
-
-
- visible.insert(key);
- }
- }
- }
- else
- {
-
-
-
-
-
-
- return false;
- }
- }
- }
-
-
- std::set<EdgeKey<true>> boundary;
- if (!GetAndRemoveInsertionPolygon(i, candidates, boundary))
- {
- return false;
- }
-
-
-
- for (auto const& key : boundary)
- {
- int v0 = key.V[0];
- int v1 = key.V[1];
- if (mQuery.ToLine(i, v0, v1) < 0)
- {
-
- if (!mGraph.Insert(i, v0, v1))
- {
- return false;
- }
- }
- }
- for (auto const& key : visible)
- {
- if (!mGraph.Insert(i, key.V[1], key.V[0]))
- {
- return false;
- }
- }
- }
- return true;
- }
-
-
-
-
-
-
-
-
- InputType mEpsilon;
- int mDimension;
- Line2<InputType> mLine;
-
-
- std::vector<Vector2<ComputeType>> mComputeVertices;
- PrimalQuery2<ComputeType> mQuery;
-
- int mNumVertices;
- int mNumUniqueVertices;
- int mNumTriangles;
- Vector2<InputType> const* mVertices;
- ETManifoldMesh mGraph;
- std::vector<int> mIndices;
- std::vector<int> mAdjacencies;
-
-
-
-
- struct ProcessedVertex
- {
- ProcessedVertex() = default;
- ProcessedVertex(Vector2<InputType> const& inVertex, int inLocation)
- :
- vertex(inVertex),
- location(inLocation)
- {
- }
- bool operator<(ProcessedVertex const& v) const
- {
- return vertex < v.vertex;
- }
- Vector2<InputType> vertex;
- int location;
- };
- std::vector<int> mDuplicates;
-
-
-
-
-
-
- std::array<std::array<int, 2>, 3> mIndex;
- };
- }
|