-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdef3d.cpp
More file actions
273 lines (244 loc) · 7.8 KB
/
def3d.cpp
File metadata and controls
273 lines (244 loc) · 7.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// Copyright (c) 2018 Marek Dvoroznak
// Licensed under the MIT License.
#include "def3d.h"
#include "mesh3d.h"
#include <unordered_set>
#include <iostream>
#include <vector>
using namespace Eigen;
using namespace std;
Def3D::Def3D()
{
}
Def3D::~Def3D()
{
}
void Def3D::updatePtsAccordingToCPs(Mesh3D &inMesh)
{
for(const auto &it : cps) {
const CP &cp = *it.second;
inMesh.VCurr.row(cp.ptId) = cp.pos;
// p.weight = cp.weight;
// p.fixed = cp.fixed;
}
}
const Def3D::CP& Def3D::getCP(int index) const
{
const auto &it = cps.find(index);
if (it == cps.end()) {
throw(out_of_range("Def3D::getCP: index (" + to_string(index) + ") not found"));
}
return *it->second;
}
Def3D::CP& Def3D::getCP(int index)
{
return const_cast<CP&>(static_cast<const Def3D&>(*this).getCP(index));
}
const std::map<int,std::shared_ptr<Def3D::CP>>& Def3D::getCPs() const
{
return cps;
}
int Def3D::addCP(CP &cp)
{
cps[nextId] = make_shared<CP>(cp);
nextId++;
cpChangedNum++;
return nextId-1;
}
std::vector<int> Def3D::getControlPointsInsideRect(double x1, double y1, double x2, double y2, const Eigen::Matrix4d &M)
{
vector<int> ids;
for(const auto &it : cps) {
const CP &cp = *it.second;
const int cpId = it.first;
const Vector3d p = (M * cp.pos.homogeneous()).hnormalized();
if (p(0) >= x1 && p(1) >= y1 && p(0) <= x2 && p(1) <= y2) ids.push_back(cpId);
}
return ids;
}
int Def3D::getControlPoint(double x, double y, double radius, double depth, bool considerDepth, bool highestDepth, const Eigen::Matrix4d &M)
{
int ind = -1;
double extDepth = highestDepth ? -numeric_limits<double>::infinity() : numeric_limits<double>::infinity();
double minDist = numeric_limits<double>::infinity();
Vector3d pos(x,y,depth);
for(const auto &it : cps) {
CP &cp = *it.second;
const int cpId = it.first;
const Vector3d p = (M * cp.pos.homogeneous()).hnormalized();
double d;
if (considerDepth) d = (pos-p).norm();
else d = (pos.head(2)-p.head(2)).norm();
double depth = p(2);
if (d <= radius && d < minDist && (highestDepth ? depth>extDepth : depth<extDepth)) {
minDist = d;
extDepth = depth;
ind = cpId;
}
}
return ind;
}
bool Def3D::addControlPointOnFace(const MatrixXd &V, const MatrixXi &F, double x, double y, double planarRadius, bool highest, bool reverseDirection)
{
int index;
return addControlPointOnFace(V, F, x, y, planarRadius, highest, reverseDirection, index);
}
bool Def3D::addControlPointOnFace(const MatrixXd &V, const MatrixXi &F, double x, double y, double planarRadius, bool highest, bool reverseDirection, int &index, const Eigen::Matrix4d &M)
{
int ind = getControlPoint(x, y, planarRadius, 0, false, highest, M);
if (ind != -1) {
index = ind;
return false;
}
const MatrixXd VProj = (V.rowwise().homogeneous() * M.transpose()).rowwise().hnormalized();
int faceId = Mesh3D::getMeshFace(VProj, F, x, y, highest, reverseDirection);
if (faceId == -1) {
index = -1;
return false;
}
const VectorXi &facePts = F.row(faceId);
// choose the nearest point of the face
double min = numeric_limits<double>::infinity();
Vector2d pos(x,y);
int ptId = -1;
fora(i, 0, facePts.size()) {
const Vector3d &p = VProj.row(facePts(i));
double d = (p.head(2)-pos).norm();
if (d < min) {
min = d;
ptId = facePts[i];
}
}
ind = ptId;
// check if such control point is associated to a mesh point
for(const auto &it : cps) {
const int cpId = it.first;
const CP &cp = *it.second;
if (cp.ptId == ind) {
index = cpId;
return false;
}
}
double z = VProj(ind,2);
const Vector3d unproj = (M.inverse() * Vector3d(x,y,z).homogeneous()).hnormalized();
CP cp(unproj, cpDefaultFixed, cpDefaultWeight);
cp.prevPos = cp.pos;
cp.ptId = ind;
index = addCP(cp);
return true;
}
bool Def3D::addControlPoint(const MatrixXd &V, double x, double y, double planarRadius, bool highest, int &index, const MatrixXd &M)
{
int ind = getControlPoint(x, y, planarRadius, 0, false, highest);
if (ind != -1) {
index = ind;
return false;
}
const MatrixXd VProj = (V.rowwise().homogeneous() * M.transpose()).rowwise().hnormalized();
ind = Mesh3D::getMeshPoint(VProj, x, y, planarRadius, highest);
if (ind == -1) {
index = -1;
return false;
}
double z = VProj(ind,2);
const Vector3d unproj = (M.inverse() * Vector3d(x,y,z).homogeneous()).hnormalized();
CP cp(unproj, cpDefaultFixed, cpDefaultWeight);
cp.ptId = ind;
index = addCP(cp);
return true;
}
// Adds a control point to a mesh point that is the nearest to a point with [x,y,depth] coordinate
// within a radius only if there is not a control point associated to the mesh point already.
// Returns true if new control point was added and also it's index.
// Returns false if there is already a control point and also index of the control point.
// Returns false if there is not a mesh point within the radius and also index -1 in this case.
bool Def3D::addControlPoint(const MatrixXd &V, double x, double y, double radius, double depth, int &index, bool considerDepth)
{
int ind = getControlPoint(x, y, radius, depth, considerDepth, false);
if (ind != -1) {
index = ind;
return false;
}
ind = Mesh3D::getMeshPoint(V, x, y, radius, depth, considerDepth);
if (ind == -1) {
index = -1;
return false;
}
CP cp(Vector3d(x,y,depth), cpDefaultFixed, cpDefaultWeight);
cp.ptId = ind;
index = addCP(cp);
return true;
}
// Adds a control point to a mesh point that is the nearest to a point with [x,y,depth] coordinate
// within a radius and that is at the same time also not associated with some existing control point.
// It search the whole space around specified point and tries to find a "free" mesh point that is
// not associated with a control point.
// Returns true if new control point was added and also it's index.
// Returns false if there is already a control point and also index of the control point.
// Returns false if there is not a mesh point within the radius and also index -1 in this case.
bool Def3D::addControlPointExhaustive(const Eigen::MatrixXd &V, double x, double y, double radius, double depth, bool considerDepth, int &index)
{
const int nPts = V.rows();
const Vector3d pos(x,y,depth);
// find the nearest mesh point that is not associated with a control point
int bestInd = -1;
int occupiedInd = -1;
unordered_set<int> occupiedInds;
for(const auto &it : cps) {
int ptInd = it.second->ptId;
occupiedInds.insert(ptInd);
}
double min = numeric_limits<double>::infinity();
fora(ind, 0, nPts) {
const Vector3d &p = V.row(ind);
double d;
const Vector3d dvec = p-pos;
if (considerDepth) d = dvec.norm();
else d = dvec.head(2).norm();
if (d <= radius && d < min) {
// test if the mesh point is associated with a control point
const auto &it = occupiedInds.find(ind);
if (it == occupiedInds.end()) {
// this is the nearest point that is not associated
bestInd = ind;
min = d;
} else {
occupiedInd = *it;
}
}
}
if (bestInd != -1) {
CP cp(Vector3d(x,y,depth), cpDefaultFixed, cpDefaultWeight);
cp.ptId = bestInd;
index = addCP(cp);
return true;
}
index = occupiedInd;
return false;
}
bool Def3D::removeControlPoint(int index)
{
const auto &it = cps.find(index);
if (it == cps.end()) return false;
cps.erase(it);
cpChangedNum++;
return true;
}
bool Def3D::removeControlPoint(double x, double y, double radius, double depth, bool considerDepth)
{
int ind = getControlPoint(x, y, radius, depth, considerDepth, false);
return removeControlPoint(ind);
}
bool Def3D::removeLastControlPoint()
{
return removeControlPoint(nextId-1);
}
void Def3D::removeControlPoints()
{
cps.clear();
cpChangedNum++;
}
long Def3D::getCp2ptChangedNum() const
{
return cpChangedNum;
}