1 changed files with 115 additions and 114 deletions
@ -1,115 +1,116 @@ |
|||||
#include "io_primitive.h" |
#include "io_primitive.h" |
||||
|
|
||||
#include <data/data_center.hpp> |
#include <data/data_center.hpp> |
||||
|
|
||||
auto construct_polyline_extrude_axis(const polyline_axis_descriptor_t& desc) |
auto construct_polyline_extrude_axis(const polyline_axis_descriptor_t& desc) |
||||
{ |
{ |
||||
bool is_ccw{}; |
bool is_ccw{}; |
||||
|
|
||||
const Eigen::Vector3d vert0 = convert_vec3d(desc.points[0]); |
const Eigen::Vector3d vert0 = convert_vec3d(desc.points[0]); |
||||
const Eigen::Vector3d vert1 = convert_vec3d(desc.points[1]); |
const Eigen::Vector3d vert1 = convert_vec3d(desc.points[1]); |
||||
Eigen::Vector3d vec_x = vert1 - vert0; |
Eigen::Vector3d vec_x = vert1 - vert0; |
||||
vec_x.normalize(); |
vec_x.normalize(); |
||||
Eigen::Vector3d vec_z = convert_vec3d(desc.reference_normal); |
Eigen::Vector3d vec_z = convert_vec3d(desc.reference_normal); |
||||
Eigen::Vector3d vec_y = vec_z.cross(vec_x); |
Eigen::Vector3d vec_y = vec_z.cross(vec_x); |
||||
|
|
||||
if (desc.point_number == 2) |
if (desc.point_number == 2) |
||||
is_ccw = true; |
is_ccw = true; |
||||
else { |
else { |
||||
const Eigen::Vector3d vert2 = convert_vec3d(desc.points[2]); |
const Eigen::Vector3d vert2 = convert_vec3d(desc.points[2]); |
||||
const auto& bulge0 = desc.bulges[0]; |
const auto& bulge0 = desc.bulges[0]; |
||||
const auto& bulge1 = desc.bulges[1]; |
const auto& bulge1 = desc.bulges[1]; |
||||
auto ccw_by_cross = (vert2 - vert1).dot(vec_y) > 0; |
auto ccw_by_cross = (vert2 - vert1).dot(vec_y) > 0; |
||||
auto ccw_by_bulge = bulge0 < 0 && bulge1 < 0; |
auto ccw_by_bulge = bulge0 < 0 && bulge1 < 0; |
||||
is_ccw = ccw_by_cross || ccw_by_bulge; |
is_ccw = ccw_by_cross || ccw_by_bulge; |
||||
} |
} |
||||
|
|
||||
std::vector<Eigen::Vector2d> vertices(desc.point_number); |
std::vector<Eigen::Vector2d> vertices(desc.point_number); |
||||
std::vector<double> bulges(desc.bulge_number); |
std::vector<double> bulges(desc.bulge_number); |
||||
// 偏移点坐标,并重新处理bulge为tan(theta/2)
|
// 偏移点坐标,并重新处理bulge为tan(theta/2)
|
||||
if (is_ccw) { |
if (is_ccw) { |
||||
std::transform(desc.points, desc.points + desc.point_number, vertices.begin(), [&](vector3d p) { |
std::transform(desc.points, desc.points + desc.point_number, vertices.begin(), [&](vector3d p) { |
||||
Eigen::Vector3d p_ = {p.x, p.y, p.z}; |
Eigen::Vector3d p_ = {p.x, p.y, p.z}; |
||||
p_ -= vert0; |
p_ -= vert0; |
||||
return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; |
return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; |
||||
}); |
}); |
||||
std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.begin(), [&](double bulge) { |
std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.begin(), [&](double bulge) { |
||||
return 2 * bulge / (1 - bulge * bulge); |
return 2 * bulge / (1 - bulge * bulge); |
||||
}); |
}); |
||||
} else { |
} else { |
||||
std::transform(desc.points, desc.points + desc.point_number, vertices.rbegin(), [&](vector3d p) { |
std::transform(desc.points, desc.points + desc.point_number, vertices.rbegin(), [&](vector3d p) { |
||||
Eigen::Vector3d p_ = {p.x, p.y, p.z}; |
Eigen::Vector3d p_ = {p.x, p.y, p.z}; |
||||
p_ -= vert0; |
p_ -= vert0; |
||||
return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; |
return Eigen::Vector2d{p_.dot(vec_x), p_.dot(vec_y)}; |
||||
}); |
}); |
||||
std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.rbegin(), [&](double bulge) { |
std::transform(desc.bulges, desc.bulges + desc.bulge_number, bulges.rbegin(), [&](double bulge) { |
||||
return 2 * bulge / (1 - bulge * bulge); |
return 2 * bulge / (1 - bulge * bulge); |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
internal::polyline_extrude_axis obj{}; |
internal::polyline_extrude_axis obj{}; |
||||
obj.vertices = std::move(vertices); |
obj.vertices = std::move(vertices); |
||||
obj.bulges = std::move(bulges); |
obj.bulges = std::move(bulges); |
||||
|
|
||||
Eigen::AffineCompact3d axis_to_world{}; |
Eigen::AffineCompact3d axis_to_world{}; |
||||
axis_to_world.matrix().col(0) = vec_x; |
axis_to_world.matrix().col(0) = vec_x; |
||||
axis_to_world.matrix().col(1) = vec_y; |
axis_to_world.matrix().col(1) = vec_y; |
||||
axis_to_world.matrix().col(2) = vec_z; |
axis_to_world.matrix().col(2) = vec_z; |
||||
axis_to_world.matrix().col(3) = vert0; |
axis_to_world.matrix().col(3) = vert0; |
||||
|
|
||||
return std::make_tuple(obj, desc.is_closed, axis_to_world); |
return std::make_tuple(obj, desc.is_closed, axis_to_world); |
||||
} |
} |
||||
|
|
||||
auto construct_helixline_extrude_axis(const helixline_axis_descriptor_t& desc) |
auto construct_helixline_extrude_axis(const helixline_axis_descriptor_t& desc) |
||||
{ |
{ |
||||
Eigen::Vector3d origin = convert_vec3d(desc.axis_start); |
Eigen::Vector3d origin = convert_vec3d(desc.axis_start); |
||||
Eigen::Vector3d vec_z = convert_vec3d(desc.axis_end) - origin; |
Eigen::Vector3d vec_z = convert_vec3d(desc.axis_end) - origin; |
||||
auto height = vec_z.norm(); |
auto height = vec_z.norm(); |
||||
vec_z /= height; |
vec_z /= height; |
||||
auto total_theta = height / desc.advance_per_round * two_pi; |
auto total_theta = height / desc.advance_per_round * two_pi; |
||||
|
|
||||
internal::helixline_extrude_axis obj{}; |
internal::helixline_extrude_axis obj{}; |
||||
obj.scale_coeff_x = desc.radius; |
obj.scale_coeff_x = desc.radius; |
||||
obj.scale_coeff_y = desc.radius * height |
obj.scale_coeff_y = desc.radius * height |
||||
* std::sqrt((total_theta * total_theta + 1) |
* std::sqrt((total_theta * total_theta + 1) |
||||
/ (desc.radius * desc.radius * total_theta * total_theta + height * height)); |
/ (desc.radius * desc.radius * total_theta * total_theta + height * height)); |
||||
obj.total_theta = total_theta; |
obj.total_theta = total_theta; |
||||
|
|
||||
Eigen::AffineCompact3d axis_to_world = Eigen::AffineCompact3d::Identity(); |
Eigen::AffineCompact3d axis_to_world = Eigen::AffineCompact3d::Identity(); |
||||
auto rot = Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d{0, 0, 1}, vec_z); |
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)); |
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; |
if (!desc.is_righthanded) axis_to_world.matrix().col(1).y() = -1; |
||||
axis_to_world = rot * axis_to_world; |
axis_to_world = rot * axis_to_world; |
||||
axis_to_world.translation() = origin; |
axis_to_world.matrix().col(2) *= height; |
||||
|
axis_to_world.translation() = origin; |
||||
return std::make_tuple(obj, false, axis_to_world); |
|
||||
} |
return std::make_tuple(obj, false, axis_to_world); |
||||
|
} |
||||
EXTERN_C_BEGIN |
|
||||
|
EXTERN_C_BEGIN |
||||
API extend_axis_object_t create_extrude_axis(primitive_data_center_t* data_center, void* descriptor, axis_type type) noexcept(false) |
|
||||
{ |
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: { |
switch (type) { |
||||
const auto& desc = *reinterpret_cast<polyline_axis_descriptor_t*>(descriptor); |
case AXIS_TYPE_EXTRUDE_POLYLINE: { |
||||
auto [obj, is_closed, mat] = construct_polyline_extrude_axis(desc); |
const auto& desc = *reinterpret_cast<polyline_axis_descriptor_t*>(descriptor); |
||||
auto ptr = data_center->require_axis(type, obj); |
auto [obj, is_closed, mat] = construct_polyline_extrude_axis(desc); |
||||
return {ptr, is_closed, convert_mat3x4d(mat)}; |
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); |
case AXIS_TYPE_EXTRUDE_HELIXLINE: { |
||||
auto [obj, is_closed, mat] = construct_helixline_extrude_axis(desc); |
const auto& desc = *reinterpret_cast<helixline_axis_descriptor_t*>(descriptor); |
||||
auto ptr = data_center->require_axis(type, obj); |
auto [obj, is_closed, mat] = construct_helixline_extrude_axis(desc); |
||||
return {ptr, is_closed, convert_mat3x4d(mat)}; |
auto ptr = data_center->require_axis(type, obj); |
||||
} |
return {ptr, is_closed, convert_mat3x4d(mat)}; |
||||
default: throw std::logic_error("invalid extrude axis type."); |
} |
||||
} |
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) |
|
||||
{ |
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); |
auto ptr = make_pointer_wrapper(reinterpret_cast<internal::extrude_axis*>(axis_ptr)); |
||||
} |
data_center->release_axis(type, ptr); |
||||
|
} |
||||
|
|
||||
EXTERN_C_END |
EXTERN_C_END |
||||
Loading…
Reference in new issue