From 037922a878da7bd8e4f17534df9896fdc8c24c20 Mon Sep 17 00:00:00 2001 From: Zhicheng Wang <1627343141@qq.com> Date: Mon, 29 Jun 2026 05:44:40 +0800 Subject: [PATCH] take height into axis_to_world of helixline --- frontend/src/io_axis.cpp | 229 ++++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 114 deletions(-) diff --git a/frontend/src/io_axis.cpp b/frontend/src/io_axis.cpp index f7f57fe..6408748 100644 --- a/frontend/src/io_axis.cpp +++ b/frontend/src/io_axis.cpp @@ -1,115 +1,116 @@ -#include "io_primitive.h" - -#include - -auto construct_polyline_extrude_axis(const polyline_axis_descriptor_t& desc) -{ - bool is_ccw{}; - - const Eigen::Vector3d vert0 = convert_vec3d(desc.points[0]); - const Eigen::Vector3d vert1 = convert_vec3d(desc.points[1]); - Eigen::Vector3d vec_x = vert1 - vert0; - vec_x.normalize(); - Eigen::Vector3d vec_z = convert_vec3d(desc.reference_normal); - Eigen::Vector3d vec_y = vec_z.cross(vec_x); - - if (desc.point_number == 2) - is_ccw = true; - else { - const Eigen::Vector3d vert2 = convert_vec3d(desc.points[2]); - const auto& bulge0 = desc.bulges[0]; - const auto& bulge1 = desc.bulges[1]; - auto ccw_by_cross = (vert2 - vert1).dot(vec_y) > 0; - auto ccw_by_bulge = bulge0 < 0 && bulge1 < 0; - is_ccw = ccw_by_cross || ccw_by_bulge; - } - - std::vector vertices(desc.point_number); - std::vector bulges(desc.bulge_number); - // 偏移点坐标,并重新处理bulge为tan(theta/2) - if (is_ccw) { - std::transform(desc.points, desc.points + desc.point_number, vertices.begin(), [&](vector3d p) { - Eigen::Vector3d p_ = {p.x, p.y, p.z}; - p_ -= vert0; - return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; - }); - std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.begin(), [&](double bulge) { - return 2 * bulge / (1 - bulge * bulge); - }); - } else { - std::transform(desc.points, desc.points + desc.point_number, vertices.rbegin(), [&](vector3d p) { - Eigen::Vector3d p_ = {p.x, p.y, p.z}; - p_ -= vert0; - return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; - }); - std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.rbegin(), [&](double bulge) { - return 2 * bulge / (1 - bulge * bulge); - }); - } - - internal::polyline_extrude_axis obj{}; - obj.vertices = std::move(vertices); - obj.bulges = std::move(bulges); - - Eigen::AffineCompact3d axis_to_world{}; - axis_to_world.matrix().col(0) = vec_x; - axis_to_world.matrix().col(1) = vec_y; - axis_to_world.matrix().col(2) = vec_z; - axis_to_world.matrix().col(3) = vert0; - - return std::make_tuple(obj, desc.is_closed, axis_to_world); -} - -auto construct_helixline_extrude_axis(const helixline_axis_descriptor_t& desc) -{ - Eigen::Vector3d origin = convert_vec3d(desc.axis_start); - Eigen::Vector3d vec_z = convert_vec3d(desc.axis_end) - origin; - auto height = vec_z.norm(); - vec_z /= height; - auto total_theta = height / desc.advance_per_round * two_pi; - - internal::helixline_extrude_axis obj{}; - obj.scale_coeff_x = desc.radius; - obj.scale_coeff_y = desc.radius * height - * std::sqrt((total_theta * total_theta + 1) - / (desc.radius * desc.radius * total_theta * total_theta + height * height)); - obj.total_theta = total_theta; - - Eigen::AffineCompact3d axis_to_world = Eigen::AffineCompact3d::Identity(); - auto rot = Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d{0, 0, 1}, vec_z); - rot *= Eigen::Quaterniond::FromTwoVectors(rot * Eigen::Vector3d(1, 0, 0), convert_vec3d(desc.start_direction)); - if (!desc.is_righthanded) axis_to_world.matrix().col(1).y() = -1; - axis_to_world = rot * axis_to_world; - axis_to_world.translation() = origin; - - return std::make_tuple(obj, false, axis_to_world); -} - -EXTERN_C_BEGIN - -API extend_axis_object_t create_extrude_axis(primitive_data_center_t* data_center, void* descriptor, axis_type type) noexcept(false) -{ - switch (type) { - case AXIS_TYPE_EXTRUDE_POLYLINE: { - const auto& desc = *reinterpret_cast(descriptor); - auto [obj, is_closed, mat] = construct_polyline_extrude_axis(desc); - auto ptr = data_center->require_axis(type, obj); - return {ptr, is_closed, convert_mat3x4d(mat)}; - } - case AXIS_TYPE_EXTRUDE_HELIXLINE: { - const auto& desc = *reinterpret_cast(descriptor); - auto [obj, is_closed, mat] = construct_helixline_extrude_axis(desc); - auto ptr = data_center->require_axis(type, obj); - return {ptr, is_closed, convert_mat3x4d(mat)}; - } - default: throw std::logic_error("invalid extrude axis type."); - } -} - -API void destroy_extrude_axis(primitive_data_center_t* data_center, axis_object_t axis_ptr, axis_type type) -{ - auto ptr = make_pointer_wrapper(reinterpret_cast(axis_ptr)); - data_center->release_axis(type, ptr); -} - +#include "io_primitive.h" + +#include + +auto construct_polyline_extrude_axis(const polyline_axis_descriptor_t& desc) +{ + bool is_ccw{}; + + const Eigen::Vector3d vert0 = convert_vec3d(desc.points[0]); + const Eigen::Vector3d vert1 = convert_vec3d(desc.points[1]); + Eigen::Vector3d vec_x = vert1 - vert0; + vec_x.normalize(); + Eigen::Vector3d vec_z = convert_vec3d(desc.reference_normal); + Eigen::Vector3d vec_y = vec_z.cross(vec_x); + + if (desc.point_number == 2) + is_ccw = true; + else { + const Eigen::Vector3d vert2 = convert_vec3d(desc.points[2]); + const auto& bulge0 = desc.bulges[0]; + const auto& bulge1 = desc.bulges[1]; + auto ccw_by_cross = (vert2 - vert1).dot(vec_y) > 0; + auto ccw_by_bulge = bulge0 < 0 && bulge1 < 0; + is_ccw = ccw_by_cross || ccw_by_bulge; + } + + std::vector vertices(desc.point_number); + std::vector bulges(desc.bulge_number); + // 偏移点坐标,并重新处理bulge为tan(theta/2) + if (is_ccw) { + std::transform(desc.points, desc.points + desc.point_number, vertices.begin(), [&](vector3d p) { + Eigen::Vector3d p_ = {p.x, p.y, p.z}; + p_ -= vert0; + return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; + }); + std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.begin(), [&](double bulge) { + return 2 * bulge / (1 - bulge * bulge); + }); + } else { + std::transform(desc.points, desc.points + desc.point_number, vertices.rbegin(), [&](vector3d p) { + Eigen::Vector3d p_ = {p.x, p.y, p.z}; + p_ -= vert0; + return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; + }); + std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.rbegin(), [&](double bulge) { + return 2 * bulge / (1 - bulge * bulge); + }); + } + + internal::polyline_extrude_axis obj{}; + obj.vertices = std::move(vertices); + obj.bulges = std::move(bulges); + + Eigen::AffineCompact3d axis_to_world{}; + axis_to_world.matrix().col(0) = vec_x; + axis_to_world.matrix().col(1) = vec_y; + axis_to_world.matrix().col(2) = vec_z; + axis_to_world.matrix().col(3) = vert0; + + return std::make_tuple(obj, desc.is_closed, axis_to_world); +} + +auto construct_helixline_extrude_axis(const helixline_axis_descriptor_t& desc) +{ + Eigen::Vector3d origin = convert_vec3d(desc.axis_start); + Eigen::Vector3d vec_z = convert_vec3d(desc.axis_end) - origin; + auto height = vec_z.norm(); + vec_z /= height; + auto total_theta = height / desc.advance_per_round * two_pi; + + internal::helixline_extrude_axis obj{}; + obj.scale_coeff_x = desc.radius; + obj.scale_coeff_y = desc.radius * height + * std::sqrt((total_theta * total_theta + 1) + / (desc.radius * desc.radius * total_theta * total_theta + height * height)); + obj.total_theta = total_theta; + + Eigen::AffineCompact3d axis_to_world = Eigen::AffineCompact3d::Identity(); + auto rot = Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d{0, 0, 1}, vec_z); + rot *= Eigen::Quaterniond::FromTwoVectors(rot * Eigen::Vector3d(1, 0, 0), convert_vec3d(desc.start_direction)); + if (!desc.is_righthanded) axis_to_world.matrix().col(1).y() = -1; + axis_to_world = rot * axis_to_world; + axis_to_world.matrix().col(2) *= height; + axis_to_world.translation() = origin; + + return std::make_tuple(obj, false, axis_to_world); +} + +EXTERN_C_BEGIN + +API extend_axis_object_t create_extrude_axis(primitive_data_center_t* data_center, void* descriptor, axis_type type) noexcept(false) +{ + switch (type) { + case AXIS_TYPE_EXTRUDE_POLYLINE: { + const auto& desc = *reinterpret_cast(descriptor); + auto [obj, is_closed, mat] = construct_polyline_extrude_axis(desc); + auto ptr = data_center->require_axis(type, obj); + return {ptr, is_closed, convert_mat3x4d(mat)}; + } + case AXIS_TYPE_EXTRUDE_HELIXLINE: { + const auto& desc = *reinterpret_cast(descriptor); + auto [obj, is_closed, mat] = construct_helixline_extrude_axis(desc); + auto ptr = data_center->require_axis(type, obj); + return {ptr, is_closed, convert_mat3x4d(mat)}; + } + default: throw std::logic_error("invalid extrude axis type."); + } +} + +API void destroy_extrude_axis(primitive_data_center_t* data_center, axis_object_t axis_ptr, axis_type type) +{ + auto ptr = make_pointer_wrapper(reinterpret_cast(axis_ptr)); + data_center->release_axis(type, ptr); +} + EXTERN_C_END \ No newline at end of file