1 changed files with 115 additions and 114 deletions
@ -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…
Reference in new issue