#pragma once #include #include #include #include #include #include "primitive_descriptor.h" // ========================================================================================================================= class evaluation_routine_tag { }; class closest_point_routine_tag { }; template static constexpr bool is_process_routine_tag_v = std::is_same_v || std::is_same_v; template static constexpr bool is_evaluation_routine_v = std::is_same_v; template static constexpr bool is_closest_point_routine_v = std::is_same_v; template using process_return_type_t = std::conditional_t, double, Eigen::Vector3d>; // static constexpr evaluation_routine_tag evaluation_tag{}; // static constexpr closest_point_routine_tag closest_point_tag{}; // ========================================================================================================================= template using aabb_t = std::conditional_t; using legal_primitive_descriptor_t = std::variant; struct PE_API primitive_node_t { aabb_t<> aabb{}; void* desc{nullptr}; // Type conversion when using primitive_type type{}; primitive_node_t(const legal_primitive_descriptor_t&) noexcept; primitive_node_t(legal_primitive_descriptor_t&&) noexcept; ~primitive_node_t() noexcept; template process_return_type_t evaluate([[maybe_unused]] const Eigen::Ref&) const; }; static constexpr auto EPSILON = std::numeric_limits::epsilon() * 1e6; static constexpr auto PI = 3.14159265358979323846; static constexpr auto TWO_PI = PI * 2; static constexpr auto PI2 = PI / 2; static constexpr auto INV_PI = 1. / PI; static constexpr auto INV_TWO_PI = 1. / TWO_PI; static const auto x_direction = Eigen::Vector3d{1.0, 0.0, 0.0}; inline void vec3d_conversion(const raw_vector3d_t& src, Eigen::Ref dst) { dst = Eigen::Map(&src.x); } inline void vec3d_conversion(raw_vector3d_t&& src, Eigen::Ref dst) { std::move(&src.x, &src.x + 3, dst.data()); } inline double sign(const double t) { return t >= 0.0 ? 1.0 : -1.0; } namespace internal { template using stl_vector = std::vector>; struct line_closest_param_t { Eigen::Vector3d point{}; double t{}; bool is_peak_value{}; }; #define DEF_PRIMITIVE_COMMON_METHODS(internal_type, descriptor_type) \ internal_type(const descriptor_type&, aabb_t<>&); \ internal_type(descriptor_type&&, aabb_t<>&); \ template \ process_return_type_t evaluate([[maybe_unused]] const Eigen::Ref&) const; struct PE_API constant { double value{}; DEF_PRIMITIVE_COMMON_METHODS(constant, constant_descriptor_t) }; struct PE_API plane { Eigen::Vector3d point{}; Eigen::Vector3d normal{}; DEF_PRIMITIVE_COMMON_METHODS(plane, plane_descriptor_t) }; struct PE_API sphere { Eigen::Vector3d center{}; double radius{}; DEF_PRIMITIVE_COMMON_METHODS(sphere, sphere_descriptor_t) }; struct PE_API cylinder { Eigen::Vector3d bottom_center{}; Eigen::Vector3d offset{}; double radius{}; DEF_PRIMITIVE_COMMON_METHODS(cylinder, cylinder_descriptor_t) }; struct PE_API cone { Eigen::Vector3d top_center{}; Eigen::Vector3d bottom_center{}; double radius1{}; double radius2{}; DEF_PRIMITIVE_COMMON_METHODS(cone, cone_descriptor_t) }; struct PE_API box { Eigen::Vector3d center{}; Eigen::Vector3d half_size{}; DEF_PRIMITIVE_COMMON_METHODS(box, box_descriptor_t) }; struct PE_API mesh { stl_vector vertices{}; stl_vector> faces{}; DEF_PRIMITIVE_COMMON_METHODS(mesh, mesh_descriptor_t) }; // CAUTION: in polyline local space, the X/Y axis should be according to local N/B directions struct polyline { std::vector vertices{}; // // for a straight line, it consists of two vertices; for a circle arc, it consists // of three vertices: start point, circle center, and a point on the circle to // construct local XY coordinate system std::vector thetas{}; // for a straight line, this should be 0 std::vector start_indices{}; // has the same size as thetas, indicating the starting index of each segment void build_as_axis(const polyline_descriptor_t&, const raw_vector3d_t&, Eigen::Ref>, aabb_t<>&); void build_as_axis(polyline_descriptor_t&&, const raw_vector3d_t&, Eigen::Ref>, aabb_t<>&); void build_as_profile(const polyline_descriptor_t&, const Eigen::Ref>&, aabb_t<>&); void build_as_profile(polyline_descriptor_t&&, const Eigen::Ref>&, aabb_t<>&); [[nodiscard]] Eigen::Vector3d calculate_tangent(double) const; [[nodiscard]] Eigen::Vector3d calculate_normal(double) const; [[nodiscard]] line_closest_param_t calculate_closest_param(const Eigen::Ref&) const; }; struct helixline { double radius{}; double total_theta{}; double height{}; // CAUTION: here returned aabb is in helixline's local space helixline(const helixline_descriptor_t&, Eigen::Ref>&, aabb_t<>&); helixline(helixline_descriptor_t&&, Eigen::Ref>&, aabb_t<>&); [[nodiscard]] Eigen::Vector3d calculate_tangent(double) const; [[nodiscard]] Eigen::Vector3d calculate_normal(double) const; [[nodiscard]] line_closest_param_t calculate_closest_param(const Eigen::Ref&) const; }; struct PE_API extrude_polyline { Eigen::Transform axis_to_world{}; polyline axis; polyline profile; DEF_PRIMITIVE_COMMON_METHODS(extrude_polyline, extrude_polyline_descriptor_t) }; struct PE_API extrude_helixline { Eigen::Transform axis_to_world{}; helixline axis; polyline profile; DEF_PRIMITIVE_COMMON_METHODS(extrude_helixline, extrude_helixline_descriptor_t) }; #undef DEF_PRIMITIVE_COMMON_METHODS } // namespace internal