#pragma once #include #include namespace internal { // local: plane x=0 // u: planar local x-axis // v: planar local y-axis struct plane_t final : subface { const plane_descriptor_t* geometry_ptr = nullptr; const plane_descriptor_t* get_geometry_ptr() const { return geometry_ptr; // plane 可以没有 descriptor } }; } // namespace internal namespace detail { template <> struct hasher { size_t operator()(const internal::plane_t& subface) const { // CAUTION: we use vec4d to contain translation info here // to do this, we have to use the first row of world_to_local instead of the first column of local_to_world // since the later one does not contain translation info Eigen::Vector4d vec = subface.world_to_local.matrix().row(0); vec.head<3>().normalize(); if (vec.z() < 0) vec.head<3>() = -vec.head<3>(); return hash_funcs(vec); } }; // only when hash is equal so that eq is called, so we do not have to reverse signs here template <> struct eq_compare { bool operator()(const internal::plane_t& lhs, const internal::plane_t& rhs) const { //return eq_funcs(lhs.local_to_world, rhs.local_to_world); constexpr double eps = 1e-12; return lhs.world_to_local.isApprox(rhs.world_to_local, eps); } }; } // namespace detail