#pragma once #include #include #include #include #include #include typedef enum { // PRIMITIVE_TYPE_CONSTANT, // PRIMITIVE_TYPE_PLANE, PRIMITIVE_TYPE_SPHERE, PRIMITIVE_TYPE_CYLINDER, PRIMITIVE_TYPE_CONE, PRIMITIVE_TYPE_BOX, // PRIMITIVE_TYPE_MESH, PRIMITIVE_TYPE_EXTRUDE_POLYLINE, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE, PRIMITIVE_TYPE_MAX_COUNT } primitive_type; // // Placeholder, currently used to represent empty body // typedef struct { // double value; // Use 0 to represent an empty body // } constant_descriptor_t; // Plane descriptor typedef struct { //vector3d point; // The base point of the plane //vector3d normal; // The normal of the plane vector2d local_aabb_min; vector2d local_aabb_max; } plane_descriptor_t; // Sphere descriptor typedef struct { vector3d center; // The center of the sphere double radius; // The radius of the sphere } sphere_descriptor_t; // Cylinder descriptor typedef struct { vector3d bottom_origin; // The origin of bottom face of the cylinder double radius; // The radius of the cylinder double height; // The total height of the cylinder vector3d offset; // The vector from the origion of bottom face to the origion of the top face } cylinder_descriptor_t; typedef struct { vector3d top_point; // The origin of top face of the cone vector3d bottom_point; // The origin of bottom face of the cone double radius1; // The radius of the top face double radius2; // The radius of the bottom face } cone_descriptor_t; typedef struct { vector3d center; // The center of the box vector3d half_size; // The { half_length, half_width, half_height} of the box } box_descriptor_t; // // Mesh descriptor // typedef struct { // uint32_t begin_index; // uint32_t vertex_count; // } polygon_face_descriptor_t; // typedef struct { // uint32_t point_number; // The point number of the mesh // uint32_t face_number; // The face number of the mesh // vector3d* points; // The points of the mesh // uint32_t* indices; // The indices from face to point // polygon_face_descriptor_t* faces; // Two-dimensional array, Use [begin index, length] to represent a face // } mesh_descriptor_t; // Extrude descriptor // CAUTION: when looking into the polyline from -{reference_normal} direction, all points should be arranged in counter // clockwise order // CAUTION: iff {is_closed} is true, then {point_number} == {bulge_number} should be agreed; iff {is_closed} is false, // then {point_number} == {bulge_number} + 1 should be agreed. typedef struct { uint32_t point_number; // The point number of the polyline vector3d* points; // The points of the polyline uint32_t bulge_number; // The bulge number of the polyline double* bulges; // The bulge of each edge vector3d reference_normal; // The reference normal of the polyline bool is_close; // Whether the polyline is close } polyline_descriptor_t; typedef struct { vector3d axis_start; // The start point of the helix line vector3d axis_end; // The end point of the helix line double radius; // The radius of the helix line double advance_per_round; // The advance per round of the helix line vector3d start_direction; // The direction from axisStart to start of the helix line bool is_righthanded; // {axis_start -> axis_end} as upward direction } helixline_descriptor_t; // 独立的 Profile Descriptor typedef struct { uint32_t point_number; vector3d* points; uint32_t bulge_number; double* bulges; vector3d reference_normal; bool is_close; } profile_descriptor_t; // (与 polyline_descriptor_t 完全相同) // Axis Descriptor typedef enum { AXIS_TYPE_POLYLINE, AXIS_TYPE_HELIXLINE } axis_type_t; typedef struct { axis_type_t type; union { polyline_descriptor_t polyline; helixline_descriptor_t helixline; } data; } axis_descriptor_t; // Note : In profiles, The first polyline is outer boundary, and the ohters is internal holes typedef struct { uint32_t profile_number; // The profiles number of the extruded solid polyline_descriptor_t* profiles; // The profiles of the extruded solid polyline_descriptor_t axis; // The axis of the extruded solid } extrude_polyline_descriptor_t; typedef struct { uint32_t profile_number; // The profiles number of the extruded solid polyline_descriptor_t* profiles; // The profiles of the extruded solid helixline_descriptor_t axis; // The axis of the extruded solid } extrude_helixline_descriptor_t; namespace descriptor_defaults { // @brief 单位平面:center=(0,0,0), r=1.0 inline constexpr plane_descriptor_t unit_plane{ vector2d{-1, -1}, // local_aabb_min vector2d{1, 1}, // local_aabb_max }; // @brief 单位球:center=(0,0,0), r=1.0 inline constexpr sphere_descriptor_t unit_sphere{ vector3d{0, 0, 0}, 1.0 }; /// @brief 单位圆柱:底面原点在(0,0,0),半径=1.0,高度=1.0 inline constexpr cylinder_descriptor_t unit_cylinder{ {0.0, 0.0, 0.0}, // bottom_origin: 原点在(0,0,0) 1.0, // radius: 半径为1.0 1.0, // height: 高度为1.0 {0.0, 0.0, 1.0} // offset: 沿Z轴向上偏移1.0 }; /// @brief 单位正方形 profile inline const polyline_descriptor_t unit_square_profile = [] { static const std::vector points = { //{-0.5, -0.5, 0.0}, //{0.5, -0.5, 0.0}, //{0.5, 0.5, 0.0}, //{-0.5, 0.5, 0.0} //{-1.5, -1.5, 0.0}, //{1.5, -1.5, 0.0}, //{0.0, 6.0, 0.0} //{0.0, 0.430871, -0.902414}, // 局部坐标: (1, 1) //{0.0, -0.430871, 0.902414 }, // 局部坐标: (-1, 1) //{2.0, -0.430871, 0.902414 }, // 局部坐标: (-1, -1) //{2.0, 0.430871, -0.902414} // 局部坐标: (1, -1) {0.0, 0.430871, -0.902414}, {0.0, -0.430871, 0.902414 }, {2.0, 0.1, -0.6}, {2.0, 0.430871, -0.902414} //{0.0, 0.430871, -0.902414}, // 局部坐标: (1, 1) //{1.0, -0.430871, 0.902414 }, //{6.0, 0.430871, -0.902414} // 局部坐标: (1, -1) }; // static const std::vector bulges = {0.4, -0.8, 1.0, -0.5}; // static const std::vector bulges = {-0.4, 0.8, 0.0, -0.5}; // polyline ERROR // static const std::vector bulges = {0.0, 0.0, -0.5, 0.0}; // helixline ERROR static const std::vector bulges = {0.0, 0.0, 1.0, 0.0}; // helixline ERROR polyline_descriptor_t desc; desc.point_number = 4; desc.points = const_cast(points.data()); desc.bulge_number = 4; desc.bulges = const_cast(bulges.data()); desc.reference_normal = {0, 0, 1}; desc.is_close = true; return desc; }(); inline const std::vector unit_axis_points = { {0.0, 0.0, -0.5}, {0.0, 6.0, 6.0 } //{4.0, 0.0, 1.0} //{4.0, 0.0, -1.0} }; inline const std::vector unit_axis_bulges = {0.0}; inline const polyline_descriptor_t unit_polyline_axis = [] { polyline_descriptor_t desc; desc.point_number = 2; desc.points = const_cast(unit_axis_points.data()); desc.bulge_number = 1; desc.bulges = const_cast(unit_axis_bulges.data()); desc.reference_normal = {0, 1, 0}; // 注意 reference_normal 要垂直与 axis 所在平面 desc.is_close = false; return desc; }(); inline const extrude_polyline_descriptor_t unit_extrude_polyline = [] { extrude_polyline_descriptor_t desc; desc.profile_number = 1; desc.profiles = const_cast(&unit_square_profile); desc.axis = unit_polyline_axis; return desc; }(); /// @brief 单位螺旋线:默认参数 inline constexpr helixline_descriptor_t unit_helix = { {0.0, 0.0, 0.0}, // axis_start {0.0, 0.0, 10.0}, // axis_end 1.0, // radius 3.0, // advance_per_round {1.0, 0.0, 0.0}, // start_direction true // is_righthanded }; /// @brief 单位拉伸 helixline inline const extrude_helixline_descriptor_t unit_extrude_helixline = [] { extrude_helixline_descriptor_t desc; desc.profile_number = 1; desc.profiles = const_cast(&unit_square_profile); desc.axis = unit_helix; return desc; }(); } // namespace descriptor_defaults namespace detail { template inline void hash_combine(size_t& seed, const T& val) { seed ^= std::hash{}(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } template <> struct hasher { size_t operator()(const polyline_descriptor_t& desc) const { size_t h = 0; hash_combine(h, desc.point_number); hash_combine(h, desc.bulge_number); hash_combine(h, desc.is_close); hash_combine(h, desc.reference_normal.x); hash_combine(h, desc.reference_normal.y); hash_combine(h, desc.reference_normal.z); // 点数据 for (uint32_t i = 0; i < desc.point_number; ++i) { hash_combine(h, desc.points[i].x); hash_combine(h, desc.points[i].y); hash_combine(h, desc.points[i].z); } // Bulge 数据 for (uint32_t i = 0; i < desc.bulge_number; ++i) { hash_combine(h, desc.bulges[i]); } return h; } }; template <> struct eq_compare { bool operator()(const polyline_descriptor_t& lhs, const polyline_descriptor_t& rhs) const { if (lhs.point_number != rhs.point_number) return false; if (lhs.bulge_number != rhs.bulge_number) return false; if (lhs.is_close != rhs.is_close) return false; if (lhs.reference_normal.x != rhs.reference_normal.x || lhs.reference_normal.y != rhs.reference_normal.y || lhs.reference_normal.z != rhs.reference_normal.z) { return false; } for (uint32_t i = 0; i < lhs.point_number; ++i) { if (lhs.points[i].x != rhs.points[i].x || lhs.points[i].y != rhs.points[i].y || lhs.points[i].z != rhs.points[i].z) { return false; } } for (uint32_t i = 0; i < lhs.bulge_number; ++i) { if (lhs.bulges[i] != rhs.bulges[i]) { return false; } } return true; } }; template <> struct hasher { size_t operator()(const helixline_descriptor_t& desc) const { size_t h = 0; hash_combine(h, desc.axis_start.x); hash_combine(h, desc.axis_start.y); hash_combine(h, desc.axis_start.z); hash_combine(h, desc.axis_end.x); hash_combine(h, desc.axis_end.y); hash_combine(h, desc.axis_end.z); hash_combine(h, desc.radius); hash_combine(h, desc.advance_per_round); hash_combine(h, desc.start_direction.x); hash_combine(h, desc.start_direction.y); hash_combine(h, desc.start_direction.z); hash_combine(h, desc.is_righthanded); return h; } }; template <> struct eq_compare { bool operator()(const helixline_descriptor_t& lhs, const helixline_descriptor_t& rhs) const { constexpr double eps = 1e-12; return std::abs(lhs.axis_start.x - rhs.axis_start.x) < eps && std::abs(lhs.axis_start.y - rhs.axis_start.y) < eps && std::abs(lhs.axis_start.z - rhs.axis_start.z) < eps && std::abs(lhs.axis_end.x - rhs.axis_end.x) < eps && std::abs(lhs.axis_end.y - rhs.axis_end.y) < eps && std::abs(lhs.axis_end.z - rhs.axis_end.z) < eps && std::abs(lhs.radius - rhs.radius) < eps && std::abs(lhs.advance_per_round - rhs.advance_per_round) < eps && std::abs(lhs.start_direction.x - rhs.start_direction.x) < eps && std::abs(lhs.start_direction.y - rhs.start_direction.y) < eps && std::abs(lhs.start_direction.z - rhs.start_direction.z) < eps && lhs.is_righthanded == rhs.is_righthanded; } }; // Profile Descriptor Hash(复用 polyline 逻辑) template <> struct hasher { size_t operator()(const profile_descriptor_t& desc) const { // profile_descriptor_t 和 polyline_descriptor_t 布局完全相同 return hasher{}(*reinterpret_cast(&desc)); } }; template <> struct eq_compare { bool operator()(const profile_descriptor_t& lhs, const profile_descriptor_t& rhs) const { return eq_compare{}(*reinterpret_cast(&lhs), *reinterpret_cast(&rhs)); } }; // Axis Descriptor Hash template <> struct hasher { size_t operator()(const axis_descriptor_t& desc) const { size_t h = std::hash{}(static_cast(desc.type)); if (desc.type == AXIS_TYPE_POLYLINE) { hash_combine(h, hasher{}(desc.data.polyline)); } else if (desc.type == AXIS_TYPE_HELIXLINE) { hash_combine(h, hasher{}(desc.data.helixline)); } return h; } }; template <> struct eq_compare { bool operator()(const axis_descriptor_t& lhs, const axis_descriptor_t& rhs) const { if (lhs.type != rhs.type) return false; if (lhs.type == AXIS_TYPE_POLYLINE) { return eq_compare{}(lhs.data.polyline, rhs.data.polyline); } else if (lhs.type == AXIS_TYPE_HELIXLINE) { return eq_compare{}(lhs.data.helixline, rhs.data.helixline); } return true; } }; template <> struct hasher { size_t operator()(const plane_descriptor_t& desc) const { size_t seed = 0; hash_combine(seed, desc.local_aabb_max.x); hash_combine(seed, desc.local_aabb_max.y); hash_combine(seed, desc.local_aabb_min.x); hash_combine(seed, desc.local_aabb_min.y); return seed; } }; template <> struct eq_compare { bool operator()(const plane_descriptor_t& lhs, const plane_descriptor_t& rhs) const { constexpr double eps = 1e-12; return std::abs(lhs.local_aabb_max.x - rhs.local_aabb_max.x) < eps && std::abs(lhs.local_aabb_max.y - rhs.local_aabb_max.y) < eps && std::abs(lhs.local_aabb_min.x - rhs.local_aabb_min.x) < eps && std::abs(lhs.local_aabb_min.y - rhs.local_aabb_min.y) < eps; } }; template <> struct hasher { size_t operator()(const cylinder_descriptor_t& desc) const { size_t seed = 0; hash_combine(seed, desc.bottom_origin.x); hash_combine(seed, desc.bottom_origin.y); hash_combine(seed, desc.bottom_origin.z); hash_combine(seed, desc.radius); hash_combine(seed, desc.height); hash_combine(seed, desc.offset.x); hash_combine(seed, desc.offset.y); hash_combine(seed, desc.offset.z); return seed; } }; template <> struct eq_compare { bool operator()(const cylinder_descriptor_t& lhs, const cylinder_descriptor_t& rhs) const { constexpr double eps = 1e-12; return std::abs(lhs.radius - rhs.radius) < eps && std::abs(lhs.height - rhs.height) < eps; } }; template <> struct hasher { size_t operator()(const extrude_polyline_descriptor_t& desc) const { size_t h = 0; hash_combine(h, desc.profile_number); hash_combine(h, desc.axis.point_number); hash_combine(h, desc.axis.bulge_number); hash_combine(h, static_cast(desc.axis.is_close)); if (desc.profiles && desc.profile_number > 0) { const auto& p = desc.profiles[0]; hash_combine(h, p.point_number); hash_combine(h, p.bulge_number); hash_combine(h, static_cast(p.is_close)); // 哈希所有点的坐标 for (uint32_t i = 0; i < p.point_number; ++i) { hash_combine(h, p.points[i].x); hash_combine(h, p.points[i].y); hash_combine(h, p.points[i].z); } } // 哈希 axis 数据 for (uint32_t i = 0; i < desc.axis.point_number; ++i) { hash_combine(h, desc.axis.points[i].x); hash_combine(h, desc.axis.points[i].y); hash_combine(h, desc.axis.points[i].z); } return h; } }; // extrude_polyline_descriptor_t 的相等比较 template <> struct eq_compare { bool operator()(const extrude_polyline_descriptor_t& lhs, const extrude_polyline_descriptor_t& rhs) const { // 比较指针地址 if (lhs.profiles != rhs.profiles) return false; if (lhs.axis.points != rhs.axis.points) return false; if (lhs.axis.bulges != rhs.axis.bulges) return false; // 比较基本字段 if (lhs.profile_number != rhs.profile_number) return false; if (lhs.axis.point_number != rhs.axis.point_number) return false; if (lhs.axis.bulge_number != rhs.axis.bulge_number) return false; if (lhs.axis.is_close != rhs.axis.is_close) return false; return true; } }; // extrude_helixline_descriptor_t 的哈希 template <> struct hasher { size_t operator()(const extrude_helixline_descriptor_t& desc) const { size_t h = 0; hash_combine(h, desc.profile_number); // 哈希所有 profiles for (uint32_t profile_idx = 0; profile_idx < desc.profile_number; ++profile_idx) { if (!desc.profiles) break; const auto& profile = desc.profiles[profile_idx]; hash_combine(h, profile.point_number); hash_combine(h, profile.bulge_number); hash_combine(h, profile.is_close); // reference_normal hash_combine(h, profile.reference_normal.x); hash_combine(h, profile.reference_normal.y); hash_combine(h, profile.reference_normal.z); for (uint32_t i = 0; i < profile.point_number; ++i) { hash_combine(h, profile.points[i].x); hash_combine(h, profile.points[i].y); hash_combine(h, profile.points[i].z); } for (uint32_t i = 0; i < profile.bulge_number; ++i) { hash_combine(h, profile.bulges[i]); } } // 哈希 helixline axis(完整字段) hash_combine(h, desc.axis.axis_start.x); hash_combine(h, desc.axis.axis_start.y); hash_combine(h, desc.axis.axis_start.z); hash_combine(h, desc.axis.axis_end.x); hash_combine(h, desc.axis.axis_end.y); hash_combine(h, desc.axis.axis_end.z); hash_combine(h, desc.axis.radius); hash_combine(h, desc.axis.advance_per_round); // start_direction hash_combine(h, desc.axis.start_direction.x); hash_combine(h, desc.axis.start_direction.y); hash_combine(h, desc.axis.start_direction.z); hash_combine(h, desc.axis.is_righthanded); return h; } }; // extrude_helixline_descriptor_t 的相等比较 template <> struct eq_compare { bool operator()(const extrude_helixline_descriptor_t& lhs, const extrude_helixline_descriptor_t& rhs) const { constexpr double eps = 1e-12; if (lhs.profile_number != rhs.profile_number) return false; // // 比较所有 profiles for (uint32_t profile_idx = 0; profile_idx < lhs.profile_number; ++profile_idx) { const auto& lp = lhs.profiles[profile_idx]; const auto& rp = rhs.profiles[profile_idx]; if (lp.point_number != rp.point_number) return false; if (lp.bulge_number != rp.bulge_number) return false; if (lp.is_close != rp.is_close) return false; // reference_normal if (std::abs(lp.reference_normal.x - rp.reference_normal.x) > eps) return false; if (std::abs(lp.reference_normal.y - rp.reference_normal.y) > eps) return false; if (std::abs(lp.reference_normal.z - rp.reference_normal.z) > eps) return false; for (uint32_t i = 0; i < lp.point_number; ++i) { if (std::abs(lp.points[i].x - rp.points[i].x) > eps) return false; if (std::abs(lp.points[i].y - rp.points[i].y) > eps) return false; if (std::abs(lp.points[i].z - rp.points[i].z) > eps) return false; } for (uint32_t i = 0; i < lp.bulge_number; ++i) { if (std::abs(lp.bulges[i] - rp.bulges[i]) > eps) return false; } } // 比较 helixline axis(完整字段) if (std::abs(lhs.axis.axis_start.x - rhs.axis.axis_start.x) > eps) return false; if (std::abs(lhs.axis.axis_start.y - rhs.axis.axis_start.y) > eps) return false; if (std::abs(lhs.axis.axis_start.z - rhs.axis.axis_start.z) > eps) return false; if (std::abs(lhs.axis.axis_end.x - rhs.axis.axis_end.x) > eps) return false; if (std::abs(lhs.axis.axis_end.y - rhs.axis.axis_end.y) > eps) return false; if (std::abs(lhs.axis.axis_end.z - rhs.axis.axis_end.z) > eps) return false; if (std::abs(lhs.axis.radius - rhs.axis.radius) > eps) return false; if (std::abs(lhs.axis.advance_per_round - rhs.axis.advance_per_round) > eps) return false; // start_direction if (std::abs(lhs.axis.start_direction.x - rhs.axis.start_direction.x) > eps) return false; if (std::abs(lhs.axis.start_direction.y - rhs.axis.start_direction.y) > eps) return false; if (std::abs(lhs.axis.start_direction.z - rhs.axis.start_direction.z) > eps) return false; if (lhs.axis.is_righthanded != rhs.axis.is_righthanded) return false; return true; } }; } // namespace descriptor_defaults