|
|
@ -1,4 +1,4 @@ |
|
|
#include "SurfaceIntegrator.hpp" |
|
|
#include "subface_integrator.hpp" |
|
|
#include "quadrature.hpp" |
|
|
#include "quadrature.hpp" |
|
|
#include <Eigen/Geometry> // For vector and cross product operations |
|
|
#include <Eigen/Geometry> // For vector and cross product operations |
|
|
#include <cmath> // For math functions like sqrt |
|
|
#include <cmath> // For math functions like sqrt |
|
|
@ -8,27 +8,30 @@ |
|
|
namespace internal |
|
|
namespace internal |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
// Main entry point to compute surface area
|
|
|
double integrator_t::calculate(int gauss_order, double (*func)(double u, double v, |
|
|
// Main entry point to compute surface area
|
|
|
const Eigen::Vector3d& p, |
|
|
template <typename Func> |
|
|
const Eigen::Vector3d& dU, |
|
|
double integrator_t::calculate(int gauss_order, Func&& func) const |
|
|
const Eigen::Vector3d& dV)) const |
|
|
{ |
|
|
{ |
|
|
total_integral = 0.0; |
|
|
double total_integral = 0.0; |
|
|
for (const auto& [subface_index, param_plane] : m_uv_planes) { |
|
|
for (const auto& [subface_index, param_plane] : m_uv_planes) { |
|
|
const auto& subface = m_subfaces[subface_index].object_ptr.get(); |
|
|
const auto& subface = m_subfaces[subface_index].object_ptr.get(); |
|
|
total_integral += calculate_one_subface(subface, param_plane, gauss_order, std::forward<Func>(func)); |
|
|
total_integral += calculate_one_subface(subface, param_plane, gauss_order, func); |
|
|
} |
|
|
} |
|
|
return total_integral; |
|
|
return total_integral; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Func> |
|
|
|
|
|
double integrator_t::calculate_one_subface(const subface& subface, const parametric_plane_t& param_plane, int gauss_order, Func&& func) const |
|
|
double integrator_t::calculate_one_subface(const subface& subface, const parametric_plane_t& param_plane, int gauss_order, double (*func)(double u, double v, |
|
|
|
|
|
const Eigen::Vector3d& p, |
|
|
|
|
|
const Eigen::Vector3d& dU, |
|
|
|
|
|
const Eigen::Vector3d& dV)) const |
|
|
{ |
|
|
{ |
|
|
auto solver = subface.fetch_solver_evaluator(); |
|
|
auto solver = subface.fetch_solver_evaluator(); |
|
|
// Gaussian integration in u direction
|
|
|
// Gaussian integration in u direction
|
|
|
auto u_integrand = [&](double u) { |
|
|
auto u_integrand = [&](double u) { |
|
|
// Find exact v intersections for each u
|
|
|
// Find exact v intersections for each u
|
|
|
std::vector<double> v_breaks = find_vertical_intersections(u); |
|
|
stl_vector_mp<double> v_breaks = find_v_intersections_at_u(subface, param_plane, u);; |
|
|
|
|
|
|
|
|
// Gaussian integration in v direction
|
|
|
// Gaussian integration in v direction
|
|
|
auto v_integrand = [&](double v) { |
|
|
auto v_integrand = [&](double v) { |
|
|
@ -75,14 +78,14 @@ double integrator_t::calculate_one_subface(const subface& subface, const paramet |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// Integrate in u direction
|
|
|
// Integrate in u direction
|
|
|
const auto& u_breaks = compute_u_breaks(param_plane); |
|
|
const auto& u_breaks = compute_u_breaks(param_plane,0.0, 1.0); |
|
|
double integral = 0.0; |
|
|
double integral = 0.0; |
|
|
for (size_t i = 0; i < u_breaks.size() - 1; ++i) { |
|
|
for (size_t i = 0; i < u_breaks.size() - 1; ++i) { |
|
|
double a = u_breaks[i]; |
|
|
double a = u_breaks[i]; |
|
|
double b = u_breaks[i + 1]; |
|
|
double b = u_breaks[i + 1]; |
|
|
|
|
|
|
|
|
double mid_u = (a + b) / 2.0; |
|
|
double mid_u = (a + b) / 2.0; |
|
|
auto v_intersections = find_vertical_intersections(mid_u, self.outerEdges, self.Vmin, self.Vmax); |
|
|
auto v_intersections = find_v_intersections_at_u(subface, param_plane,mid_u); |
|
|
|
|
|
|
|
|
if (!v_intersections.empty()) { |
|
|
if (!v_intersections.empty()) { |
|
|
integral += integrate_1D(a, b, u_integrand, gauss_order, is_u_near_singularity(mid_u)); |
|
|
integral += integrate_1D(a, b, u_integrand, gauss_order, is_u_near_singularity(mid_u)); |
|
|
@ -92,72 +95,6 @@ double integrator_t::calculate_one_subface(const subface& subface, const paramet |
|
|
return integral; |
|
|
return integral; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 在 integrator_t 类中添加:
|
|
|
|
|
|
/*
|
|
|
|
|
|
double integrator_t::compute_volume(int gauss_order) const |
|
|
|
|
|
{ |
|
|
|
|
|
double total_volume = 0.0; |
|
|
|
|
|
|
|
|
|
|
|
// 外层:对 u 分段积分
|
|
|
|
|
|
auto u_integrand = [&](double u) { |
|
|
|
|
|
std::vector<double> v_breaks = find_vertical_intersections(u); |
|
|
|
|
|
double v_integral = 0.0; |
|
|
|
|
|
|
|
|
|
|
|
// 内层:对 v 积分
|
|
|
|
|
|
auto v_integrand = [&](double v) -> double { |
|
|
|
|
|
if (!is_point_inside_domain(subface, u, v)) { |
|
|
|
|
|
return 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// 获取偏导数
|
|
|
|
|
|
auto eval_du = m_surface.fetch_curve_constraint_evaluator(parameter_v_t{}, v); // ∂/∂u
|
|
|
|
|
|
auto eval_dv = m_surface.fetch_curve_constraint_evaluator(parameter_u_t{}, u); // ∂/∂v
|
|
|
|
|
|
|
|
|
|
|
|
auto res_u = eval_du(u); |
|
|
|
|
|
auto res_v = eval_dv(v); |
|
|
|
|
|
|
|
|
|
|
|
Eigen::Vector3d p = res_u.f.template head<3>(); // r(u,v)
|
|
|
|
|
|
Eigen::Vector3d dU = res_u.grad_f.template head<3>(); // r_u
|
|
|
|
|
|
Eigen::Vector3d dV = res_v.grad_f.template head<3>(); // r_v
|
|
|
|
|
|
|
|
|
|
|
|
// 计算 r · (r_u × r_v)
|
|
|
|
|
|
Eigen::Vector3d cross = dU.cross(dV); |
|
|
|
|
|
double mixed_product = p.dot(cross); |
|
|
|
|
|
|
|
|
|
|
|
return mixed_product; // 注意:不是 norm,是点积
|
|
|
|
|
|
} catch (...) { |
|
|
|
|
|
return 0.0; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < v_breaks.size() - 1; ++i) { |
|
|
|
|
|
double a = v_breaks[i]; |
|
|
|
|
|
double b = v_breaks[i + 1]; |
|
|
|
|
|
double mid_v = (a + b) / 2.0; |
|
|
|
|
|
if (is_point_inside_domain(subface, u, mid_v)) { |
|
|
|
|
|
v_integral += integrate_1D(a, b, v_integrand, gauss_order); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return v_integral; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 在 u 方向积分
|
|
|
|
|
|
for (size_t i = 0; i < m_u_breaks.size() - 1; ++i) { |
|
|
|
|
|
double a = m_u_breaks[i]; |
|
|
|
|
|
double b = m_u_breaks[i + 1]; |
|
|
|
|
|
double mid_u = (a + b) / 2.0; |
|
|
|
|
|
auto v_intersections = find_vertical_intersections(mid_u); |
|
|
|
|
|
if (!v_intersections.empty()) { |
|
|
|
|
|
total_volume += integrate_1D(a, b, u_integrand, gauss_order, is_u_near_singularity(mid_u)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 乘以 1/3
|
|
|
|
|
|
return std::abs(total_volume) / 3.0; |
|
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
|
* @brief Compute the u-parameter breakpoints for integration. |
|
|
* @brief Compute the u-parameter breakpoints for integration. |
|
|
* @note The function currently uses std::set for uniqueness and sorting, |
|
|
* @note The function currently uses std::set for uniqueness and sorting, |
|
|
@ -166,10 +103,10 @@ double integrator_t::compute_volume(int gauss_order) const |
|
|
* TODO: Use a tolerance-based approach to avoid floating-point precision issues |
|
|
* TODO: Use a tolerance-based approach to avoid floating-point precision issues |
|
|
* when inserting u-values (e.g., merge values within 1e-12). |
|
|
* when inserting u-values (e.g., merge values within 1e-12). |
|
|
*/ |
|
|
*/ |
|
|
stl_vector_mp<double> compute_u_breaks( |
|
|
stl_vector_mp<double> integrator_t::compute_u_breaks( |
|
|
const parametric_plane_t& param_plane, |
|
|
const parametric_plane_t& param_plane, |
|
|
double u_min, |
|
|
double u_min, |
|
|
double u_max) |
|
|
double u_max) const |
|
|
{ |
|
|
{ |
|
|
std::set<double> break_set; |
|
|
std::set<double> break_set; |
|
|
|
|
|
|