Skip to content

Commit 886dc47

Browse files
committed
Added rosy field options
1 parent 8a363be commit 886dc47

File tree

5 files changed

+189
-2
lines changed

5 files changed

+189
-2
lines changed

include/holonomy/holonomy/field/frame_field.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,48 @@ void write_frame_field(
8989
const Eigen::MatrixXd& kappa,
9090
const Eigen::MatrixXi& period_jump);
9191

92+
/**
93+
* @brief Write a rosy field to file.
94+
*
95+
* The format is
96+
* ```
97+
* <num_faces>
98+
* 4
99+
* <dx> <dy> <dz>
100+
* ...
101+
* ```
102+
* where d is a representative direction on the face.
103+
*
104+
* @param output_filename: file location to serialize the frame field
105+
* @param V: mesh vertices
106+
* @param F: mesh faces
107+
* @param reference_field: per-face reference tangent direction matrix
108+
* @param theta: offset angles of a representative cross field direction relative to the reference
109+
*/
110+
void write_rosy_field(
111+
const std::string& output_filename,
112+
const Eigen::MatrixXd& V,
113+
const Eigen::MatrixXi& F,
114+
const Eigen::MatrixXd& reference_field,
115+
const Eigen::VectorXd& theta);
116+
117+
/**
118+
* @brief Load a rosy field from file.
119+
*
120+
* The format is
121+
* ```
122+
* <num_faces>
123+
* 4
124+
* <dx> <dy> <dz>
125+
* ...
126+
* ```
127+
* where d is a representative direction on the face.
128+
*
129+
* @param input_filename: file location of the rosy field
130+
* @return per-face representative field direction
131+
*/
132+
Eigen::MatrixXd load_rosy_field(const std::string& input_filename);
133+
92134
/**
93135
* @brief Load a frame field from file.
94136
*

include/holonomy/holonomy/field/intrinsic_field.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ class IntrinsicNRosyField
4242
Eigen::VectorXd& face_angle,
4343
Eigen::MatrixXd& corner_kappa,
4444
Eigen::MatrixXi& corner_period_jump) const;
45+
void get_field(
46+
const Mesh<Scalar>& m,
47+
const std::vector<int>& vtx_reindex,
48+
const Eigen::MatrixXi& F,
49+
Eigen::VectorXi& reference_corner,
50+
Eigen::VectorXd& face_angle,
51+
Eigen::MatrixXd& corner_kappa,
52+
Eigen::MatrixXi& corner_period_jump) const;
4553

4654
void get_fixed_faces(
4755
const Mesh<Scalar>& m,
@@ -61,6 +69,16 @@ class IntrinsicNRosyField
6169
const Eigen::VectorXd& face_theta,
6270
const Eigen::MatrixXd& corner_kappa,
6371
const Eigen::MatrixXi& corner_period_jump);
72+
void set_field(
73+
const Mesh<Scalar>& m,
74+
const std::vector<int>& vtx_reindex,
75+
const Eigen::MatrixXi& F,
76+
const Eigen::VectorXd& face_theta,
77+
const Eigen::MatrixXd& corner_kappa,
78+
const Eigen::MatrixXi& corner_period_jump);
79+
void set_theta(
80+
const Mesh<Scalar>& m,
81+
const Eigen::VectorXd& face_theta);
6482

6583
Scalar min_angle = 0.;
6684

src/holonomy/field/frame_field.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,31 @@ Eigen::MatrixXd generate_frame_field(
7373
return igl::rotate_vectors(reference_field, theta, B1, B2);
7474
}
7575

76+
void write_rosy_field(
77+
const std::string& output_filename,
78+
const Eigen::MatrixXd& V,
79+
const Eigen::MatrixXi& F,
80+
const Eigen::MatrixXd& reference_field,
81+
const Eigen::VectorXd& theta)
82+
{
83+
Eigen::MatrixXd rosy_field = generate_frame_field(V, F, reference_field, theta);
84+
85+
std::ofstream field_file(output_filename, std::ios::out | std::ios::trunc);
86+
field_file << F.rows() << std::endl;
87+
field_file << "4" << std::endl;
88+
for (int f = 0; f < F.rows(); ++f)
89+
{
90+
for (int j : {0 , 1, 2})
91+
{
92+
field_file << std::fixed << std::setprecision(17) << rosy_field(f, j) << " ";
93+
}
94+
95+
field_file << std::endl;
96+
}
97+
98+
field_file.close();
99+
}
100+
76101
void write_frame_field(
77102
const std::string& output_filename,
78103
const Eigen::MatrixXd& reference_field,
@@ -114,6 +139,48 @@ void write_frame_field(
114139
field_file.close();
115140
}
116141

142+
Eigen::MatrixXd load_rosy_field(const std::string& input_filename)
143+
{
144+
// Open file
145+
spdlog::debug("opening field at {}", input_filename);
146+
std::ifstream input_file(input_filename);
147+
if (!input_file) return {};
148+
149+
// get number of faces
150+
std::string line;
151+
std::getline(input_file, line);
152+
std::istringstream iss(line);
153+
int num_faces;
154+
iss >> num_faces;
155+
spdlog::debug("{} faces", num_faces);
156+
std::getline(input_file, line); // skip start line
157+
158+
// initialize vectors
159+
Eigen::MatrixXd frame_field(num_faces, 3);
160+
161+
// Read file one face at a time
162+
int f = 0;
163+
while ((f < num_faces) && (std::getline(input_file, line))) {
164+
std::istringstream iss(line);
165+
for (int i : {0 , 1, 2})
166+
{
167+
iss >> frame_field(f, i);
168+
}
169+
170+
++f;
171+
}
172+
173+
if (num_faces != f)
174+
{
175+
spdlog::error("Number of faces inconsistent with number of lines");
176+
}
177+
178+
// Close file
179+
input_file.close();
180+
return frame_field;
181+
}
182+
183+
117184
std::tuple<Eigen::MatrixXd, Eigen::VectorXd, Eigen::MatrixXd, Eigen::MatrixXi>
118185
load_frame_field(const std::string& filename)
119186
{

src/holonomy/field/intrinsic_field.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,7 +1686,6 @@ std::vector<Scalar> generate_cones_from_rotation_form_FIXME(
16861686
void IntrinsicNRosyField::compute_principal_matchings(const Mesh<Scalar>& m)
16871687
{
16881688
int num_halfedges = m.n_halfedges();
1689-
VectorX rotation_form(num_halfedges);
16901689
for (int hij = 0; hij < num_halfedges; ++hij) {
16911690
if (hij < m.opp[hij]) continue;
16921691
int hji = m.opp[hij];
@@ -2551,5 +2550,58 @@ void IntrinsicNRosyField::set_field(
25512550
}
25522551
}
25532552

2553+
void IntrinsicNRosyField::set_theta(
2554+
const Mesh<Scalar>& m,
2555+
const Eigen::VectorXd& face_theta)
2556+
{
2557+
int num_faces = m.n_faces();
2558+
for (int fijk = 0; fijk < num_faces; ++fijk)
2559+
{
2560+
// get reference halfedge
2561+
int hij = m.h[fijk];
2562+
2563+
// only process original faces
2564+
if (m.type[hij] == 2) continue;
2565+
2566+
// record face angles
2567+
theta[fijk] = Scalar(face_theta[fijk]);
2568+
2569+
// skip doubling on closed mesh
2570+
if (m.type[hij] == 0) continue;
2571+
2572+
// invert theta on reflected face
2573+
int fjik = m.f[m.R[hij]];
2574+
theta[fjik] = M_PI - theta[fijk];
2575+
}
2576+
}
2577+
2578+
2579+
void IntrinsicNRosyField::set_field(
2580+
const Mesh<Scalar>& m,
2581+
const std::vector<int>& vtx_reindex,
2582+
const Eigen::MatrixXi& F,
2583+
const Eigen::VectorXd& face_theta,
2584+
const Eigen::MatrixXd& corner_kappa,
2585+
const Eigen::MatrixXi& corner_period_jump)
2586+
{
2587+
std::vector<int> face_reindex;
2588+
arange(F.rows(), face_reindex);
2589+
set_field(m, vtx_reindex, F, face_reindex, face_theta, corner_kappa, corner_period_jump);
2590+
}
2591+
2592+
void IntrinsicNRosyField::get_field(
2593+
const Mesh<Scalar>& m,
2594+
const std::vector<int>& vtx_reindex,
2595+
const Eigen::MatrixXi& F,
2596+
Eigen::VectorXi& reference_corner,
2597+
Eigen::VectorXd& face_theta,
2598+
Eigen::MatrixXd& corner_kappa,
2599+
Eigen::MatrixXi& corner_period_jump) const
2600+
{
2601+
std::vector<int> face_reindex;
2602+
arange(F.rows(), face_reindex);
2603+
get_field(m, vtx_reindex, F, face_reindex, reference_corner, face_theta, corner_kappa, corner_period_jump);
2604+
}
2605+
25542606
} // namespace Holonomy
25552607
} // namespace Penner

src/holonomy/interface.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,14 @@ std::tuple<Mesh<Scalar>, std::vector<int>> generate_mesh(
315315
const std::vector<Scalar>& Th_hat,
316316
std::vector<int> free_cones)
317317
{
318+
// set all flat cones if no cones given
319+
std::vector<Scalar> Th_hat_temp = Th_hat;
320+
if (Th_hat.empty())
321+
{
322+
Th_hat_temp = std::vector<Scalar>(V.rows(), 2 * PI);
323+
}
324+
325+
318326
// Convert VF mesh to halfedge
319327
bool fix_boundary = false;
320328
std::vector<int> vtx_reindex, indep_vtx, dep_vtx, v_rep, bnd_loops;
@@ -323,7 +331,7 @@ std::tuple<Mesh<Scalar>, std::vector<int>> generate_mesh(
323331
F,
324332
uv,
325333
F_uv,
326-
Th_hat,
334+
Th_hat_temp,
327335
vtx_reindex,
328336
indep_vtx,
329337
dep_vtx,

0 commit comments

Comments
 (0)