|
|
@ -2,6 +2,7 @@ |
|
|
|
|
|
|
|
#include <algorithm/glue_algorithm.hpp> |
|
|
|
|
|
|
|
#include "Eigen/Core" |
|
|
|
#include "internal_primitive_desc.hpp" |
|
|
|
|
|
|
|
static inline auto manually_projection(const raw_vector3d_t &point, |
|
|
@ -30,18 +31,20 @@ namespace internal |
|
|
|
void polyline::build_as_axis(const polyline_descriptor_t &desc, |
|
|
|
const raw_vector3d_t &profile_ref_normal, |
|
|
|
Eigen::Transform<double, 3, Eigen::AffineCompact, Eigen::DontAlign> &axis_to_world, |
|
|
|
aabb_t<> &aabb) |
|
|
|
aabb_t<> &aabb, |
|
|
|
const raw_vector3d_t &anchor_point) |
|
|
|
{ |
|
|
|
auto &matrix_handle = axis_to_world.matrix(); |
|
|
|
vec3d_conversion(desc.reference_normal, matrix_handle.col(1)); |
|
|
|
matrix_handle.col(1).normalize(); |
|
|
|
vec3d_conversion(profile_ref_normal, matrix_handle.col(2)); |
|
|
|
vec3d_conversion(profile_ref_normal, matrix_handle.col(0)); |
|
|
|
matrix_handle.col(0).normalize(); |
|
|
|
vec3d_conversion(desc.reference_normal, matrix_handle.col(2)); |
|
|
|
matrix_handle.col(2).normalize(); |
|
|
|
matrix_handle.col(0) = matrix_handle.col(1).cross(matrix_handle.col(2)); |
|
|
|
vec3d_conversion(desc.points[0], matrix_handle.col(3)); |
|
|
|
matrix_handle.col(1) = matrix_handle.col(2).cross(matrix_handle.col(0)); |
|
|
|
// vec3d_conversion(desc.points[0], matrix_handle.col(3));
|
|
|
|
vec3d_conversion(anchor_point, matrix_handle.col(3)); |
|
|
|
|
|
|
|
aabb_t<2> profile_aabb; |
|
|
|
build_as_profile(desc, matrix_handle.col(2), matrix_handle.col(0), matrix_handle.col(3), profile_aabb); |
|
|
|
build_as_profile(desc, matrix_handle.col(0), matrix_handle.col(1), matrix_handle.col(3), profile_aabb); |
|
|
|
const auto &profile_aabb_min = profile_aabb.min(); |
|
|
|
const auto &profile_aabb_max = profile_aabb.max(); |
|
|
|
aabb = { |
|
|
@ -54,18 +57,20 @@ void polyline::build_as_axis(const polyline_descriptor_t |
|
|
|
void polyline::build_as_axis(polyline_descriptor_t &&desc, |
|
|
|
const raw_vector3d_t &profile_ref_normal, |
|
|
|
Eigen::Transform<double, 3, Eigen::AffineCompact, Eigen::DontAlign> &axis_to_world, |
|
|
|
aabb_t<> &aabb) |
|
|
|
aabb_t<> &aabb, |
|
|
|
const raw_vector3d_t &anchor_point) |
|
|
|
{ |
|
|
|
auto &matrix_handle = axis_to_world.matrix(); |
|
|
|
vec3d_conversion(std::move(desc.reference_normal), matrix_handle.col(1)); |
|
|
|
matrix_handle.col(1).normalize(); |
|
|
|
vec3d_conversion(profile_ref_normal, matrix_handle.col(2)); |
|
|
|
vec3d_conversion(profile_ref_normal, matrix_handle.col(0)); |
|
|
|
matrix_handle.col(0).normalize(); |
|
|
|
vec3d_conversion(std::move(desc.reference_normal), matrix_handle.col(2)); |
|
|
|
matrix_handle.col(2).normalize(); |
|
|
|
matrix_handle.col(0) = matrix_handle.col(1).cross(matrix_handle.col(2)); |
|
|
|
vec3d_conversion(desc.points[0], matrix_handle.col(3)); |
|
|
|
matrix_handle.col(1) = matrix_handle.col(2).cross(matrix_handle.col(0)); |
|
|
|
// vec3d_conversion(desc.points[0], matrix_handle.col(3));
|
|
|
|
vec3d_conversion(anchor_point, matrix_handle.col(3)); |
|
|
|
|
|
|
|
aabb_t<2> profile_aabb; |
|
|
|
build_as_profile(std::move(desc), matrix_handle.col(2), matrix_handle.col(0), matrix_handle.col(3), profile_aabb); |
|
|
|
build_as_profile(std::move(desc), matrix_handle.col(0), matrix_handle.col(1), matrix_handle.col(3), profile_aabb); |
|
|
|
const auto &profile_aabb_min = profile_aabb.min(); |
|
|
|
const auto &profile_aabb_max = profile_aabb.max(); |
|
|
|
aabb = { |
|
|
@ -105,6 +110,10 @@ void polyline::build_as_profile(const polyline_descriptor_t &desc, |
|
|
|
} |
|
|
|
}); |
|
|
|
// i.e. iff close curve, deduce loop to simple segements by copying the first vertex to the end
|
|
|
|
Eigen::Vector3d proj_x_dir_tmp = proj_x_dir; |
|
|
|
Eigen::Vector3d proj_y_dir_tmp = proj_y_dir; |
|
|
|
Eigen::Vector3d proj_origin_tmp = proj_origin; // for debug
|
|
|
|
|
|
|
|
this->vertices.resize(this->start_indices.back() + 1); |
|
|
|
this->start_indices.pop_back(); |
|
|
|
circle_start_indices.shrink_to_fit(); |
|
|
@ -136,26 +145,27 @@ void polyline::build_as_profile(const polyline_descriptor_t &desc, |
|
|
|
const auto &bulge = desc.bulges[index]; |
|
|
|
const auto &theta = this->thetas[index]; |
|
|
|
|
|
|
|
const auto &a = this->vertices[start_index]; |
|
|
|
const auto &b = this->vertices[start_index + 3]; |
|
|
|
auto &c = this->vertices[start_index + 1]; |
|
|
|
auto &d = this->vertices[start_index + 2]; |
|
|
|
const auto half_vec_ab = 0.5 * (a + b); |
|
|
|
const auto &a = this->vertices[start_index]; |
|
|
|
const auto &b = this->vertices[start_index + 3]; |
|
|
|
auto &c = this->vertices[start_index + 1]; |
|
|
|
auto &d = this->vertices[start_index + 2]; |
|
|
|
const auto center_vec_ab = 0.5 * (a + b); |
|
|
|
const auto half_vec_ab = b - center_vec_ab; |
|
|
|
Eigen::Matrix<double, 2, 1> temp = center_vec_ab; // for debug
|
|
|
|
if (theta == PI) { |
|
|
|
c = std::move(half_vec_ab); |
|
|
|
c = std::move(center_vec_ab); |
|
|
|
} else { |
|
|
|
// NOTE: bulge = tan(theta/4), so we can directly calculate tan(theta/2)
|
|
|
|
// and no more operations are needed for identifying the circle center
|
|
|
|
// since all direction info is already included in the sign & magnitude of bulge
|
|
|
|
const auto inv_tan_half_theta = (1 - bulge * bulge) / (2 * bulge); |
|
|
|
c = half_vec_ab + inv_tan_half_theta * Eigen::Vector2d{half_vec_ab[1], -half_vec_ab[0]}; |
|
|
|
c = center_vec_ab + inv_tan_half_theta * Eigen::Vector2d{half_vec_ab[1], -half_vec_ab[0]}; |
|
|
|
} |
|
|
|
const auto vec_ca = a - c; |
|
|
|
if (bulge > 0) |
|
|
|
d = c + Eigen::Vector2d{vec_ca[1], -vec_ca[0]}; |
|
|
|
else |
|
|
|
d = c + Eigen::Vector2d{-vec_ca[1], vec_ca[0]}; |
|
|
|
|
|
|
|
aabb.extend(c); |
|
|
|
aabb.extend(d); |
|
|
|
}); |
|
|
@ -222,19 +232,21 @@ void polyline::build_as_profile(polyline_descriptor_t &&desc, |
|
|
|
const auto &bulge = desc.bulges[index]; |
|
|
|
const auto &theta = this->thetas[index]; |
|
|
|
|
|
|
|
const auto &a = this->vertices[start_index]; |
|
|
|
const auto &b = this->vertices[start_index + 3]; |
|
|
|
auto &c = this->vertices[start_index + 1]; |
|
|
|
auto &d = this->vertices[start_index + 2]; |
|
|
|
const auto half_vec_ab = 0.5 * (a + b); |
|
|
|
const auto &a = this->vertices[start_index]; |
|
|
|
const auto &b = this->vertices[start_index + 3]; |
|
|
|
auto &c = this->vertices[start_index + 1]; |
|
|
|
auto &d = this->vertices[start_index + 2]; |
|
|
|
const auto center_vec_ab = 0.5 * (a + b); |
|
|
|
const auto half_vec_ab = b - center_vec_ab; |
|
|
|
Eigen::Matrix<double, 2, 1> temp = center_vec_ab; // for debug
|
|
|
|
if (theta == PI) { |
|
|
|
c = std::move(half_vec_ab); |
|
|
|
c = std::move(center_vec_ab); |
|
|
|
} else { |
|
|
|
// NOTE: bulge = tan(theta/4), so we can directly calculate tan(theta/2)
|
|
|
|
// and no more operations are needed for identifying the circle center
|
|
|
|
// since all direction info is already included in the sign & magnitude of bulge
|
|
|
|
const auto inv_tan_half_theta = (1 - bulge * bulge) / (2 * bulge); |
|
|
|
c = half_vec_ab + inv_tan_half_theta * Eigen::Vector2d{half_vec_ab[1], -half_vec_ab[0]}; |
|
|
|
c = center_vec_ab + inv_tan_half_theta * Eigen::Vector2d{half_vec_ab[1], -half_vec_ab[0]}; |
|
|
|
} |
|
|
|
const auto vec_ca = a - c; |
|
|
|
if (bulge > 0) |
|
|
@ -274,11 +286,11 @@ void polyline::build_as_profile(polyline_descriptor_t &&desc, |
|
|
|
if (this->thetas[n] <= EPSILON) { |
|
|
|
// HINT: assume the plane normal (ref_normal) to be {0, 0, 1}, then the normal should be this
|
|
|
|
const auto temp = (*(iter + 1) - *iter).normalized(); |
|
|
|
return {temp.y(), -temp.x()}; |
|
|
|
return Eigen::Vector2d{-temp.y(), temp.x()}.normalized(); |
|
|
|
} else { |
|
|
|
const auto alpha = std::cos(t * this->thetas[n]); |
|
|
|
const auto beta = std::sin(t * this->thetas[n]); |
|
|
|
return (alpha + beta) * *(iter + 1) - alpha * *iter - beta * *(iter + 2); |
|
|
|
return ((alpha + beta) * *(iter + 1) - alpha * *iter - beta * *(iter + 2)).normalized(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -329,7 +341,8 @@ void polyline::build_as_profile(polyline_descriptor_t &&desc, |
|
|
|
const auto p_vec_norm = p_vec.norm(); |
|
|
|
const auto r = base_vec1.norm(); |
|
|
|
const auto dis_on_plane = p_vec_norm - r; |
|
|
|
const auto closest_point = p_vec / p_vec_norm * r + *(iter + 1); |
|
|
|
auto closest_point = *iter; |
|
|
|
if (p_vec_norm >= EPSILON) { closest_point = p_vec / p_vec_norm * r + *(iter + 1); } |
|
|
|
return { |
|
|
|
{closest_point.x(), closest_point.y(), 0}, |
|
|
|
phi / theta, |
|
|
@ -338,6 +351,7 @@ void polyline::build_as_profile(polyline_descriptor_t &&desc, |
|
|
|
}; |
|
|
|
|
|
|
|
std::vector<comparable_closest_param_t> closest_params(this->thetas.size()); |
|
|
|
const Eigen::Vector3d pTmp = p; // for debugging
|
|
|
|
algorithm::transform(counting_iterator<size_t>(), |
|
|
|
counting_iterator<size_t>(this->thetas.size()), |
|
|
|
closest_params.begin(), |
|
|
@ -368,10 +382,18 @@ void polyline::build_as_profile(polyline_descriptor_t &&desc, |
|
|
|
dist |
|
|
|
}; |
|
|
|
}); |
|
|
|
const auto back = this->vertices.back(); |
|
|
|
if (*vertices.begin() != back) { |
|
|
|
closest_params.emplace_back(comparable_closest_param_t{ |
|
|
|
{back.x(), back.y(), 0}, |
|
|
|
static_cast<double>(thetas.size()), |
|
|
|
std::sqrt((p.topRows<2>() - back).squaredNorm() + p[2] * p[2]) |
|
|
|
}); |
|
|
|
} |
|
|
|
const auto iter_ = algorithm::min_element(closest_params.begin(), closest_params.end()); |
|
|
|
return { |
|
|
|
line_closest_param_t{std::move(iter->point), iter->t, false}, |
|
|
|
iter->dist * iter->dist_sign |
|
|
|
line_closest_param_t{std::move(iter_->point), iter_->t, false}, |
|
|
|
iter_->dist * iter_->dist_sign |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|