1
+ #include < jse/jse.h>
2
+ #include < CLI/CLI.hpp>
3
+ #include < filesystem>
4
+ #include < nlohmann/json.hpp>
5
+
6
+ #include < wmtk/EdgeMesh.hpp>
7
+ #include < wmtk/Mesh.hpp>
8
+ #include < wmtk/PointMesh.hpp>
9
+ #include < wmtk/TetMesh.hpp>
10
+ #include < wmtk/TriMesh.hpp>
11
+
12
+ #include < wmtk/utils/Logger.hpp>
13
+
14
+ #include < wmtk/components/utils/resolve_path.hpp>
15
+
16
+
17
+ #include < wmtk/components/delaunay/delaunay.hpp>
18
+ #include < wmtk/components/input/input.hpp>
19
+ #include < wmtk/components/output/output.hpp>
20
+ #include < wmtk/components/tetwild_simplification/tetwild_simplification.hpp>
21
+ #include < wmtk/components/to_points/to_points.hpp>
22
+ #include < wmtk/components/triangle_insertion/triangle_insertion.hpp>
23
+ #include < wmtk/components/wildmeshing/wildmeshing.hpp>
24
+ #include < wmtk/components/winding_number/winding_number.hpp>
25
+
26
+
27
+ #include " tetwild_spec.hpp"
28
+
29
+ using namespace wmtk ;
30
+ using namespace wmtk ::components;
31
+ namespace fs = std::filesystem;
32
+
33
+ using wmtk::components::utils::resolve_paths;
34
+
35
+ int main (int argc, char * argv[])
36
+ {
37
+ CLI::App app{argv[0 ]};
38
+
39
+ app.ignore_case ();
40
+
41
+ fs::path json_input_file;
42
+ app.add_option (" -j, --json" , json_input_file, " json specification file" )
43
+ ->required (true )
44
+ ->check (CLI::ExistingFile);
45
+ CLI11_PARSE (app, argc, argv);
46
+
47
+ nlohmann::json j;
48
+ {
49
+ std::ifstream ifs (json_input_file);
50
+ j = nlohmann::json::parse (ifs);
51
+
52
+ jse::JSE spec_engine;
53
+ bool r = spec_engine.verify_json (j, tetwild_spec);
54
+ if (!r) {
55
+ wmtk::logger ().error (" {}" , spec_engine.log2str ());
56
+ return 1 ;
57
+ } else {
58
+ j = spec_engine.inject_defaults (j, tetwild_spec);
59
+ }
60
+ }
61
+
62
+ fs::path input_file = resolve_paths (json_input_file, {j[" root" ], j[" input" ]});
63
+
64
+ auto mesh = wmtk::components::input::input (input_file);
65
+ wmtk::logger ().info (" mesh has {} vertices" , mesh->get_all (PrimitiveType::Vertex).size ());
66
+
67
+ auto mesh_after_simp = mesh;
68
+ if (!j[" skip_simplification" ]) {
69
+ auto [out, stats] = tetwild_simplification (
70
+ static_cast <const TriMesh&>(*mesh),
71
+ " vertices" ,
72
+ j[" target_edge_length" ]);
73
+ mesh_after_simp = out;
74
+ }
75
+
76
+ wmtk::components::ToPtsOptions tpo;
77
+ tpo.add_box = false ;
78
+ tpo.box_scale = 0.05 ;
79
+ tpo.add_grid = true ;
80
+ tpo.grid_spacing = j[" target_edge_length" ];
81
+ tpo.min_dist = 0 ;
82
+ tpo.remove_duplicates = true ;
83
+
84
+ auto pts_attr_simp =
85
+ mesh_after_simp->get_attribute_handle <double >(" vertices" , PrimitiveType::Vertex);
86
+
87
+ auto mesh_after_to_points = to_points (*mesh_after_simp, pts_attr_simp, tpo);
88
+
89
+ auto pts_attr_tp =
90
+ mesh_after_to_points->get_attribute_handle <double >(" vertices" , PrimitiveType::Vertex);
91
+
92
+ auto mesh_after_delaunay = delaunay (*mesh_after_to_points, pts_attr_tp);
93
+
94
+ std::vector<attribute::MeshAttributeHandle> pass_through;
95
+
96
+ auto [main_mesh, child_meshes] = wmtk::components::triangle_insertion::triangle_insertion (
97
+ static_cast <const TetMesh&>(*mesh_after_delaunay),
98
+ " vertices" ,
99
+ static_cast <const TriMesh&>(*mesh_after_simp),
100
+ " vertices" ,
101
+ pass_through,
102
+ true ,
103
+ true ,
104
+ false );
105
+
106
+ std::vector<wmtk::components::EnvelopeOptions> enves;
107
+
108
+ wmtk::components::EnvelopeOptions e_surface;
109
+ e_surface.envelope_name = " surface" ;
110
+ e_surface.envelope_constrained_mesh = child_meshes.surface_mesh ;
111
+ e_surface.envelope_geometry_mesh = mesh_after_simp;
112
+ e_surface.constrained_position_name = " vertices" ;
113
+ e_surface.geometry_position_name = " vertices" ;
114
+ e_surface.thickness = j[" envelope_size" ];
115
+
116
+ enves.push_back (e_surface);
117
+
118
+ wmtk::components::EnvelopeOptions e_bbox;
119
+ e_bbox.envelope_name = " bbox" ;
120
+ e_bbox.envelope_constrained_mesh = child_meshes.bbox_mesh ;
121
+ e_bbox.envelope_geometry_mesh = child_meshes.bbox_mesh ;
122
+ e_bbox.constrained_position_name = " vertices" ;
123
+ e_bbox.geometry_position_name = " vertices" ;
124
+ e_bbox.thickness = j[" envelope_size" ];
125
+
126
+ enves.push_back (e_bbox);
127
+
128
+ if (child_meshes.open_boundary_mesh != nullptr ) {
129
+ wmtk::components::EnvelopeOptions e_open_boundary;
130
+ e_open_boundary.envelope_name = " open_boundary" ;
131
+ e_open_boundary.envelope_constrained_mesh = child_meshes.open_boundary_mesh ;
132
+ e_open_boundary.envelope_geometry_mesh = child_meshes.open_boundary_mesh ;
133
+ e_open_boundary.constrained_position_name = " vertices" ;
134
+ e_open_boundary.geometry_position_name = " vertices" ;
135
+ e_open_boundary.thickness = j[" envelope_size" ];
136
+
137
+ enves.push_back (e_open_boundary);
138
+ }
139
+
140
+ if (child_meshes.nonmanifold_edge_mesh != nullptr ) {
141
+ wmtk::components::EnvelopeOptions e_nonmanifold_edge;
142
+ e_nonmanifold_edge.envelope_name = " nonmanifold_edge" ;
143
+ e_nonmanifold_edge.envelope_constrained_mesh = child_meshes.nonmanifold_edge_mesh ;
144
+ e_nonmanifold_edge.envelope_geometry_mesh = child_meshes.nonmanifold_edge_mesh ;
145
+ e_nonmanifold_edge.constrained_position_name = " vertices" ;
146
+ e_nonmanifold_edge.geometry_position_name = " vertices" ;
147
+ e_nonmanifold_edge.thickness = j[" envelope_size" ];
148
+
149
+ enves.push_back (e_nonmanifold_edge);
150
+ }
151
+
152
+
153
+ wmtk::components::WildMeshingOptions wmo;
154
+ wmo.input_mesh = main_mesh;
155
+ wmo.input_mesh_position = " vertices" ;
156
+ wmo.target_edge_length = j[" target_edge_length" ];
157
+ wmo.target_max_amips = j[" target_max_amips" ];
158
+ wmo.max_passes = j[" max_passes" ];
159
+ wmo.intermediate_output = j[" intermediate_output" ];
160
+ wmo.replace_double_coordinate = false ;
161
+ wmo.scheduler_update_frequency = 0 ;
162
+ wmo.intermediate_output_path = " " ;
163
+ wmo.intermediate_output_name = j[" output" ];
164
+ wmo.envelopes = enves;
165
+ wmo.pass_through = pass_through;
166
+
167
+ auto meshes_after_tetwild = wildmeshing (wmo);
168
+ auto main_mesh_after_tetwild = meshes_after_tetwild[0 ].first ;
169
+
170
+ std::string output_file = j[" output" ];
171
+
172
+ std::shared_ptr<Mesh> surface_mesh;
173
+ for (int64_t i = 1 ; i < meshes_after_tetwild.size (); ++i) {
174
+ // output child meshes
175
+ wmtk::components::output::output (
176
+ *(meshes_after_tetwild[i].first ),
177
+ output_file + " _" + meshes_after_tetwild[i].second ,
178
+ " vertices" );
179
+
180
+ if (meshes_after_tetwild[i].second == " surface" ) {
181
+ surface_mesh = meshes_after_tetwild[i].first ;
182
+ }
183
+ }
184
+
185
+
186
+ auto mesh_after_winding_number = winding_number (main_mesh_after_tetwild, surface_mesh);
187
+
188
+ wmtk::components::output::output (*mesh_after_winding_number, output_file, " vertices" );
189
+
190
+ const std::string report = j[" report" ];
191
+ if (!report.empty ()) {
192
+ nlohmann::json out_json;
193
+ out_json[" vertices" ] = mesh_after_winding_number->get_all (PrimitiveType::Vertex).size ();
194
+ out_json[" edges" ] = mesh_after_winding_number->get_all (PrimitiveType::Edge).size ();
195
+ out_json[" faces" ] = mesh_after_winding_number->get_all (PrimitiveType::Triangle).size ();
196
+ out_json[" cells" ] = mesh_after_winding_number->get_all (PrimitiveType::Tetrahedron).size ();
197
+
198
+ out_json[" input" ] = j;
199
+
200
+ std::ofstream ofs (report);
201
+ ofs << out_json;
202
+ }
203
+
204
+
205
+ return 0 ;
206
+ }
0 commit comments