Skip to content

Commit 6ce86c4

Browse files
committed
Merged feature into main
1 parent 796d0f8 commit 6ce86c4

File tree

214 files changed

+28550
-3784
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

214 files changed

+28550
-3784
lines changed

CMakeLists.txt

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ if (PROJECT_IS_TOP_LEVEL)
1515

1616
# Alternative library options
1717
option(USE_MULTIPRECISION "Use high precision floating point" OFF)
18-
option(USE_EMBREE "Use Embree for rendering" OFF)
1918
option(USE_SUITESPARSE "Use suite sparse methods for matrix inversion" ON)
2019
option(USE_COMISO "Use Comiso for field generation" ON)
2120

@@ -35,11 +34,11 @@ endif()
3534

3635
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
3736

38-
#include(boost)
37+
include(boost)
3938
#include(eigen)
4039

4140
# Optionally get multiprecision libraries
42-
if(USE_MULTIPRECISION)
41+
if(USE_MULTIPRECISION OR USE_MULTIPRECISION_OVERLAY)
4342
# Turning this on activates mpfr in the conformal code
4443
option(LIBIGL_COPYLEFT_CGAL "Use CGAL" ON)
4544
add_compile_definitions(WITH_MPFR)
@@ -48,6 +47,9 @@ if(USE_MULTIPRECISION)
4847
include_directories(${GMP_INCLUDE_DIR})
4948
link_directories(${MPFR_LIBRARIES_DIR})
5049
endif()
50+
if(USE_MULTIPRECISION)
51+
add_compile_definitions(MULTIPRECISION)
52+
endif()
5153

5254
# Optionally get frame field libraries
5355
if (USE_COMISO)
@@ -64,9 +66,6 @@ if (RENDER_TEXTURE)
6466
option(LIBIGL_GLFW "Use GLFW" ON)
6567
option(LIBIGL_PNG "Use PNG" ON)
6668
endif()
67-
if (USE_EMBREE)
68-
option(LIBIGL_EMBREE "Use EMBREE" ON)
69-
endif()
7069

7170
# Set compile definitions
7271
add_compile_definitions(_USE_MATH_DEFINES)
@@ -79,9 +78,6 @@ endif()
7978
if (RENDER_TEXTURE)
8079
add_compile_definitions(RENDER_TEXTURE)
8180
endif()
82-
if (USE_EMBREE)
83-
add_compile_definitions(USE_EMBREE)
84-
endif()
8581
if(USE_PYBIND)
8682
add_compile_definitions(PYBIND)
8783
endif()
@@ -97,12 +93,20 @@ if(USE_SUITESPARSE)
9793
endif()
9894

9995
# Get external libraries
96+
include(boost)
10097
include(conformal_ideal_delaunay)
10198
include(libigl)
10299
include(spectra)
103100
include(cli11)
104101
include(json)
105102
include(geometry-central)
103+
#include(symmetric-dirichlet)
104+
105+
include(directional)
106+
add_library(DirectionalLib INTERFACE)
107+
target_include_directories(DirectionalLib SYSTEM INTERFACE
108+
${directional_SOURCE_DIR}/include
109+
)
106110

107111
# Optionally create rendering library
108112
if(RENDER_TEXTURE)
@@ -119,12 +123,6 @@ if(RENDER_TEXTURE)
119123
plot
120124
)
121125

122-
# Link in embree if enabled
123-
if(USE_EMBREE)
124-
target_link_libraries(rendering PUBLIC
125-
igl::embree
126-
)
127-
endif()
128126

129127
# Change rendering libraries from null to singleton
130128
set(RENDER_LIBRARIES
@@ -144,6 +142,9 @@ endif()
144142
# Optionally build pybind
145143
if(USE_PYBIND)
146144
include(pybind11)
145+
set(PYBIND_LIBRARIES
146+
pybind11::module
147+
)
147148
endif()
148149

149150
# Install executables to bin directory

cmake/directional.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
include(FetchContent)
2+
FetchContent_Declare(
3+
directional
4+
SYSTEM
5+
GIT_REPOSITORY https://github.com/avaxman/Directional.git
6+
)
7+
FetchContent_MakeAvailable(directional)
8+

cmake/symmetric-dirichlet.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
include(FetchContent)
2+
FetchContent_Declare(
3+
symmetric-dirichlet
4+
SYSTEM
5+
GIT_REPOSITORY https://github.com/rjc8237/symmetric-dirichlet.git
6+
GIT_TAG energy_dev
7+
)
8+
FetchContent_MakeAvailable(symmetric-dirichlet)
9+
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#pragma once
2+
3+
#include "feature/core/common.h"
4+
5+
namespace Penner {
6+
namespace Feature {
7+
8+
/**
9+
* @brief Representation of a boundary edge path. If the boundary edge is unflipped and lies along
10+
* the symmetry line, then this is just a single halfedge in the primal mesh. If the edge is
11+
* flipped, then this is a path of halfedges in the mesh copy (type 2) homotopic to the symmetry
12+
* line segment between the two vertices on the boundary.
13+
*
14+
*/
15+
class BoundaryPath
16+
{
17+
public:
18+
/**
19+
* @brief Construct a new Boundary Path object from the given boundary vertex
20+
* to the next ccw vertex on the boundary.
21+
*
22+
* @param m: underlying mesh
23+
* @param vertex_index: starting vertex index (must be on the boundary)
24+
*/
25+
BoundaryPath(const Mesh<Scalar>& m, int vertex_index);
26+
27+
/**
28+
* @brief Compute the number of edges in the boundary path
29+
*
30+
* @return number of edges
31+
*/
32+
int size() const { return m_halfedge_path.size(); }
33+
34+
/**
35+
* @brief Compute the length of the boundary path in the given mesh
36+
*
37+
* @param m: underlying mesh
38+
* @return length of the current path in the mesh
39+
*/
40+
Scalar compute_length(const Mesh<Scalar>& m) const;
41+
42+
/**
43+
* @brief Compute the (doubled) log length of the boundary path in the given mesh
44+
*
45+
* @param m: underlying mesh
46+
* @return log length of the current path in the mesh
47+
*/
48+
Scalar compute_log_length(const Mesh<Scalar>& m) const;
49+
50+
/**
51+
* @brief Compute the Jacobian of the length of the boundary path in the given mesh with
52+
* respect to the halfedge lengths
53+
*
54+
* The Jacobian is represented as a sparse vector with index, value pairs.
55+
*
56+
* @param m: underlying mesh
57+
* @return jacobian of length
58+
*/
59+
std::vector<std::pair<int, Scalar>> compute_length_jacobian(const Mesh<Scalar>& m) const;
60+
61+
/**
62+
* @brief Compute the Jacobian of the log length of the boundary path in the given mesh with
63+
* respect to the halfedge lengths
64+
*
65+
* The Jacobian is represented as a sparse vector with index, value pairs.
66+
*
67+
* @param m: underlying mesh
68+
* @return jacobian of log length
69+
*/
70+
std::vector<std::pair<int, Scalar>> compute_log_length_jacobian(const Mesh<Scalar>& m) const;
71+
72+
/**
73+
* @brief Check if the boundary path is valid
74+
*
75+
* @param m: underlying mesh
76+
* @return true if the path is valid
77+
* @return false otherwise
78+
*/
79+
bool is_valid_boundary_path(const Mesh<Scalar>& m) const;
80+
81+
/**
82+
* @brief Get the start vertex of the path
83+
*
84+
* @return start vertex index
85+
*/
86+
int get_start_vertex() const { return m_start_vertex; }
87+
88+
/**
89+
* @brief Get the ending vertex of the path, which is the next original boundary vertex
90+
* counterclockwise on the symmetry line.
91+
*
92+
* @return end vertex index
93+
*/
94+
int get_end_vertex() const { return m_end_vertex; }
95+
96+
/**
97+
* @brief Get the representative path of halfedges from the start to end vertex;
98+
*
99+
* This is either a single primal halfedge or a path of doubled halfedges bounding
100+
* the facets crossing the symmetry line between the vertices.
101+
*
102+
* @return path from the start to end vertex
103+
*/
104+
const std::vector<int>& get_halfedge_path() const { return m_halfedge_path; }
105+
106+
/**
107+
* @brief Get transverse halfedges crossing the line of symmetry.
108+
*
109+
* One halfedge per transverse edge is returned.
110+
*
111+
* @return transverse halfedges.
112+
*/
113+
const std::vector<int>& get_transverse_edges() const { return m_transverse_edges; }
114+
115+
private:
116+
int m_start_vertex;
117+
int m_end_vertex;
118+
119+
Scalar compute_tri_length(Scalar side_length, Scalar base_length) const;
120+
Scalar compute_quad_length(
121+
Scalar side_length,
122+
Scalar first_base_length,
123+
Scalar second_base_length) const;
124+
Scalar compute_tri_side_derivative(Scalar side_length, Scalar base_length) const;
125+
Scalar compute_tri_base_derivative(Scalar side_length, Scalar base_length) const;
126+
Scalar compute_quad_side_derivative(
127+
Scalar side_length,
128+
Scalar first_base_length,
129+
Scalar second_base_length) const;
130+
Scalar compute_quad_base_derivative(
131+
Scalar side_length,
132+
Scalar first_base_length,
133+
Scalar second_base_length) const;
134+
135+
// Paths between boundary vertices contained in the primal mesh
136+
std::vector<int> m_halfedge_path;
137+
138+
// Transverse edges crossing the symmetry line
139+
std::vector<int> m_transverse_edges;
140+
};
141+
142+
/**
143+
* @brief Build all boundary paths for a mesh and a map to the corresponding halfedges.
144+
*
145+
* @param m: underlying mesh
146+
* @return list of boundary paths
147+
* @return map from boundary path indices to halfedge indices
148+
*/
149+
std::tuple<std::vector<BoundaryPath>, MatrixX> build_boundary_paths(const Mesh<Scalar>& m);
150+
151+
} // namespace Feature
152+
} // namespace Penner
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#pragma once
2+
3+
#include "holonomy/interface.h"
4+
#include "holonomy/core/common.h"
5+
#include "holonomy/core/dual_loop.h"
6+
#include "holonomy/holonomy/marked_penner_cone_metric.h"
7+
#include "holonomy/holonomy/newton.h"
8+
9+
namespace Penner {
10+
namespace Feature {
11+
12+
using Holonomy::DualLoop;
13+
using Holonomy::MarkedPennerConeMetric;
14+
using Holonomy::NewtonParameters;
15+
using Holonomy::MarkedMetricParameters;
16+
typedef std::array<int, 2> VertexEdge;
17+
18+
/**
19+
* @brief Compute the square of a scalar.
20+
*
21+
* @param x: value to square
22+
* @return squared value
23+
*/
24+
inline Scalar square(Scalar x)
25+
{
26+
return x * x;
27+
}
28+
29+
/**
30+
* @brief Compute the one ring of halfedges emenating from a mesh vertex.
31+
*
32+
* @param m: mesh
33+
* @param vertex_index: index of a vertex in the mesh
34+
* @return halfedges emenating from a given vertex
35+
*/
36+
std::vector<int> generate_vertex_one_ring(const Mesh<Scalar>& m, int vertex_index);
37+
38+
/**
39+
* @brief Determine if a VF mesh is manifold
40+
* @param F: mesh faces
41+
* @return true iff the mesh is edge and vertex manifold
42+
*/
43+
bool is_manifold(const Eigen::MatrixXi& F);
44+
45+
/**
46+
* @brief Compute salient geometry aligned field directions for a mesh.
47+
*
48+
* The parabolic anisotropy used for the relative threshold is ||k2| - |k1|| / max(|k1|, |k2|)
49+
* This measurement is near 0 for parabolic regions and near 1 for highly anisotropic regions
50+
*
51+
* @param V: mesh vertices
52+
* @param F: mesh faces
53+
* @param radius: (optional) vertex radius for fitting a smooth surface for field estimation
54+
* @param abs_threshold: (optional) minimum threshold for mean anisotropy of principal curvatures
55+
* @param rel_threshold: (optional) minimum threshold for parabolic anisotropy of principal curvatures
56+
* @return |F|x3 matrix of per face directions
57+
* @return per face mask indicating whether a direction is salient or not
58+
*/
59+
std::tuple<Eigen::MatrixXd, std::vector<bool>> compute_field_direction(
60+
const Eigen::MatrixXd& V,
61+
const Eigen::MatrixXi& F,
62+
int radius=5,
63+
Scalar abs_threshold=1.,
64+
Scalar rel_threshold=0.9);
65+
66+
/**
67+
* @brief Reindex VF mesh.
68+
*
69+
* @param V: mesh vertices
70+
* @param F: mesh faces
71+
* @param vtx_reindex: map from old to new vertex indices
72+
* @return reindexed mesh vertices
73+
* @return reindexed mesh faces
74+
*/
75+
std::tuple<Eigen::MatrixXd, Eigen::MatrixXi> reindex_mesh(
76+
const Eigen::MatrixXd& V,
77+
const Eigen::MatrixXi& F,
78+
const std::vector<int>& vtx_reindex);
79+
80+
/**
81+
* @brief Reindex list of edge endpoints under vertex reindexing.
82+
*
83+
* @param endpoints: list of vertex endpoints before reindexing
84+
* @param vtx_reindex: map from old to new vertex indices
85+
* @return list of reindexed vertex endpoints
86+
*/
87+
std::vector<std::pair<int, int>> reindex_endpoints(
88+
const std::vector<std::pair<int, int>>& endpoints,
89+
const std::vector<int>& vtx_reindex);
90+
91+
92+
} // namespace Feature
93+
} // namespace Penner

0 commit comments

Comments
 (0)