Browse Source

take height into axis_to_world of helixline

V2-integral
Zhicheng Wang 5 days ago
parent
commit
037922a878
  1. 229
      frontend/src/io_axis.cpp

229
frontend/src/io_axis.cpp

@ -1,115 +1,116 @@
#include "io_primitive.h"
#include <data/data_center.hpp>
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<Eigen::Vector2d> vertices(desc.point_number);
std::vector<double> 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<polyline_axis_descriptor_t*>(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<helixline_axis_descriptor_t*>(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<internal::extrude_axis*>(axis_ptr));
data_center->release_axis(type, ptr);
}
#include "io_primitive.h"
#include <data/data_center.hpp>
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<Eigen::Vector2d> vertices(desc.point_number);
std::vector<double> 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<polyline_axis_descriptor_t*>(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<helixline_axis_descriptor_t*>(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<internal::extrude_axis*>(axis_ptr));
data_center->release_axis(type, ptr);
}
EXTERN_C_END
Loading…
Cancel
Save