|
Wildmeshing Toolkit
|
Classes | |
| struct | PositionInfoCache |
Public Types | |
| using | VertAttCol = wmtk::AttributeCollection< VertexAttributes > |
Public Types inherited from wmtk::TriMesh | |
| template<typename T > | |
| using | vector = std::vector< T > |
| using | VertexMutex = wmtk::threading::VertexMutex |
Public Member Functions | |
| void | set_feature_edges (const std::vector< std::array< size_t, 2 > > &edges) |
| Curves the remeshing keeps: label boundaries, say. | |
| void | set_feature_edges (const std::vector< std::array< size_t, 2 > > &edges, const std::vector< int64_t > &ids) |
The same, with an id for each edge (-1 for none), which the remeshing carries: the halves of a split keep it, and a collapse along a curve leaves the curve its id. A vertex on two feature edges of different ids ends one curve and starts the next, so it stays put like a junction (see stays_put). ids has one entry per edge. | |
| std::vector< std::array< size_t, 2 > > | feature_edges () const |
| The feature edges, smaller vertex id first. | |
| bool | is_feature_edge (size_t a, size_t b) const |
| int64_t | feature_edge_id (size_t a, size_t b) const |
| The id set_feature_edges gave the feature edge (a, b): -1 for none, or for no feature edge. | |
| size_t | feature_degree (size_t v) const |
| void | set_fixed_vertices (const std::vector< std::pair< size_t, int64_t > > &vertices) |
| Vertices the remeshing keeps exactly: B-rep corners, say, which may sit inside a curve between two regions as well as where curves meet. | |
| bool | is_fixed (size_t v) const |
| bool | stays_put (size_t v) const |
Whether v is never moved and never removed: a curve's end, a junction of curves, a vertex between feature edges of different ids, or a fixed vertex. | |
| bool | may_collapse_away (const Tuple &t) const |
Whether the curve rules let a collapse of t remove t.vid(): it does not stay put, and if it is on a curve, t runs along it. The rest of collapse_edge_before still applies. | |
| void | set_face_fields (const std::vector< std::vector< double > > &values) |
Per-face values the remeshing carries: per-face labels, say, whose boundaries are feature edges. A split gives both halves of a face its values; a collapse or swap keeps the values of the faces it changes, which is right where no swapped or collapsed edge separates faces of different values – where the boundaries are feature edges, as set_feature_edges keeps them. values has one entry per face of the mesh given to create_mesh(), in that order; call after create_mesh(). | |
| bool | has_face_fields () const |
| void | set_feature_envelope (double eps) |
Keep the curves near the feature edges as they are now – the input's, called before remeshing: every feature edge an operation leaves must lie within eps of them. | |
| void | consolidate_mesh () |
| TriMesh::consolidate_mesh, plus the renumbering of the feature edges. | |
| size_t | remove_feature_ears () |
| Removes the triangles that hold two feature edges – "ears". | |
| bool | is_feature_ear_tip (const Tuple &v) const |
Whether v is on a curve and one triangle holds both of its curve edges. | |
| void | set_check_inversions (bool check) |
| Refuse a collapse, swap or smoothing that folds the surface over. | |
| void | set_swap_quality (bool quality) |
| Swap an edge to raise the worse shape quality of its two triangles (see compute_swap_quality), instead of to bring the valences of its four vertices to 6 (4 on the boundary). Off by default. | |
| void | set_limit_collapse_length (bool limit) |
| Refuse a collapse that leaves an edge longer than 4/3 of the target length – the split threshold – as Botsch and Kobbelt's remeshing does. Off by default: a collapse is then judged by the edge it removes alone, and those of the last iteration leave edges that no split comes after to cut. cleanup_triangles() holds its collapses to the same bound, on or off (see there). | |
| void | set_cleanup_angle (double degrees) |
Repair, at the end of every iteration, the triangles whose smallest angle is under degrees; 0, the default, repairs none. Call before create_mesh(), which then keeps the input's area vectors for the fold test below. | |
| size_t | cleanup_triangles (double degrees) |
Repairs the triangles whose smallest angle is under degrees, worst first. | |
| size_t | refused_inversions () const |
| The operations set_check_inversions() refused, since the mesh was made. | |
| bool | smooth_vertex_to (size_t v, const Eigen::Vector3d &p) |
Moves v to p as a smoothing: smooth_vertex() with p in place of the smoothed position, so that the smoothing's rules, the envelopes and the fold check judge the move, and a history records it. Returns whether it moved. cleanup_triangles() moves its vertices so. | |
| IsotropicRemeshing (std::vector< Eigen::Vector3d > _m_vertex_positions, int num_threads=1, bool use_exact=true) | |
| void | create_mesh (size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris, const std::vector< size_t > &frozen_verts=std::vector< size_t >(), bool m_freeze=true, double eps=0, double boundary_eps=0) |
| void | cache_edge_positions (const Tuple &t) |
| bool | invariants (const std::vector< Tuple > &new_tris) override |
| User specified invariants that can't be violated. | |
| void | partition_mesh () |
| void | partition_mesh_morton () |
| size_t | get_partition_id (const Tuple &loc) const |
| bool | smooth_all_vertices () |
| Eigen::Vector3d | smooth (const Tuple &t) |
| Eigen::Vector3d | tangential_smooth (const Tuple &t) |
| bool | collapse_edge_before (const Tuple &t) override |
| User specified preparations and desideratas for an edge collapse including the link check as collapse prerequisite. | |
| bool | collapse_edge_after (const Tuple &t) override |
| User specified modifications and desideratas after an edge collapse. | |
| bool | swap_edge_before (const Tuple &t) override |
| User specified preparations and desideratas for an edge swap including 1.can't swap on boundary edge. 2. when swap edge between v1, v2, there can't exist edges between the two opposite vertices v3, v4. | |
| bool | swap_edge_after (const Tuple &t) override |
| User specified modifications and desideras after an edge swap. | |
| std::vector< TriMesh::Tuple > | new_edges_after (const std::vector< TriMesh::Tuple > &tris) const |
| std::vector< TriMesh::Tuple > | new_edges_after_swap (const TriMesh::Tuple &t) const |
| std::vector< TriMesh::Tuple > | replace_edges_after_split (const std::vector< TriMesh::Tuple > &tris, const size_t vid_threshold) const |
| std::vector< TriMesh::Tuple > | new_sub_edges_after_split (const std::vector< TriMesh::Tuple > &tris) const |
| bool | split_edge_before (const Tuple &t) override |
| User specified preparations and desideratas for an edge split. | |
| bool | split_edge_after (const Tuple &t) override |
| User specified modifications and desideratas after an edge split. | |
| bool | smooth_before (const Tuple &t) override |
| User specified preparations and desideratas for an edge smooth. | |
| bool | smooth_after (const Tuple &t) override |
| User specified modifications and desideras after an edge smooth. | |
| double | compute_edge_cost_collapse (const TriMesh::Tuple &t, double L) const |
| double | compute_edge_cost_split (const TriMesh::Tuple &t, double L) const |
| double | compute_vertex_valence (const TriMesh::Tuple &t) const |
| double | compute_swap_quality (const TriMesh::Tuple &t) const |
| std::vector< double > | average_len_valen () |
| Report statistics. | |
| bool | split_remeshing (double L) |
| bool | collapse_remeshing (double L) |
| bool | swap_remeshing () |
| bool | uniform_remeshing (double L, int interations) |
| bool | write_triangle_mesh (std::string path) |
Public Member Functions inherited from wmtk::TriMesh | |
| void | init (size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris) |
| void | init (const MatrixXi &F) |
| Generate the connectivity of the mesh from an IGL-style F matrix. | |
| std::vector< Tuple > | get_vertices () const |
| std::vector< Tuple > | get_edges () const |
| std::vector< Tuple > | get_faces () const |
| Tuple | tuple_from_edge (size_t vid1, size_t vid2, size_t fid) const |
| Tuple | tuple_from_vids (size_t vid0, size_t vid1, size_t vid2) const |
| simplex::Vertex | simplex_from_vertex (const Tuple &t) const |
| simplex::Edge | simplex_from_edge (const Tuple &t) const |
| simplex::Face | simplex_from_face (const Tuple &t) const |
| simplex::Face | simplex_from_face (const size_t fid) const |
| Tuple | tuple_from_simplex (const simplex::Face &s) const |
| simplex::SimplexCollection | simplex_incident_triangles (const simplex::Vertex &v) const |
| simplex::SimplexCollection | simplex_incident_triangles (const simplex::Edge &e) const |
| simplex::SimplexCollection | simplex_link_vertices (const simplex::Vertex &v) const |
| simplex::SimplexCollection | simplex_link_vertices (const simplex::Edge &e) const |
| simplex::SimplexCollection | simplex_link_edges (const simplex::Vertex &v) const |
| void | set_preallocation_factor (double factor) |
| Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so operations can grab fresh slots without resizing the storage. When a pass exhausts the reserved capacity the affected operations fail (retried later after a consolidate). Values < 1 are clamped to 1. | |
| double | preallocation_factor () const |
| bool | slots_exhausted () const |
| void | clear_slots_exhausted () |
| size_t | request_tri_slots (size_t n) |
| size_t | request_vert_slots (size_t n) |
| virtual bool | split_face_before (const Tuple &t) |
| User specified preparations and desideratas for a face split. | |
| virtual bool | split_face_after (const Tuple &t) |
| User specified modifications and desideratas after a face split. | |
| size_t | tri_capacity () const |
| get the current largest global fid | |
| size_t | vert_capacity () const |
| get the current largest global vid | |
| void | consolidate_mesh () |
| removing the elements that are removed | |
| std::shared_ptr< history::Recorder > | start_history (std::function< Eigen::Vector3d(size_t)> position) |
| Record every operation this mesh commits from now on (see wmtk/history). | |
| void | stop_history () |
| Stop recording. The recorder keeps the edits it has. | |
| std::shared_ptr< history::TrackedCurveRecorder > | start_curve_history (std::function< Eigen::Vector3d(size_t)> position) |
| Record every change to the tracked curves from now on (see wmtk/history/TrackedRecorder.hpp). | |
| void | stop_curve_history () |
| Stop recording curves. The recorder keeps what it has. | |
| size_t | resync_curve_history (const std::vector< std::array< size_t, 2 > > &edges) |
| std::vector< std::array< size_t, 2 > > | tracked_edges () const |
| Every tracked edge, each with its smaller vertex first. | |
| virtual bool | is_tracked_edge (const Tuple &e) const |
| virtual std::vector< size_t > | tracked_feature_points () const |
| void | remove_tris_by_ids (const std::vector< size_t > &fids) |
| Mark the given triangles, and any vertex left without an incident triangle, as removed. | |
| Tuple | switch_vertex (const Tuple &t) const |
| a duplicate of Tuple::switch_vertex funciton | |
| Tuple | switch_edge (const Tuple &t) const |
| a duplicate of Tuple::switch_edge funciton | |
| std::optional< Tuple > | switch_face (const Tuple &t) const |
| a duplicate of Tuple::switch_face funciton | |
| bool | check_link_condition (const Tuple &t) const |
| prerequisite for collapse | |
| void | set_use_link_condition (bool use_it) |
| Should collapse_edge_before enforce the link condition? | |
| bool | use_link_condition () const |
| bool | check_mesh_connectivity_validity () const |
| verify the connectivity validity of the mesh | |
| bool | check_edge_manifold () const |
| verify the edge manifoldness of the mesh | |
| size_t | edge_valence (const TriMesh::Tuple &t) const |
| Number of triangles incident to the edge the Tuple points at. | |
| bool | is_boundary_edge (const TriMesh::Tuple &t) const |
| Does exactly one triangle share this edge? | |
| bool | is_manifold_edge (const TriMesh::Tuple &t) const |
| Do exactly two triangles share this edge? | |
| size_t | vertex_component_count (const size_t vid) const |
| Number of edge-connected components in the fan of a vertex. | |
| size_t | vertex_component_count (const TriMesh::Tuple &t) const |
| bool | is_manifold_vertex (const size_t vid) const |
| std::optional< Tuple > | switch_component (const TriMesh::Tuple &t) const |
| Jump to the next edge-connected component of the fan of the Tuple's vertex. | |
| bool | is_boundary_vertex (const TriMesh::Tuple &t) const |
| check if the vertex that's represented by a Tuple is at the boundary of the mesh | |
| bool | split_edge (const Tuple &t, std::vector< Tuple > &new_t) |
| virtual bool | collapse_edge (const Tuple &t, std::vector< Tuple > &new_t) |
| void | collapse_edge_conn (const Tuple &loc0, std::vector< Tuple > &new_tris, Tuple &return_t, size_t &new_vid, std::vector< std::pair< size_t, TriangleConnectivity > > &old_tris, std::vector< std::pair< size_t, VertexConnectivity > > &old_vertices, std::vector< std::pair< size_t, size_t > > &same_edge_vid_fid, std::vector< size_t > &n12_intersect_fids) |
| void | collapse_edge_rollback (size_t &new_vid, std::vector< std::pair< size_t, TriangleConnectivity > > &old_tris, std::vector< std::pair< size_t, VertexConnectivity > > &old_vertices, std::vector< std::pair< size_t, size_t > > &same_edge_vid_fid, std::vector< size_t > &n12_intersect_fids) |
| bool | swap_edge (const Tuple &t, std::vector< Tuple > &new_t) |
| bool | smooth_vertex (const Tuple &t) |
| bool | split_face (const Tuple &t, std::vector< Tuple > &new_t) |
| Split a face in 3 faces. | |
| size_t | get_valence_for_vertex (const Tuple &t) const |
| Count the number of the one ring tris for a vertex. | |
| size_t | vertex_valence (const size_t vid) const |
| Number of triangles incident to a vertex, by id. | |
| std::vector< Tuple > | get_one_ring_tris_for_vertex (const Tuple &t) const |
| Get the one ring tris for a vertex. | |
| const std::vector< size_t > & | get_one_ring_fids_for_vertex (const Tuple &t) const |
| const std::vector< size_t > & | get_one_ring_fids_for_vertex (const size_t vid) const |
| std::vector< size_t > | get_one_ring_vids_for_vertex_duplicate (const size_t &t) const |
| Get the vids of the incident one ring tris for a vertex. | |
| void | get_one_ring_vids_for_vertex_duplicate (const size_t &t, std::vector< size_t > &one_ring) const |
| std::vector< size_t > | get_incident_fids_for_edge (const Tuple &t) const |
| std::vector< size_t > | get_incident_fids_for_edge (const size_t vid0, const size_t vid1) const |
| std::vector< Tuple > | get_one_ring_edges_for_vertex (const Tuple &t) const |
Get all edges that are incident to the vertex of Tuple t. | |
| std::vector< Tuple > | get_one_ring_edges_for_vertex (const size_t vid) const |
| std::array< Tuple, 3 > | oriented_tri_vertices (const Tuple &t) const |
| Get the incident vertices for a triangle. | |
| std::array< size_t, 3 > | oriented_tri_vids (const Tuple &t) const |
| Get the incident vertices for a triangle. | |
| std::array< size_t, 3 > | oriented_tri_vids (const size_t i) const |
| std::array< Tuple, 2 > | get_edge_vertices (const Tuple &t) const |
| std::array< size_t, 2 > | get_edge_vids (const Tuple &t) const |
| Tuple | tuple_from_tri (size_t fid) const |
| Tuple | tuple_from_vertex (size_t vid) const |
| Tuple | tuple_from_edge (size_t fid, size_t local_eid) const |
| std::tuple< Tuple, size_t > | tuple_from_edge (const std::array< size_t, 2 > &vids) const |
| std::optional< std::tuple< Tuple, size_t > > | try_tuple_from_edge (const std::array< size_t, 2 > &vids) const |
| tuple_from_edge for callers where a missing edge is an answer, not a bug. | |
| void | start_protect_attributes () |
| Start the phase where the attributes that will be modified can be recorded. | |
| void | release_protect_attributes () |
| End the modification phase. | |
| void | rollback_protected_attributes () |
| rollback the attributes that are modified if any condition failed | |
| int | release_vertex_mutex_in_stack () |
| int | release_vertex_mutex_to (size_t mark) |
Release the mutexes taken since the release stack held mark entries. | |
| bool | try_set_vertex_mutex_n_ring (const Tuple &v, int threadid, int n) |
Lock every vertex within graph distance n of v, the seed included. | |
| bool | try_set_vertex_mutex_n_ring (size_t vid, int threadid, int n) |
| bool | try_set_edge_mutex_n_ring (const Tuple &e, int threadid, int n) |
| try_set_vertex_mutex_n_ring seeded from both ends of an edge. | |
| bool | try_set_face_mutex_one_ring (const Tuple &f, int threadid) |
| try lock the one-ring neighboring triangles' incident vertices. | |
| void | for_each_face (const std::function< void(const Tuple &)> &) |
| perform the given function for each face | |
| void | for_each_edge (const std::function< void(const Tuple &)> &) |
| perform the given function for each edge | |
| void | for_each_vertex (const std::function< void(const Tuple &)> &) |
| perform the given function for each vertex | |
| virtual bool | vertex_is_on_surface (const size_t vid) const |
| Is a vertex part of the substructure. | |
| virtual bool | edge_is_on_surface (const std::array< size_t, 2 > &vids) const |
| Is an edge part of the substructure. | |
| simplex::SimplexCollection | get_surface_edges_for_vertex (const size_t vid) const |
| Get all edges on the surface that are incident to vid. | |
| size_t | get_order_of_edge (const std::array< size_t, 2 > &vids) const |
| Compute the order of an edge. | |
| size_t | get_order_of_vertex (const size_t vid) const |
| Get the order of a vertex. | |
| bool | substructure_link_condition (const Tuple &e_tuple) const |
| Link condition that also considers substructures. | |
| size_t | tri_storage_capacity () const |
| size_t | vert_storage_capacity () const |
| bool | try_set_vertex_mutex_two_ring (const Tuple &v, int threadid) |
| Lock v's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_edge_mutex_two_ring (const Tuple &e, int threadid) |
| Lock the edge's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_vertex_mutex_one_ring (const Tuple &v, int threadid) |
| Lock v and its one-ring. Complete, unlike the two-ring pair. | |
| size_t | cell_capacity () const |
| size_t | cell_storage_capacity () const |
| Tuple | tuple_from_cell (size_t cid) const |
| size_t | cell_slot_bound (const Tuple &t) const |
| void | reserve_free_slots (size_t cells, size_t verts) |
| virtual bool | storage_grows_on_demand () const |
Public Attributes | |
| wmtk::Envelope | m_envelope |
| bool | m_has_envelope = false |
| wmtk::BoundaryEnvelope | m_boundary_envelope |
| wmtk::Envelope | m_feature_envelope |
| Around the feature edges set_feature_envelope() saw; initialized() is false without one. | |
| VertAttCol | vertex_attrs |
| wmtk::AttributeCollection< FeatureAttributes > | feature_attrs |
| Read and written only while the mesh has feature edges or fixed vertices. | |
| wmtk::AttributeCollection< FaceFieldAttributes > | face_field_attrs |
| int | retry_limit = 10 |
| wmtk::threading::enumerable_thread_specific< PositionInfoCache > | position_cache |
Public Attributes inherited from wmtk::TriMesh | |
| AbstractAttributeContainer * | p_vertex_attrs = nullptr |
| AbstractAttributeContainer * | p_edge_attrs = nullptr |
| AbstractAttributeContainer * | p_face_attrs = nullptr |
| bool | m_check_smoothing_stays_in_star = false |
| While true, smooth_vertex() checks that the smooth recorded nothing outside the vertex's star – the vertex itself and the edges, faces and triangles incident to it – and throws if it did. | |
| wmtk::threading::enumerable_thread_specific< std::vector< size_t > > | mutex_release_stack |
| int | NUM_THREADS = 0 |
Private Member Functions | |
| void | set_regions () |
| int64_t | region (const Tuple &f) const |
The region of the curves f lies in; -1 without curves. | |
| std::vector< std::pair< int64_t, std::vector< Tuple > > > | by_region (const std::vector< Tuple > &tris) const |
| The triangles, by region (see set_feature_edges), in the order the regions first appear. | |
| template<typename F > | |
| void | for_each_region (const std::vector< Tuple > &tris, F &&side) const |
| std::vector< std::array< size_t, 6 > > | feature_wedges (const std::vector< Tuple > &tris) const |
| bool | closes_a_crease (const std::vector< Tuple > &tris, const ReplacedSurface &before) const |
| Eigen::Vector3d | area_normal (const std::vector< Tuple > &tris) const |
| The area vectors of the triangles, summed (twice over). | |
| size_t | not_facing (const std::vector< Tuple > &tris, const Eigen::Vector3d &n) const |
| How many of the triangles do not face along n. | |
| size_t | star_folds (const std::vector< Tuple > &tris) const |
| ReplacedSurface | replaced (const std::vector< Tuple > &tris) const |
| The triangles an operation is about to replace. | |
| bool | more_folds (const std::vector< Tuple > &tris, const ReplacedSurface &before) const |
| bool | folds (const std::vector< Tuple > &tris, const ReplacedSurface &before) |
| The same; counts a refusal. | |
| double | min_angle (const std::vector< Tuple > &tris) const |
| The smallest angle of the triangles, in degrees. | |
| Eigen::Vector3d | input_normal (const Tuple &f) const |
The area vectors of the input triangles next to f, summed: see cleanup_triangles(). | |
| size_t | input_folds (const std::vector< Tuple > &tris) const |
| How many of the triangles do not face along input_normal(). | |
| bool | cleanup_allows (const std::vector< Tuple > &tris, const ReplacedSurface &before, size_t input_folds_before, double floor) const |
| bool | cleanup_move (size_t v, double floor) |
Moves v to where the smallest angle of its star is largest, above floor. | |
Private Attributes | |
| wmtk::AttributeContainerGroup | m_vertex_group |
| bool | m_has_features = false |
| bool | m_has_fixed = false |
| bool | m_has_edge_ids = false |
| Some feature edge has an id other than -1. | |
| bool | m_has_face_fields = false |
| bool | m_has_feature_envelope = false |
| bool | m_removing_ears = false |
| Set while remove_feature_ears() runs (serially): its collapses may make an ear. | |
| bool | m_check_inversions = true |
| bool | m_swap_quality = false |
| bool | m_limit_collapse_length = false |
| double | m_cleanup_angle = 0 |
| double | m_cleanup_floor = 0 |
| bool | m_cleaning = false |
| std::optional< Eigen::Vector3d > | m_smooth_target |
| Where cleanup_triangles() moves a vertex, in place of the smoothing's position. | |
| double | m_envelope_eps = 0 |
| With a cleanup angle: the envelope's eps, and the input's area vectors and face fields. | |
| std::vector< Eigen::Vector3d > | m_input_area |
| std::vector< std::vector< double > > | m_input_values |
| double | m_collapse_target = 0 |
| The target length of the last collapse_remeshing(), for the limit above. | |
| std::atomic< size_t > | m_refused_inversions = 0 |
| bool | m_has_regions = false |
| The faces have their regions (see set_feature_edges). | |
Additional Inherited Members | |
Static Public Member Functions inherited from wmtk::TriMesh | |
| static bool | dry_run () |
| Whether operations on this thread are dry runs (see wmtk/OperationDryRun.hpp). | |
| static SlotUsage | slot_usage_of_this_thread () |
Static Public Attributes inherited from wmtk::TriMesh | |
| static constexpr int | EDGES_PER_CELL = 3 |
Protected Member Functions inherited from wmtk::TriMesh | |
| virtual void | on_slot_storage_grown () |
| void | vertex_fan_components (size_t vid, std::vector< size_t > &component_of, std::vector< size_t > &representatives) const |
| void | resize_mutex (size_t v) |
| std::vector< double > wmtk::components::isotropic_remeshing::IsotropicRemeshing::average_len_valen | ( | ) |
Report statistics.
Returns a vector with: average_length max length min length average valence max valence min valence
|
private |
Whether the triangles a repair left fold no more than the before they replaced and beat floor; or, where before folds already, face against the input less often than its input_folds_before. See cleanup_triangles().
| size_t wmtk::components::isotropic_remeshing::IsotropicRemeshing::cleanup_triangles | ( | double | degrees | ) |
Repairs the triangles whose smallest angle is under degrees, worst first.
Each gets the first of these that is allowed: a collapse of its shortest edge, either way; a swap of one of its edges, longest first; a move of one of its vertices, or else of one of the triangles around it – one off the curves within its tangent plane, one inside a curve along it – to where the smallest angle of its star is largest. Allowed means the curve rules, the envelopes and the fixed vertices hold, as everywhere; the operation folds nothing by the rule of the fold check (see set_check_inversions; on or off, the repairs keep it); a collapse leaves no edge longer than 4/3 of the target of the last collapse_remeshing(), with set_limit_collapse_length() or without – the repairs mend angles and are not to coarsen the mesh, and those after the last iteration have no split after them; and it raises the smallest angle of the triangles it leaves over that of the triangles around the one repaired (of its star, for a move). Where what it replaces folds already, the fold check, which judges against those triangles, can count a repair of the fold as one more: there an operation that leaves fewer triangles facing against the input next to them – the input triangles within half their size plus the envelope, of the same face fields where set_face_fields() gave some – than there were is allowed too, even if no angle improves. Only there: where two sheets of the input are closer than that, a thin wall, the far one cancels the near one, and the input's orientation is noise. Rounds until one repairs nothing, 10 at most. Serial; returns the number of repairs. Throws unless set_cleanup_angle() came before create_mesh().
|
private |
Whether at a crease of before (see set_check_inversions) the triangles an operation left open the wedge the other way, or are flat.
|
overridevirtual |
User specified modifications and desideratas after an edge collapse.
| the | edge Tuple to be collapsed |
Reimplemented from wmtk::TriMesh.
|
overridevirtual |
User specified preparations and desideratas for an edge collapse including the link check as collapse prerequisite.
| the | edge Tuple to be split |
Reimplemented from wmtk::TriMesh.
| double wmtk::components::isotropic_remeshing::IsotropicRemeshing::compute_swap_quality | ( | const TriMesh::Tuple & | t | ) | const |
1 / the worse shape quality (4 sqrt(3) area / sum of squared edge lengths) of the two triangles at t, less the same after swapping it: positive where the swap helps the worse one. -1 where t has not two faces.
| void wmtk::components::isotropic_remeshing::IsotropicRemeshing::create_mesh | ( | size_t | n_vertices, |
| const std::vector< std::array< size_t, 3 > > & | tris, | ||
| const std::vector< size_t > & | frozen_verts = std::vector<size_t>(), |
||
| bool | m_freeze = true, |
||
| double | eps = 0, |
||
| double | boundary_eps = 0 |
||
| ) |
| m_freeze | freeze frozen_verts and, unless boundary_eps is positive, every vertex of the open boundary |
| eps | surface envelope thickness; 0 = no envelope |
| boundary_eps | how the open boundary is held. 0 (default): m_freeze decides – frozen, or held only by the surface envelope, which is a containment test and does not notice an outline retracting along the surface. Feature edges set before it give the faces their regions here (see set_feature_edges). |
|
private |
The feature edges (a, b) of the triangles with a triangle on either side, oriented the same way, as {a, b, p, q, f, g}: a to b in face f, with apex p, b to a in face g, with apex q. Once each. An operation may read the triangle across, and the stars of a and b: one that changes them holds a or b, which this operation holds.
|
private |
Calls side(region, triangles) for each region of the triangles, in the order of by_region; without regions once, with all of them as they are, uncopied.
|
overridevirtual |
User specified invariants that can't be violated.
| std::vector<Tuple> | a vector of Tuples that are concerned in a given operation |
Reimplemented from wmtk::TriMesh.
| bool wmtk::components::isotropic_remeshing::IsotropicRemeshing::may_collapse_away | ( | const Tuple & | t | ) | const |
Whether the curve rules let a collapse of t remove t.vid(): it does not stay put, and if it is on a curve, t runs along it. The rest of collapse_edge_before still applies.
With fixed vertices or edge ids, collapse_remeshing turns a collapse around when its tuple's vertex may not go and the other end may: the queue holds an edge in one direction only, and a fixed vertex is mostly the end that has to stay.
|
private |
Whether the triangles an operation left fold the surface over more than the before they replaced, or close a crease of theirs.
| size_t wmtk::components::isotropic_remeshing::IsotropicRemeshing::remove_feature_ears | ( | ) |
Removes the triangles that hold two feature edges – "ears".
Three consecutive curve vertices a, b, c that span a triangle leave b that triangle alone on one side, and smoothing b along the curve would flatten it. Swapping the edge (a, c) gives b two triangles there; where that is not possible – (a, c) is a curve or the boundary, or the swap would make a new ear or turn a triangle over – b collapses along the curve and the corner goes. Where it cannot either – the moved b would turn a triangle over – (a, c) is split at its midpoint, which gives b two triangles there and moves nothing; at a junction, which smoothing does not move, the corner stays. Where a curve zigzags, removing one ear can make the next, so call it until it removes none. No other swap or collapse makes an ear, but the input can hold them. A triangle with curves (or the boundary) all round is a region of its own, not an ear, and stays. Serial; returns the number removed.
|
inline |
Refuse a collapse, swap or smoothing that folds the surface over.
The triangles an operation changes or removes have a normal, their area vectors summed; the operation may leave no more triangles that do not face along it – face against it, or are flat – than there were, nor along the normal of the triangles it leaves. Nor may it leave more folds in the stars of the vertices it touches, each star against its own normal: what it changes is in its neighbours' stars too. So it turns no triangle over against the triangles around it, and may undo a fold the input has. A triangle faces along a normal when the exact orient3d says so (see faces_along in the .cpp). A split moves no vertex and is not checked. On by default.
With feature curves, each region of the curves (see set_feature_edges) is judged on its own: its triangles against the normal of its own triangles, before and after, and in each star the triangles of each region against theirs. Across a curve the surface may turn by any angle, and where it turns by more than 90 degrees – at a sharp edge of a B-rep – the normal of triangles on both sides points between them, so that well-oriented triangles of the smaller side face away from it; at 90 degrees or less they face along it. A curve that does not close off a region has the same region on both sides, and they are judged together, as without curves.
But where the surface turns by more than 90 degrees, a side has to turn by less than 90 – by 180 less the turn – to lie flat on the other, and then to pass through it, and so still faces along its own normal. So an operation may not close a crease either: a feature edge of the triangles it leaves, between two regions whose sides – each region's triangles round the edge's ends, their area vectors summed – faced more than 90 degrees apart before it, where the two triangles at the edge opened the wedge between the regions as the sides do. They still have to after it, by the sign of the exact orient3d of the edge's ends and the two apexes. The sides, not the two triangles, tell how the surface turns there: at a curve a needle's plane need not be its side's, and two triangles can be closed through each other already – the input has such wedges, which an operation may open. The edge a collapse along the curve leaves is judged against the one it continues; a split moves nothing, and turns no wedge. Where the surface turns by 90 degrees or less, a side has to turn by 90 or more to reach the other, and then no longer faces along its region's normal (where it is flat, at least). Without curves, and at a curve with one region on both sides, the check is the first paragraph's.
|
inline |
Repair, at the end of every iteration, the triangles whose smallest angle is under degrees; 0, the default, repairs none. Call before create_mesh(), which then keeps the input's area vectors for the fold test below.
See cleanup_triangles(). The passes leave such triangles where their criteria do not see them: next to a curve, where a vertex may not leave it and no swap or collapse may make an ear, a triangle between a curve vertex and one off the curves can stay thin; and in a fold the input brings, which the splits copy into the remeshing and the fold check then holds, every operation on it can count as folding.
| void wmtk::components::isotropic_remeshing::IsotropicRemeshing::set_feature_edges | ( | const std::vector< std::array< size_t, 2 > > & | edges | ) |
Curves the remeshing keeps: label boundaries, say.
A vertex on two feature edges is on a curve; one with one, or with three or more, ends a curve or joins several, and stays where it is. A split of a feature edge leaves two feature halves. A curve vertex collapses only along its curve, onto the survivor's position – with set_feature_envelope(), onto the midpoint unless the survivor stays put; a vertex off every curve collapses as before, onto the survivor's position if that one is on a curve. A feature edge is never swapped, and a curve vertex is smoothed along its curve only. No swap or collapse makes a triangle holding two curve edges, and remove_feature_ears() removes the ones the input has.
These are the rules wmtk::history::Replay carries feature edges by, so a recorded history holds the curves at every step.
It also gives each face the region of the curves it lies in – the faces it reaches without crossing a feature edge – which every face keeps: a split gives both halves the face's region, and since no curve is swapped or merged, no swap or collapse joins two regions. The fold check judges each region on its own (see set_check_inversions). A curve that does not close off a region – one ending away from other curves and the boundary – has the same region on both sides. It may come before create_mesh(), which then gives the faces their regions.
| void wmtk::components::isotropic_remeshing::IsotropicRemeshing::set_feature_envelope | ( | double | eps | ) |
Keep the curves near the feature edges as they are now – the input's, called before remeshing: every feature edge an operation leaves must lie within eps of them.
The surface envelope does not hold a curve. Where its two sides meet at an angle, a curve vertex smoothed across a bend of the curve, or a chord a collapse leaves across one, cuts the corner along one of the sides and stays inside the surface envelope; where they meet smoothly, a curve can wander across the surface. This tube judges the curves as BoundaryEnvelope judges the boundary, with the surface envelope's predicate (exact or sampled, as create_mesh() was given); a split, which moves nothing, is not judged. With the tube, a collapse along a curve puts the survivor at the midpoint, as any other collapse, unless it stays put (see stays_put): the tube refuses it where that leaves the curve. Off until called; eps <= 0 turns it off.
| void wmtk::components::isotropic_remeshing::IsotropicRemeshing::set_fixed_vertices | ( | const std::vector< std::pair< size_t, int64_t > > & | vertices | ) |
Vertices the remeshing keeps exactly: B-rep corners, say, which may sit inside a curve between two regions as well as where curves meet.
A fixed vertex stays put (see stays_put), and carries its id to the output. Call after create_mesh().
|
private |
Gives the faces the regions of the feature edges (see set_feature_edges), if there are feature edges; on a mesh with no faces yet, create_mesh() calls it again.
|
inline |
Swap an edge to raise the worse shape quality of its two triangles (see compute_swap_quality), instead of to bring the valences of its four vertices to 6 (4 on the boundary). Off by default.
Valence leaves a triangle as it is when the swap would not change the valences much: a flat one between two long edges, or a needle a curve leaves, which only the quality notices. The remeshing app of the topology-first B-rep pipeline swaps by quality.
|
overridevirtual |
User specified modifications and desideras after an edge smooth.
| the | edge Tuple to be smoothed |
Reimplemented from wmtk::TriMesh.
|
overridevirtual |
User specified preparations and desideratas for an edge smooth.
| the | edge Tuple to be smoothed |
Reimplemented from wmtk::TriMesh.
|
overridevirtual |
User specified modifications and desideratas after an edge split.
| the | edge Tuple to be split |
Reimplemented from wmtk::TriMesh.
|
overridevirtual |
User specified preparations and desideratas for an edge split.
| the | edge Tuple to be split |
Reimplemented from wmtk::TriMesh.
|
private |
Over the vertices of the triangles, the triangles of each one's star that do not face along the area_normal of their region of that star. An operation may read these stars: one that changes a star holds its centre, which is in the one-ring of what this operation changes, and so held by it.
| bool wmtk::components::isotropic_remeshing::IsotropicRemeshing::stays_put | ( | size_t | v | ) | const |
Whether v is never moved and never removed: a curve's end, a junction of curves, a vertex between feature edges of different ids, or a fixed vertex.
A collapse removes the vertex of its tuple and keeps the other; one that would remove such a vertex is refused (see may_collapse_away).
|
overridevirtual |
User specified modifications and desideras after an edge swap.
| the | edge Tuple to be swaped |
Reimplemented from wmtk::TriMesh.
|
overridevirtual |
User specified preparations and desideratas for an edge swap including 1.can't swap on boundary edge. 2. when swap edge between v1, v2, there can't exist edges between the two opposite vertices v3, v4.
| the | edge Tuple to be swaped |
Reimplemented from wmtk::TriMesh.
| wmtk::AttributeCollection<FaceFieldAttributes> wmtk::components::isotropic_remeshing::IsotropicRemeshing::face_field_attrs |
The mesh's face attributes once set_face_fields() or set_feature_edges() is called; untouched before.
| wmtk::BoundaryEnvelope wmtk::components::isotropic_remeshing::IsotropicRemeshing::m_boundary_envelope |
Tube around the boundary edges of the mesh given to create_mesh(), used instead of freezing the boundary when that gets a positive boundary_eps. See there. initialized() is false otherwise, and for a closed input.
|
private |
While cleanup_triangles() runs: the smallest angle around the triangle it repairs, which a collapse or swap has to beat. 0 otherwise.