PeriDyno 1.0.0
Loading...
Searching...
No Matches
EarClipper.cpp
Go to the documentation of this file.
1#include "EarClipper.h"
2#include "Topology/PointSet.h"
6#include "EarClipper.h"
7#include <numeric>
8
9namespace dyno
10{
11 template<typename TDataType>
13 : ModelEditing<TDataType>()
14 {
15
16 }
17
18 template<typename TDataType>
23
24 template<typename TDataType>
26 {
27 auto d_coords = this->inPointSet()->getDataPtr()->getPoints();
28 CArray<Coord> c_coords;
29 c_coords.assign(d_coords);
30 std::vector<DataType3f::Coord> vts;
31 for (size_t i = 0; i < c_coords.size(); i++)
32 {
33 vts.push_back(c_coords[i]);
34 }
35 std::vector<TopologyModule::Triangle> outTriangles;
36 polyClip(vts,outTriangles);
37
38
39 }
40
41 Vec3f crossProduct(const Vec3f& a, const Vec3f& b) {
42 return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x };
43 }
44
45 float triangleArea(const Vec3f& a, const Vec3f& b, const Vec3f& c) {
46 Vec3f ab = b- a;
47 Vec3f ac = c- a;
48 Vec3f cross = crossProduct(ab, ac);
49 return 0.5f * std::sqrt(cross.x * cross.x + cross.y * cross.y + cross.z * cross.z);
50 }
51
52
53 Vec3f projectPointToTriangle(const Vec3f& A, const Vec3f& B, const Vec3f& C, const Vec3f& P) {
54 Vec3f AB = B - A;
55 Vec3f AC = C - A;
56 Vec3f normal = AB.cross(AC); // 计算法向量
57
58 // 计算点到平面的距离
59 float distance = std::fabs(normal.dot(P - A)) / normal.norm();
60
61 // 计算投影点
62 Vec3f projection = P - (distance * normal.normalize());
63 return projection;
64 }
65
66 // Check the point is inside the triangle
67 bool isPointInTriangle(const Vec3f& pt, const Vec3f& a, const Vec3f& b, const Vec3f& c) {
68
69 Vec3f projectP = projectPointToTriangle(a,b,c,pt);
70
71 float areaABC = triangleArea(a, b, c);
72 float areaABP = triangleArea(a, b, projectP);
73 float areaBCP = triangleArea(b, c, projectP);
74 float areaCAP = triangleArea(c, a, projectP);
75
76 // Check that the triangles are equal in area
77 return std::fabs(areaABC - (areaABP + areaBCP + areaCAP)) < 1e-6;
78 }
79
80 // Check poly ear
81 bool isEar(const std::vector<Vec3f>& vertices, const TopologyModule::Triangle& triangle,Vec3f n) {
82 const Vec3f& a = vertices[triangle[0]];
83 const Vec3f& b = vertices[triangle[1]];
84 const Vec3f& c = vertices[triangle[2]];
85 // Checke convex vertices
86 Vec3f ab = b- a;
87 Vec3f ac = c - a;
88 Vec3f cross = crossProduct(ab, ac);
89 if (cross.dot(n) < 0)
90 return false;
91 // Checke vertices in the triangle
92 for (size_t i = 0; i < vertices.size(); ++i) {
93 if (i == triangle[0] || i == triangle[1] || i == triangle[2]) {
94 continue; //is current triangle vetex,skip it
95 }
96 if (isPointInTriangle(vertices[i], a, b, c)) {
97 return false;
98 }
99 }
100
101 return true;
102 }
103
104 // Ear clip
105 std::vector<TopologyModule::Triangle> earClipping(const std::vector<Vec3f>& vertices) {
106 std::vector<TopologyModule::Triangle> triangles;
107 std::vector<int> indices(vertices.size());
108 std::iota(indices.begin(), indices.end(), 0); // init 0,1,2...
109
110 Vec3f stand_N;
111 for (size_t i = 0; i < vertices.size(); i++)
112 {
113 int prev = indices[(i + indices.size() - 1) % indices.size()];
114 int curr = indices[i];
115 int next = indices[(i + 1) % indices.size()];
116
117 stand_N += (vertices[prev] - vertices[curr]).cross(vertices[curr] - vertices[next]);
118 }
119 stand_N.normalize();
120
121 while (indices.size() > 2) {
122 bool earFound = false;
123 for (size_t i = 0; i < indices.size(); ++i) {
124 int prev = indices[(i + indices.size() - 1) % indices.size()];
125 int curr = indices[i];
126 int next = indices[(i + 1) % indices.size()];
127
128 TopologyModule::Triangle triangle(prev, curr, next);
129 if (isEar(vertices, triangle, stand_N)) {
130 triangles.push_back(triangle); // add this ear triangle;
131 indices.erase(indices.begin() + i); // delete vertex from vertices;
132 earFound = true;
133 break;
134 }
135 }
136 if (!earFound) {
137 for (int i = 0; i < indices.size() - 2; i++)
138 {
139 triangles.push_back(TopologyModule::Triangle(indices[0], indices[i + 1], indices[i + 2]));
140 }
141
142 break;
143 }
144 }
145
146 return triangles;
147 }
148
149
150
151 template<typename TDataType>
152 void EarClipper<TDataType>::polyClip(std::vector<DataType3f::Coord> vts, std::vector<TopologyModule::Triangle>& outTriangles)
153 {
154
155 outTriangles = earClipping(vts);
156
157
158 }
159
161}
#define DEFINE_CLASS(name)
Definition Object.h:140
void resetStates() override
void polyClip(std::vector< DataType3f::Coord > vts, std::vector< TopologyModule::Triangle > &outTriangles)
Vector< PointType, 3 > Triangle
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
Vec3f projectPointToTriangle(const Vec3f &A, const Vec3f &B, const Vec3f &C, const Vec3f &P)
bool isEar(const std::vector< Vec3f > &vertices, const TopologyModule::Triangle &triangle, Vec3f n)
DYN_FUNC Vector< T, 3 > cross(Vector< T, 3 > const &U, Vector< T, 3 > const &V)
Definition SimpleMath.h:211
float triangleArea(const Vec3f &a, const Vec3f &b, const Vec3f &c)
std::vector< TopologyModule::Triangle > earClipping(const std::vector< Vec3f > &vertices)
Vector< float, 3 > Vec3f
Definition Vector3D.h:93
Vec3f crossProduct(const Vec3f &a, const Vec3f &b)
bool isPointInTriangle(const Vec3f &pt, const Vec3f &a, const Vec3f &b, const Vec3f &c)
Array< T, DeviceType::CPU > CArray
Definition Array.h:151