#pragma once #include #include #include namespace internal { /* tags for identifying which equation system is used for the * subface */ enum class equation_system_type { invalid, implicit, parametric }; /* type-tags for identifying constrained parameter var */ struct parameter_u_t { } static inline parameter_u; struct parameter_v_t { } static inline parameter_v; // CAUTION: all should be in world space struct constraint_curve_intermediate { Eigen::Vector4d f; // x(t), y(t), z(t), 1 Eigen::Vector4d grad_f; // dx/dt, dy/dt, dz/dt, 0 }; struct implicit_equation_intermediate { double f; double df; }; struct parametric_equation_intermediate { Eigen::Vector3d f; // approx. surface point by surface, can also be seen // as f(u,v), g(u,v) and h(u,v) Eigen::Matrix grad_f; // [[df/du, df/dv]; [dg/du, dg/dv]; // [dh/du, dh/dv]] }; using equation_intermediate_t = std::variant; enum class periodical_state_t : uint8_t { invalid = 0, near_cycle_start = 1, near_cycle_end = 2, on_cycle = 3 }; static inline periodical_state_t operator|(const periodical_state_t &x, const periodical_state_t &y) { return static_cast(static_cast(x) | static_cast(y)); } static inline periodical_state_t operator&(const periodical_state_t &x, const periodical_state_t &y) { return static_cast(static_cast(x) & static_cast(y)); } static inline bool operator>(const periodical_state_t &lhs, const periodical_state_t &rhs) { return static_cast(lhs) > static_cast(rhs); } static inline bool operator>=(const periodical_state_t &lhs, const periodical_state_t &rhs) { return static_cast(lhs) >= static_cast(rhs); } static inline bool operator<(const periodical_state_t &lhs, const periodical_state_t &rhs) { return static_cast(lhs) < static_cast(rhs); } static inline bool operator<=(const periodical_state_t &lhs, const periodical_state_t &rhs) { return static_cast(lhs) <= static_cast(rhs); } } // namespace internal EXTERN_C struct PE_API subface : internal::paired_model_matrix { subface() noexcept = default; subface(const subface &) noexcept = default; subface(subface &&) noexcept = default; subface &operator=(const subface &) noexcept = default; subface &operator=(subface &&) noexcept = default; virtual ~subface() noexcept = default; Eigen::Vector3d local_to_world_scale() const { return local_to_world.linear().colwise().norm(); } Eigen::Matrix3d trans_world_to_local_linear() const { return world_to_local.linear().transpose(); } }; namespace internal { using eval_sdf_ptr_t = double (*)(pointer_wrapper, Eigen::Vector3d); using eval_sdf_grad_ptr_t = Eigen::Vector3d (*)(pointer_wrapper, Eigen::Vector3d); // using map_param_to_point_ptr_t = Eigen::Vector4d (*)(pointer_wrapper, Eigen::Vector2d); using map_point_to_param_ptr_t = Eigen::Vector2d (*)(pointer_wrapper, Eigen::Vector3d); // return: world position, surface jacobi weight, volume jacobi weight * dot(world position, normal) // surface jacobi weight = |local_to_world||trans_world_to_local * normal| * to param jacobi // volume jacobi weight = |local_to_world| * to param jacobi using map_param_to_point_with_weight_ptr_t = std::tuple (*)(pointer_wrapper, Eigen::Vector2d); using eval_du_constraint_ptr_t = internal::constraint_curve_intermediate (*)(pointer_wrapper, Eigen::Vector2d); using eval_dv_constraint_ptr_t = internal::constraint_curve_intermediate (*)(pointer_wrapper, Eigen::Vector2d); using eval_intersection_ptr_t = internal::equation_intermediate_t (*)(pointer_wrapper, const internal::constraint_curve_intermediate &); using decide_periodical_state_ptr_t = std::array (*)(pointer_wrapper, Eigen::Vector4d); using geometry_accessor_ptr_t = const void* (*)(pointer_wrapper); #define def_subface_function_impl(subface_name) \ struct subface_name##_function_impl { \ static double eval_sdf(pointer_wrapper, Eigen::Vector3d); \ static Eigen::Vector3d eval_sdf_grad(pointer_wrapper, Eigen::Vector3d); \ static Eigen::Vector2d map_point_to_param(pointer_wrapper, Eigen::Vector3d); \ static std::tuple map_param_to_point_with_weight(pointer_wrapper, \ Eigen::Vector2d); \ static internal::constraint_curve_intermediate eval_du_constraint(pointer_wrapper, Eigen::Vector2d); \ static internal::constraint_curve_intermediate eval_dv_constraint(pointer_wrapper, Eigen::Vector2d); \ static internal::equation_intermediate_t eval_intersection(pointer_wrapper, \ const internal::constraint_curve_intermediate &); \ static std::array decide_periodical_state(pointer_wrapper, Eigen::Vector4d); \ static const void* geometry_accessor(pointer_wrapper); \ } def_subface_function_impl(plane); def_subface_function_impl(sphere); def_subface_function_impl(cylinder); // def_subface_function_impl(cone); def_subface_function_impl(extrude_polyline_side); def_subface_function_impl(extrude_helixline_side); #undef def_subface_function_impl #define def_export_get_function_ptr(func_name) PE_API func_name##_ptr_t get_##func_name##_ptr(surface_type) def_export_get_function_ptr(eval_sdf); def_export_get_function_ptr(eval_sdf_grad); def_export_get_function_ptr(map_point_to_param); def_export_get_function_ptr(map_param_to_point_with_weight); def_export_get_function_ptr(eval_du_constraint); def_export_get_function_ptr(eval_dv_constraint); def_export_get_function_ptr(eval_intersection); def_export_get_function_ptr(decide_periodical_state); def_export_get_function_ptr(geometry_accessor); #undef def_export_get_function_ptr // for getting range for each kind of subface // in turn: (end, is_periodical) // assume: start is always 0 PE_API std::pair get_range_u(surface_type); PE_API std::pair get_range_v(surface_type); // used for getting position independent periodical state (2pi) static inline periodical_state_t common_decide_periodical_state(Eigen::Vector4d local_pos) { if (local_pos.x() <= 0) return periodical_state_t::invalid; else if (local_pos.y() < 0) return periodical_state_t::near_cycle_end; else if (local_pos.y() > 0) return periodical_state_t::near_cycle_start; else return periodical_state_t::on_cycle; } } // namespace internal