10 #include <Eigen/Dense> 17 #include <unordered_set> 18 #include <unordered_map> 33 Edge(Eigen::Vector2d rP0, Eigen::Vector2d rP1)
39 const Eigen::Vector2d
P0()
const 44 const Eigen::Vector2d
P1()
const 51 bool result = (
P0() == rOther.
P0() &&
P1() == rOther.
P1()) || (
P0() == rOther.
P1() &&
P1() == rOther.
P0());
57 if (
P0() == rPoint ||
P1() == rPoint)
64 std::cout <<
"E: (" <<
P0().transpose() <<
") and (" <<
P1().transpose() <<
") \n";
69 return std::hash<double>()(
P0().x()) + std::hash<double>()(
P0().y()) + std::hash<double>()(
P1().x()) +
70 std::hash<double>()(
P1().y());
77 const Eigen::Vector2d e = mPoints[1] - mPoints[0];
78 const Eigen::Vector2d& n = rDirection;
80 double eXn = e.x() * n.y() - e.y() * n.x();
83 const Eigen::Vector2d D = rPoint - mPoints[0];
85 double edgeParameter = (D.x() * n.y() - D.y() * n.x()) / eXn;
86 double lineParameter = (D.y() * e.x() - D.x() * e.y()) / nXe;
88 if (edgeParameter < 0. || edgeParameter > 1.)
97 Eigen::Vector2d p =
P1() -
P0();
98 Eigen::Vector2d a = rPoint -
P0();
100 return (a - a.dot(p) * p / p.dot(p)).norm();
104 std::array<Eigen::Vector2d, 2> mPoints;
119 std::array<Eigen::Vector2d, 3> uniquePoints;
120 uniquePoints[0] = mEdges[0].P0();
121 uniquePoints[1] = mEdges[0].P1();
124 uniquePoints[2] = mEdges[1].P1();
126 uniquePoints[2] = mEdges[1].P0();
128 assert(uniquePoints[0] != uniquePoints[1]);
129 assert(uniquePoints[0] != uniquePoints[2]);
130 assert(uniquePoints[1] != uniquePoints[2]);
142 for (
auto edge : mEdges)
143 if (edge.Contains(rPoint))
150 for (
auto edge : mEdges)
168 auto points = GetUniquePoints();
169 Eigen::Vector2d
A = points[0];
170 Eigen::Vector2d B = points[1];
171 Eigen::Vector2d C = points[2];
173 double d = 2 * (A.x() * (B.y() - C.y()) + B.x() * (C.y() - A.y()) + C.x() * (A.y() - B.y()));
175 double x = A.dot(A) * (B.y() - C.y()) + B.dot(B) * (C.y() - A.y()) + C.dot(C) * (A.y() - B.y());
176 double y = A.dot(A) * (C.x() - B.x()) + B.dot(B) * (A.x() - C.x()) + C.dot(C) * (B.x() - A.x());
178 return Eigen::Vector2d(x / d, y / d);
183 auto points = GetUniquePoints();
184 Eigen::Vector2d
A = points[0];
185 Eigen::Vector2d B = points[1];
186 Eigen::Vector2d C = points[2];
187 Eigen::Vector2d D = rPoint;
190 Eigen::Vector2d v1 = B -
A;
191 Eigen::Vector2d v2 = C -
A;
193 double dir = v1.x() * v2.y() - v1.y() * v2.x();
202 if (A == D || B == D || C == D)
205 Eigen::Matrix3d matr;
207 matr(0, 0) = A.x() - D.x();
208 matr(1, 0) = B.x() - D.x();
209 matr(2, 0) = C.x() - D.x();
211 matr(0, 1) = A.y() - D.y();
212 matr(1, 1) = B.y() - D.y();
213 matr(2, 1) = C.y() - D.y();
215 matr(0, 2) = A.x() * A.x() - D.x() * D.x() + A.y() * A.y() - D.y() * D.y();
216 matr(1, 2) = B.x() * B.x() - D.x() * D.x() + B.y() * B.y() - D.y() * D.y();
217 matr(2, 2) = C.x() * C.x() - D.x() * D.x() + C.y() * C.y() - D.y() * D.y();
219 return matr.determinant() > 0;
224 auto points = GetUniquePoints();
226 << points[0].transpose() <<
" | " << points[1].transpose() <<
" | " << points[2].transpose()
231 std::array<Edge, 3> mEdges;
244 SortAndRemoveDoublicates();
255 Eigen::Vector2d center(0., 0.);
256 for (
auto point : mPoints)
258 center /= mPoints.size();
260 std::map<double, Eigen::Vector2d> anglesPoints;
263 for (
auto vp : mPoints)
265 double angle = atan2(vp.x() - center.x(), vp.y() - center.y());
266 anglesPoints[angle] = vp;
269 std::vector<Eigen::Vector2d> sortedUniqueVoronoiPoints;
273 double delta = 1.e-6;
274 double lastAngle = -10;
275 for (
auto pair : anglesPoints)
277 double currentAngle = pair.first;
278 if (currentAngle - lastAngle > delta)
280 sortedUniqueVoronoiPoints.push_back(pair.second);
281 lastAngle = currentAngle;
284 mPoints = sortedUniqueVoronoiPoints;
291 int numPoints = mPoints.size();
292 for (
int i = 0; i < numPoints; ++i)
293 mEdges.push_back(
Edge(mPoints[i], mPoints[(i + 1) % numPoints]));
299 int intersectionCounter = 0;
300 Eigen::Vector2d anyDirection(1., 0.);
302 for (
auto edge : mEdges)
303 if (edge.GetIntersectionLineParameter(rPoint, anyDirection) > 0.)
304 intersectionCounter++;
306 return intersectionCounter % 2 == 1;
312 for (
auto edge : mEdges)
314 double lineParameter = edge.GetIntersectionLineParameter(rP0, rP1 - rP0);
315 if (lineParameter > 0. and lineParameter < 1.)
325 std::vector<Eigen::Vector2d> intersections;
326 double closestLineParameter = 1.e10;
328 for (
auto edge : mEdges)
330 double lineParameter = edge.GetIntersectionLineParameter(rPoint, rDirection);
331 if (lineParameter > 1.e-10)
332 closestLineParameter = std::min(closestLineParameter, lineParameter);
337 return Eigen::Vector2d(rPoint + rDirection * closestLineParameter);
343 for (
unsigned int i = 0; i < mEdges.size(); ++i)
352 auto e1 = mEdges[rEdge1];
353 auto e2 = mEdges[rEdge2];
354 if (e2.Contains(e1.P0()))
356 if (e2.Contains(e1.P1()))
359 throw "There is no point on both rEdge1 and rEdge2";
365 std::vector<Eigen::Vector2d> points = mPoints;
366 auto it = std::find(points.begin(), points.end(), rPoint);
367 assert(it != points.end());
379 int numPointsOnBoundary = 0;
380 int numPoints = mPoints.size();
382 for (
auto vp : mPoints)
384 numPointsOnBoundary++;
386 if (numPointsOnBoundary != 2)
392 for (
int i = 0; i < numPoints; ++i)
395 int e1 = rBoundary.
GetEdgeIndex(mPoints[(i + 1) % numPoints]);
397 if (e0 == -1 || e1 == -1 || e0 == e1)
403 auto originalPoints = mPoints;
405 mPoints.push_back(boundaryPoint);
406 SortAndRemoveDoublicates();
408 if (PointIsInside(rIP))
415 std::cout <<
"This happens!" << std::endl;
417 mPoints = originalPoints;
420 for (
auto point : otherBoundaryPoints)
421 mPoints.push_back(point);
423 SortAndRemoveDoublicates();
431 std::vector<Edge> mEdges;
432 std::vector<Eigen::Vector2d> mPoints;
439 DelaunayVoronoi(
const std::vector<Eigen::Vector2d>& rPoints,
bool rCalculateInTransformedSystem)
441 , mCalculateInTransformedSystem(rCalculateInTransformedSystem)
443 if (mCalculateInTransformedSystem)
447 void SetBoundary(
const std::vector<Eigen::Vector2d>& rBoundaryPoints)
449 auto points = rBoundaryPoints;
450 if (mCalculateInTransformedSystem)
458 if (mTriangulation.size() == 0)
459 CalculateDelaunayTriangulation();
461 return mTriangulation;
466 if (mVoronoiPolygons.size() == 0)
467 CalculateVoronoiPolygons();
469 return mVoronoiPolygons;
475 T << 1, .5, 0, std::sqrt(0.75);
477 for (
auto& point : rPoints)
487 T << 1, .5, 0, std::sqrt(0.75);
489 auto invT = T.inverse();
491 for (
auto& point : rPoints)
501 mTriangulation.clear();
504 Eigen::Vector2d superMin = mPoints[0];
505 Eigen::Vector2d superMax = mPoints[0];
506 for (
auto point : mPoints)
508 superMin = superMin.cwiseMin(point);
509 superMax = superMax.cwiseMax(point);
512 auto size = superMax - superMin;
513 superMin -= 3 * size;
514 superMax += 3 * size;
516 std::array<Eigen::Vector2d, 4> sP;
518 sP[1] = Eigen::Vector2d(superMax.x(), superMin.y());
520 sP[3] = Eigen::Vector2d(superMin.x(), superMax.y());
527 for (
auto point : mPoints)
529 std::list<const Triangle*> badTriangles;
530 for (
Triangle& triangle : mTriangulation)
532 if (triangle.CircumcircleContainsPoint(point))
533 badTriangles.push_back(&triangle);
536 std::list<Edge> polygon;
537 for (
const Triangle* badTriangle : badTriangles)
539 for (
Edge edge : badTriangle->GetEdges())
541 bool edgeNotShared =
true;
542 for (
const Triangle* otherBadTriangle : badTriangles)
544 if (*otherBadTriangle == *badTriangle)
547 if (otherBadTriangle->Contains(edge))
549 edgeNotShared =
false;
554 polygon.push_back(edge);
558 for (
const Triangle* triangle : badTriangles)
559 mTriangulation.remove(*triangle);
562 for (
Edge edge : polygon)
563 mTriangulation.push_back(
Triangle(edge,
Edge(point, edge.P0()),
Edge(point, edge.P1())));
566 std::list<const Triangle*> trianglesToErase;
569 for (
Triangle& triangle : mTriangulation)
570 for (
auto superPoint : sP)
571 if (triangle.Contains(superPoint))
572 trianglesToErase.push_back(&triangle);
574 for (
const Triangle* triangleToErase : trianglesToErase)
575 mTriangulation.remove(*triangleToErase);
579 file.open(
"triangles.dat");
580 for (
auto triangle : mTriangulation)
582 auto points = triangle.GetUniquePoints();
583 file << points[0].transpose() <<
'\n' 584 << points[1].transpose() <<
'\n' 585 << points[2].transpose() <<
'\n' 586 << points[0].transpose() <<
"\n \n";
594 if (mBoundary.GetPoints().size() == 0)
595 throw "Define a the boundary first! [AddBoundary()]!";
597 int num = mPoints.size();
598 mVoronoiPolygons.resize(num);
600 if (mTriangulation.size() == 0)
601 CalculateDelaunayTriangulation();
606 size_t operator()(
const Edge& x)
const 613 std::unordered_map<Edge, std::vector<const Triangle*>, EdgeHash> edgeToTriangle;
614 for (
const Triangle& triangle : mTriangulation)
615 for (
Edge edge : triangle.GetEdges())
616 edgeToTriangle[edge].push_back(&triangle);
618 for (
int p = 0; p < num; ++p)
620 auto point = mPoints[p];
622 std::list<Edge> edges;
623 for (
auto pair : edgeToTriangle)
625 const Edge& edge = pair.first;
627 edges.push_back(edge);
630 std::vector<Eigen::Vector2d> voronoiPoints;
632 for (
const Edge& edge : edges)
634 std::vector<const Triangle*> triangles = edgeToTriangle[edge];
635 assert(triangles.size() > 0);
636 assert(triangles.size() <= 2);
638 Eigen::Vector2d p0, p1;
640 if (triangles.size() == 1)
643 p0 = triangles[0]->GetCircumcenter();
646 Eigen::Vector2d e = edge.
P1() - edge.P0();
647 Eigen::Vector2d edgePoint = edge.P0() + e.dot(p0 - edge.P0()) / e.dot(e) * e;
648 Eigen::Vector2d n = edgePoint - p0;
654 n = Eigen::Vector2d(e[1], -e[0]);
662 bool intersectsAgain =
false;
664 for (
Edge edgeTri : triangles[0]->GetEdges())
669 double t = edgeTri.GetIntersectionLineParameter(p0, n);
671 intersectsAgain =
true;
677 if (not mBoundary.PointIsInside(p0))
686 p0 = mBoundary.GetClosestIntersection(p0, n);
688 p1 = mBoundary.GetClosestIntersection(p0, n);
691 if (triangles.size() == 2)
694 p0 = triangles[0]->GetCircumcenter();
695 p1 = triangles[1]->GetCircumcenter();
697 if (not mBoundary.PointIsInside(p0))
701 if (not mBoundary.SegmentIntersects(p0, p1))
705 p0 = mBoundary.GetClosestIntersection(p0, p1 - p0);
708 if (not mBoundary.PointIsInside(p1))
712 p1 = mBoundary.GetClosestIntersection(p1, p0 - p1);
716 voronoiPoints.push_back(p0);
717 voronoiPoints.push_back(p1);
720 Polygon voronoiCell(voronoiPoints);
722 mVoronoiPolygons[p] = voronoiCell;
727 std::vector<std::vector<unsigned int>>& rVisuCellIndices)
729 if (mVoronoiPolygons.size() == 0)
730 CalculateVoronoiPolygons();
733 rVisuCellIndices.resize(mPoints.size());
735 for (
auto polygon : mVoronoiPolygons)
736 for (
auto point : polygon.GetPoints())
737 if (std::find(rVisuPoints.begin(), rVisuPoints.end(), point) == rVisuPoints.end())
738 rVisuPoints.push_back(point);
740 for (
unsigned int iIP = 0; iIP < mPoints.size(); ++iIP)
742 auto polygon = mVoronoiPolygons[iIP];
745 std::vector<unsigned int> visuCell;
746 for (
auto vPoint : polygon.GetPoints())
748 visuCell.push_back(std::find(rVisuPoints.begin(), rVisuPoints.end(), vPoint) - rVisuPoints.begin());
749 rVisuCellIndices[iIP] = visuCell;
752 if (mCalculateInTransformedSystem)
753 TransformInverse(rVisuPoints);
762 std::vector<std::array<unsigned int, 3>>& rVisuCellIndices,
763 std::vector<unsigned int>& rCellIPIndex)
765 rVisuCellIndices.clear();
766 rCellIPIndex.clear();
768 std::vector<std::vector<unsigned int>> polygonCells;
769 CalculateVisualizationCellsPolygon(rVisuPoints, polygonCells);
770 for (
unsigned int iIP = 0; iIP < polygonCells.size(); ++iIP)
772 auto& polygon = polygonCells[iIP];
774 unsigned int p0 = polygon[0];
776 for (
unsigned int i = 1; i < polygon.size() - 1; ++i)
778 unsigned int p1 = polygon[i];
779 unsigned int p2 = polygon[i + 1];
781 rVisuCellIndices.push_back({{p0, p1, p2}});
782 rCellIPIndex.push_back(iIP);
789 std::vector<Eigen::Vector2d> mPoints;
790 std::list<Triangle> mTriangulation;
791 std::vector<Polygon> mVoronoiPolygons;
793 bool mCalculateInTransformedSystem;
void CalculateVoronoiPolygons()
Definition: DelaunayVoronoi.h:592
bool PointIsInside(Eigen::Vector2d rPoint) const
counts the intersections with the edges. The point rPoint is inside the polygon if that number is odd...
Definition: DelaunayVoronoi.h:297
const NuTo::DofType d("...", 1)
void CalculateDelaunayTriangulation()
special thanks to https://en.wikipedia.org/wiki/Bowyer%E2%80%93Watson_algorithm
Definition: DelaunayVoronoi.h:499
void UpdateEdges()
Definition: DelaunayVoronoi.h:288
void CalculateVisualizationCellsPolygon(std::vector< Eigen::Vector2d > &rVisuPoints, std::vector< std::vector< unsigned int >> &rVisuCellIndices)
Definition: DelaunayVoronoi.h:726
Eigen::Vector2d GetCircumcenter() const
Definition: DelaunayVoronoi.h:166
bool operator==(const Triangle &rOther) const
Definition: DelaunayVoronoi.h:156
Eigen::Vector2d GetClosestIntersection(Eigen::Vector2d rPoint, Eigen::Vector2d rDirection) const
A line from rPoint in rDirection may intersect multiple times with the polygon.
Definition: DelaunayVoronoi.h:323
MeshFem Transform(MeshFem &&oldMesh, std::function< Eigen::VectorXd(Eigen::VectorXd)> f)
transforms a mesh with a given transformation function f
Definition: UnitMeshFem.cpp:117
Definition: DelaunayVoronoi.h:107
DelaunayVoronoi(const std::vector< Eigen::Vector2d > &rPoints, bool rCalculateInTransformedSystem)
Definition: DelaunayVoronoi.h:439
Triangle(Edge rE0, Edge rE1, Edge rE2)
Definition: DelaunayVoronoi.h:110
void Info() const
Definition: DelaunayVoronoi.h:222
double GetIntersectionLineParameter(const Eigen::Vector2d rPoint, const Eigen::Vector2d rDirection) const
returns the line parameter l of the line rPoint + l * rDirection where the line intersects with the e...
Definition: DelaunayVoronoi.h:75
Definition: DelaunayVoronoi.h:234
bool operator==(const Edge &rOther) const
Definition: DelaunayVoronoi.h:49
const Eigen::Vector2d P0() const
Definition: DelaunayVoronoi.h:39
Definition: DelaunayVoronoi.h:26
Eigen::Vector2d GetPointOnBothEdges(int rEdge1, int rEdge2) const
Returns a boundary point that is contained by both rEdge1 and rEdge2.
Definition: DelaunayVoronoi.h:350
const Eigen::Vector2d P1() const
Definition: DelaunayVoronoi.h:44
std::list< Triangle > GetDelaunayTriangulation()
Definition: DelaunayVoronoi.h:456
Definition: DelaunayVoronoi.h:436
void AddIntersectionWithBoundary(const Polygon &rBoundary, const Eigen::Vector2d &rIP)
add points to this polygon if it intersects with the boundary If the polygon contains two neighboring...
Definition: DelaunayVoronoi.h:376
void SetBoundary(const std::vector< Eigen::Vector2d > &rBoundaryPoints)
Definition: DelaunayVoronoi.h:447
void CalculateVisualizationCellsTriangle(std::vector< Eigen::Vector2d > &rVisuPoints, std::vector< std::array< unsigned int, 3 >> &rVisuCellIndices, std::vector< unsigned int > &rCellIPIndex)
calculates the polygon visualization cells and triangulates them again
Definition: DelaunayVoronoi.h:761
bool Contains(Edge rEdge) const
Definition: DelaunayVoronoi.h:148
void SortAndRemoveDoublicates()
Definition: DelaunayVoronoi.h:252
double GetDistance(Eigen::Vector2d rPoint) const
calculates the (perpendicular) distance of rPoint to the edge
Definition: DelaunayVoronoi.h:95
Polygon(std::vector< Eigen::Vector2d > rPoints)
Definition: DelaunayVoronoi.h:241
Polygon()
Definition: DelaunayVoronoi.h:237
bool Contains(const Eigen::Vector2d &rPoint) const
Definition: DelaunayVoronoi.h:140
Edge()
Definition: DelaunayVoronoi.h:29
std::vector< Polygon > GetVoronoiCells()
Definition: DelaunayVoronoi.h:464
size_t GetHash() const
Definition: DelaunayVoronoi.h:67
bool SegmentIntersects(Eigen::Vector2d rP0, Eigen::Vector2d rP1) const
returns true, if the polygon intersects the segment rP0-rP1
Definition: DelaunayVoronoi.h:310
void Info() const
Definition: DelaunayVoronoi.h:62
std::array< Eigen::Vector2d, 3 > GetUniquePoints() const
Definition: DelaunayVoronoi.h:117
void TransformInverse(std::vector< Eigen::Vector2d > &rPoints)
Definition: DelaunayVoronoi.h:484
void Transform(std::vector< Eigen::Vector2d > &rPoints)
Definition: DelaunayVoronoi.h:472
std::vector< Eigen::Vector2d > GetOtherPointsOnBoundary(Eigen::Vector2d rPoint) const
returns all mPoints except rPoint
Definition: DelaunayVoronoi.h:363
bool CircumcircleContainsPoint(const Eigen::Vector2d &rPoint) const
Definition: DelaunayVoronoi.h:181
std::vector< Eigen::Vector2d > GetPoints()
Definition: DelaunayVoronoi.h:247
Edge(Eigen::Vector2d rP0, Eigen::Vector2d rP1)
Definition: DelaunayVoronoi.h:33
const Eigen::MatrixBase< OtherDerived > abs() const
elementwise absolute value of the matrix
Definition: MatrixBaseAddons.h:17
std::array< Edge, 3 > GetEdges() const
Definition: DelaunayVoronoi.h:135
bool Contains(Eigen::Vector2d rPoint) const
Definition: DelaunayVoronoi.h:55
int GetEdgeIndex(Eigen::Vector2d rPoint) const
Returns the index of the edge that contains rPoint.
Definition: DelaunayVoronoi.h:341
int A
Definition: TimeIntegrationResultForce.py:7