#pragma once #include #include struct simplified_vertex_header_t { uint32_t volume_index{}; uint32_t local_vertex_index{}; }; struct component_header_t { uint32_t vertex_index{}; uint32_t component_index{}; }; struct face_with_orient_t { uint32_t face_id{}; int8_t orient{}; }; namespace std { template <> struct hash { size_t operator()(const simplified_vertex_header_t &k) const { return (static_cast(k.volume_index) << 32) | k.local_vertex_index; // return std::hash()(k.volume_index) ^ std::hash()(k.local_vertex_index); } }; template <> struct hash { size_t operator()(const component_header_t &k) const { return (static_cast(k.vertex_index) << 32) | k.component_index; // return std::hash()(k.vertex_index) ^ std::hash()(k.component_index); } }; template <> struct hash { size_t operator()(const face_with_orient_t &k) const { return (static_cast(k.face_id) << 32) | k.orient; // return std::hash()(k.face_id) ^ std::hash()(k.orient); } }; template <> struct equal_to { bool operator()(const simplified_vertex_header_t &k1, const simplified_vertex_header_t &k2) const { return k1.volume_index == k2.volume_index && k1.local_vertex_index == k2.local_vertex_index; } }; template <> struct equal_to { bool operator()(const component_header_t &k1, const component_header_t &k2) const { return k1.vertex_index == k2.vertex_index && k1.component_index == k2.component_index; } }; template <> struct equal_to { bool operator()(const face_with_orient_t &k1, const face_with_orient_t &k2) const { return k1.face_id == k2.face_id && k1.orient == k2.orient; } }; } // namespace std // topological ray shooting for implicit arrangement ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t &tet_mesh, const stl_vector_mp> &cut_results, const stl_vector_mp &iso_verts, const stl_vector_mp &iso_faces, const stl_vector_mp> &patches, const stl_vector_mp &patch_of_face, const stl_vector_mp> &shells, const stl_vector_mp &shell_of_half_patch, const stl_vector_mp> &components, const stl_vector_mp &component_of_patch, stl_vector_mp> &shell_links); // Given tet mesh, // build the map: v-->v_next, where v_next has lower order than v ISNP_API void build_next_vert(const tetrahedron_mesh_t &tet_mesh, stl_vector_mp &next_vert); // find extremal edge for each component ISNP_API void find_extremal_edges(const stl_vector_mp &pts, const stl_vector_mp &iso_verts, const stl_vector_mp &iso_faces, const stl_vector_mp> &patches, const stl_vector_mp> &components, const stl_vector_mp &component_of_patch, const stl_vector_mp &next_vert, // extremal edge of component i is stored at position [2*i], [2*i+1] stl_vector_mp &extremal_edge_of_component, // store an iso-vert index on edge (v, v_next), None means there is no such iso-vert stl_vector_mp &iso_vert_on_v_v_next, // map: (tet_id, tet_face_id) --> iso_face_id flat_hash_map_mp &iso_face_id_of_tet_face, // map: (tet_id, tet_vert_id) --> (iso_vert_id, component_id) flat_hash_map_mp &iso_vId_compId_of_tet_vert); // compute the order of iso-vertices on a tet edge v->u, v,u in {0,1,2,3} // return a list of sorted vertex indices {v_id, i1, i2, ..., u_id} ISNP_API void compute_edge_intersection_order(const arrangement_t &tet_cut_result, uint32_t v, uint32_t u, stl_vector_mp &vert_indices); // find the two faces passing v1 and v2, v1->v2 is part of a tet edge ISNP_API void compute_passing_face_pair(const arrangement_t &tet_cut_result, uint32_t v1, uint32_t v2, face_with_orient_t &face_orient1, face_with_orient_t &face_orient2); // find the face passing v, v->u is part of a tet edge, and u is a tet vertex ISNP_API void compute_passing_face(const arrangement_t &tet_cut_result, uint32_t v, uint32_t u, face_with_orient_t &face_orient); // point (x,y,z): dictionary order inline bool point_xyz_less(const raw_point_t &p, const raw_point_t &q) { return std::lexicographical_compare(p.begin(), p.end(), q.begin(), q.end()); }