Browse Source

fix(integrator): fix small bug in integrator

feat-integrator
mckay 2 weeks ago
parent
commit
97320c95c7
  1. 27
      surface_integral/interface/subface_integrator.hpp
  2. 57
      surface_integral/src/subface_integrator.cpp

27
surface_integral/interface/subface_integrator.hpp

@ -40,9 +40,10 @@ public:
const Eigen::Vector3d& dV)) const; const Eigen::Vector3d& dV)) const;
double calculate_one_subface(const subface& subface, double calculate_one_subface(const subface& subface,
const parametric_plane_t& param_plane, const parametric_plane_t& param_plane,
int gauss_order, const stl_vector_mp<Eigen::AlignedBox2d>& chain_bboxes,
int gauss_order,
double (*func)(double u, double (*func)(double u,
double v, double v,
const Eigen::Vector3d& p, const Eigen::Vector3d& p,
@ -61,15 +62,19 @@ private:
stl_vector_mp<double> compute_u_breaks(const parametric_plane_t& param_plane, double u_min, double u_max) const; stl_vector_mp<double> compute_u_breaks(const parametric_plane_t& param_plane, double u_min, double u_max) const;
void find_v_intersections_at_u(const subface& subface, void find_v_intersections_at_u(const subface& subface,
const parametric_plane_t& param_plane, const parametric_plane_t& param_plane,
double u_val, const stl_vector_mp<Eigen::AlignedBox2d>& chain_bboxes,
double v_min, double u_val,
double v_max, double v_min,
stl_vector_mp<double>& intersections, double v_max,
stl_vector_mp<uint16_t>& intersected_chains) const; stl_vector_mp<double>& intersections,
stl_vector_mp<uint16_t>& intersected_chains) const;
bool is_point_inside_domain(const subface& subface, const parametric_plane_t& param_plane, double u, double v) const;
bool is_edge_inside_domain(const stl_vector_mp<stl_vector_mp<uint16_t>>& chain_group_indices,
uint16_t chain_idx1,
uint16_t chain_idx2) const;
bool is_u_near_singularity(double u, double tol = 1e-6) const; bool is_u_near_singularity(double u, double tol = 1e-6) const;

57
surface_integral/src/subface_integrator.cpp

@ -4,12 +4,13 @@
#include <cmath> // For math functions like sqrt #include <cmath> // For math functions like sqrt
#include <set> #include <set>
#include <iostream> #include <iostream>
#include <algorithm>
namespace internal namespace internal
{ {
integrator_t(const stl_vector_mp<object_with_index_mapping<subface>>& surfaces, integrator_t::integrator_t(const stl_vector_mp<object_with_index_mapping<subface>>& surfaces,
const flat_hash_map_mp<uint32_t, parametric_plane_t>& uv_planes) const flat_hash_map_mp<uint32_t, parametric_plane_t>& uv_planes)
: m_subfaces(surfaces), m_uv_planes(uv_planes) : m_subfaces(surfaces), m_uv_planes(uv_planes)
{ {
std::cout << "Integrator initialized with " << surfaces.size() << " subfaces." << std::endl; std::cout << "Integrator initialized with " << surfaces.size() << " subfaces." << std::endl;
@ -18,10 +19,10 @@ integrator_t(const stl_vector_mp<object_with_index_mapping<subface>>& surfaces,
// calculate chain bbox // calculate chain bbox
for (int subface_index = 0; subface_index < m_subfaces.size(); ++subface_index) { for (int subface_index = 0; subface_index < m_subfaces.size(); ++subface_index) {
if (m_uv_planes.find(subface_index) != m_uv_planes.end()) { if (m_uv_planes.find(subface_index) != m_uv_planes.end()) {
const auto& param_plane = m_uv_planes.at(subface_index); const auto& param_plane = m_uv_planes.at(subface_index);
auto& chain_bboxs = m_chain_bboxes_hash[subface_index]; auto& chain_bboxes = m_chain_bboxes_hash[subface_index];
chain_bboxes.clear(); chain_bboxes.clear();
chain_bboxs.reverse(chain_vertices.size()); chain_bboxes.reserve(param_plane.chain_vertices.size());
for (const auto& chain : param_plane.chain_vertices) { for (const auto& chain : param_plane.chain_vertices) {
Eigen::AlignedBox2d bbox; Eigen::AlignedBox2d bbox;
bbox.setEmpty(); bbox.setEmpty();
@ -33,8 +34,6 @@ integrator_t(const stl_vector_mp<object_with_index_mapping<subface>>& surfaces,
} }
} }
} }
m_chain_bboxes_hash
} }
double integrator_t::calculate( double integrator_t::calculate(
@ -44,9 +43,10 @@ double integrator_t::calculate(
double total_integral = 0.0; double total_integral = 0.0;
for (int subface_index = 0; subface_index < m_subfaces.size(); ++subface_index) { for (int subface_index = 0; subface_index < m_subfaces.size(); ++subface_index) {
if (m_uv_planes.find(subface_index) != m_uv_planes.end()) { if (m_uv_planes.find(subface_index) != m_uv_planes.end()) {
const auto& param_plane = m_uv_planes.at(subface_index); const auto& param_plane = m_uv_planes.at(subface_index);
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, func); const auto& chain_bboxes = m_chain_bboxes_hash.at(subface_index);
total_integral += calculate_one_subface(subface, param_plane, chain_bboxes, gauss_order, func);
} else { } else {
// the subface has no associated parametric plane, meaning it is compete face without trimming // the subface has no associated parametric plane, meaning it is compete face without trimming
} }
@ -55,9 +55,10 @@ double integrator_t::calculate(
} }
double integrator_t::calculate_one_subface( double integrator_t::calculate_one_subface(
const subface& subface, const subface& subface,
const parametric_plane_t& param_plane, const parametric_plane_t& param_plane,
int gauss_order, const stl_vector_mp<Eigen::AlignedBox2d>& chain_bboxes,
int gauss_order,
double (*func)(double u, double v, const Eigen::Vector3d& p, const Eigen::Vector3d& dU, const Eigen::Vector3d& dV)) const 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();
@ -69,9 +70,9 @@ double integrator_t::calculate_one_subface(
// 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
stl_vector_mp<double> v_intersections; stl_vector_mp<double> v_breaks;
stl_vector_mp<uint16_t> intersected_chains; stl_vector_mp<uint16_t> intersected_chains;
find_v_intersections_at_u(subface, param_plane, u, v_min, v_max, v_intersections, intersected_chains); find_v_intersections_at_u(subface, param_plane, chain_bboxes, u, v_min, v_max, v_breaks, intersected_chains);
// Gaussian integration in v direction // Gaussian integration in v direction
auto v_integrand = [&](double v) { auto v_integrand = [&](double v) {
@ -104,7 +105,7 @@ double integrator_t::calculate_one_subface(
// Check midpoint validity // Check midpoint validity
double mid_v = (a + b) / 2.0; double mid_v = (a + b) / 2.0;
if (is_edge_inside_domain(subface, param_plane, u, mid_v)) { if (is_edge_inside_domain(param_plane.chain_group_indices, intersected_chains[i], intersected_chains[i + 1])) {
v_integral += integrate_1D(a, b, v_integrand, gauss_order); v_integral += integrate_1D(a, b, v_integrand, gauss_order);
} else { } else {
std::cout << "uv out of domain: (" << u << "," << mid_v << ")" << std::endl; std::cout << "uv out of domain: (" << u << "," << mid_v << ")" << std::endl;
@ -124,7 +125,7 @@ double integrator_t::calculate_one_subface(
double mid_u = (a + b) / 2.0; double mid_u = (a + b) / 2.0;
stl_vector_mp<double> v_intersections; stl_vector_mp<double> v_intersections;
stl_vector_mp<uint16_t> intersected_chains; stl_vector_mp<uint16_t> intersected_chains;
find_v_intersections_at_u(subface, param_plane, mid_u, v_min, v_max, v_intersections, intersected_chains); find_v_intersections_at_u(subface, param_plane, chain_bboxes, mid_u, v_min, v_max, v_intersections, intersected_chains);
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));
@ -165,7 +166,7 @@ stl_vector_mp<double> integrator_t::compute_u_breaks(const parametric_plane_t& p
void integrator_t::find_v_intersections_at_u(const subface& subface, void integrator_t::find_v_intersections_at_u(const subface& subface,
const parametric_plane_t& param_plane, const parametric_plane_t& param_plane,
const stl_vector_mp<Eigen::AlignedBox2d>& chain_bboxs, const stl_vector_mp<Eigen::AlignedBox2d>& chain_bboxes,
double u_val, double u_val,
double v_min, double v_min,
double v_max, double v_max,
@ -187,9 +188,10 @@ void integrator_t::find_v_intersections_at_u(const subface&
} }
// filter bbox // filter bbox
if (chain_bbox[chain_idx].isEmpty() const auto& box = chain_bboxes[chain_idx];
|| (chain_bbox[chain_idx].x() < u_val - 1e-8 || chain_bbox[chain_idx].x() > u_val + 1e-8)) { if (box.isEmpty()
chain_idx++; || box.max()(0) < u_val - 1e-8 // x_max < u_val - eps
|| box.min()(0) > u_val + 1e-8) { // x_min > u_val + eps
continue; continue;
} }
@ -268,14 +270,17 @@ void integrator_t::find_v_intersections_at_u(const subface&
// if (!intersections.empty()) { sort_and_unique_with_tol(intersections, 1e-8); } // if (!intersections.empty()) { sort_and_unique_with_tol(intersections, 1e-8); }
} }
bool is_edge_inside_domain(const stl_vector_mp<stl_vector_mp<uint16_t>>& chain_group_indices, bool integrator_t::is_edge_inside_domain(const stl_vector_mp<stl_vector_mp<uint16_t>>& chain_group_indices,
uint16_t chain_idx1, uint16_t chain_idx1,
uint16_t chain_idx2) const uint16_t chain_idx2) const
{ {
if (chain_idx1 >= chain_group_indices.size() || chain_idx2 >= chain_group_indices.size()) { return false; }
const auto& group1 = chain_group_indices[chain_idx1]; const auto& group1 = chain_group_indices[chain_idx1];
const auto& group2 = chain_group_indices[chain_idx2]; const auto& group2 = chain_group_indices[chain_idx2];
if (group1.find(chain_idx2) != group1.end() && group2.find(chain_idx1) != group2.end()) { return true; }
return false; return (std::find(group1.begin(), group1.end(), chain_idx2) != group1.end())
&& (std::find(group2.begin(), group2.end(), chain_idx1) != group2.end());
} }
bool integrator_t::is_u_near_singularity(double u, double tol) const { return false; } bool integrator_t::is_u_near_singularity(double u, double tol) const { return false; }

Loading…
Cancel
Save