27 #include <Eigen/Dense> 
   28 #include "ndarray/eigen.h" 
   36         float src_dist, ndarray::Array<float, 1, 1> 
const& ref_dist_array, 
float max_dist_rad) {
 
   38             std::upper_bound(ref_dist_array.begin(), ref_dist_array.end(), src_dist - max_dist_rad - 1e-16);
 
   40             std::upper_bound(ref_dist_array.begin(), ref_dist_array.end(), src_dist + max_dist_rad + 1e-16);
 
   42     size_t startIdx = itr - ref_dist_array.begin();
 
   43     size_t endIdx = itrEnd - ref_dist_array.begin();
 
   48         ndarray::Array<double, 1, 1> 
const& src_ctr, ndarray::Array<double, 2, 1> 
const& src_delta_array,
 
   49         ndarray::Array<double, 1, 1> 
const& src_dist_array, ndarray::Array<double, 1, 1> 
const& ref_ctr,
 
   50         ndarray::Array<double, 1, 1> 
const& proj_ref_ctr_delta,
 
   51         ndarray::Array<float, 1, 1> 
const& ref_dist_array, ndarray::Array<uint16_t, 1, 1> 
const& ref_id_array,
 
   52         ndarray::Array<double, 2, 1> 
const& reference_array, 
double max_dist_rad, 
size_t n_match) {
 
   62     auto src_ctr_eigen = ndarray::asEigenMatrix(src_ctr);
 
   63     double src_delta_ctr_dot = ndarray::asEigenMatrix(src_delta_array[0]).dot(src_ctr_eigen);
 
   65     ndarray::Array<double, 1, 1> proj_src_ctr_delta = copy(src_delta_array[0] - src_delta_ctr_dot * src_ctr);
 
   66     auto proj_src_ctr_delta_eigen = ndarray::asEigenMatrix(proj_src_ctr_delta);
 
   67     double proj_src_ctr_dist_sq = proj_src_ctr_delta_eigen.dot(proj_src_ctr_delta_eigen);
 
   70     auto proj_ref_ctr_delta_eigen = ndarray::asEigenMatrix(proj_ref_ctr_delta);
 
   71     double proj_ref_ctr_dist_sq = proj_ref_ctr_delta_eigen.dot(proj_ref_ctr_delta_eigen);
 
   75     double max_sin_tol = 0.0447;
 
   76     for (
size_t src_idx = 1; src_idx < src_dist_array.size(); src_idx++) {
 
   77         if (n_fail > src_dist_array.size() - (n_match - 1)) {
 
   85         if (candidate_range.first == candidate_range.second) {
 
   92         double src_sin_tol = max_dist_rad / (src_dist_array[src_idx] + max_dist_rad);
 
   98         if (src_sin_tol > max_sin_tol) {
 
   99             src_sin_tol = max_sin_tol;
 
  104         double proj_src_delta_dot = ndarray::asEigenMatrix(src_delta_array[src_idx]).dot(src_ctr_eigen);
 
  106         ndarray::Array<double, 1, 1> proj_src_delta =
 
  107                 copy(src_delta_array[src_idx] - proj_src_delta_dot * src_ctr);
 
  108         auto proj_src_delta_eigen = ndarray::asEigenMatrix(proj_src_delta);
 
  109         double geom_dist_src = sqrt(proj_src_delta_eigen.dot(proj_src_delta_eigen) * proj_src_ctr_dist_sq);
 
  112         double cos_theta_src = proj_src_delta_eigen.dot(proj_src_ctr_delta_eigen) / geom_dist_src;
 
  113         Eigen::Vector3d cross_src =
 
  114                 proj_src_delta_eigen.head<3>().cross(proj_src_ctr_delta_eigen.head<3>()) / geom_dist_src;
 
  115         double sin_theta_src = cross_src.dot(src_ctr_eigen);
 
  120                 check_spoke(cos_theta_src, sin_theta_src, ref_ctr, proj_ref_ctr_delta, proj_ref_ctr_dist_sq,
 
  121                             candidate_range, ref_id_array, reference_array, src_sin_tol);
 
  130         if (output_spokes.
size() >= n_match - 2) {
 
  134     return output_spokes;
 
  137 int check_spoke(
double cos_theta_src, 
double sin_theta_src, ndarray::Array<double, 1, 1> 
const& ref_ctr,
 
  138                 ndarray::Array<double, 1, 1> 
const& proj_ref_ctr_delta, 
double proj_ref_ctr_dist_sq,
 
  140                 ndarray::Array<uint16_t, 1, 1> 
const& ref_id_array,
 
  141                 ndarray::Array<double, 2, 1> 
const& reference_array, 
double src_sin_tol) {
 
  145     size_t midpoint = (candidate_range.first + candidate_range.second) / 2;
 
  146     for (
size_t idx = 0; idx < candidate_range.second - candidate_range.first; idx++) {
 
  148             midpoint = midpoint + idx;
 
  150             midpoint = midpoint - idx;
 
  153         uint16_t ref_id = ref_id_array[midpoint];
 
  154         ndarray::Array<double, 1, 1> ref_delta = copy(reference_array[ref_id] - ref_ctr);
 
  156         double ref_dot = ndarray::asEigenMatrix(ref_delta).dot(ndarray::asEigenMatrix(ref_ctr));
 
  157         ndarray::Array<double, 1, 1> proj_ref_delta = copy(ref_delta - ref_dot * ref_ctr);
 
  160         auto proj_ref_delta_eigen = ndarray::asEigenMatrix(proj_ref_delta);
 
  161         auto proj_ref_ctr_delta_eigen = ndarray::asEigenMatrix(proj_ref_ctr_delta);
 
  162         double proj_delta_dist_sq = proj_ref_delta_eigen.dot(proj_ref_delta_eigen);
 
  163         double geom_dist_ref = sqrt(proj_ref_ctr_dist_sq * proj_delta_dist_sq);
 
  164         double cos_theta_ref = proj_ref_delta_eigen.dot(proj_ref_ctr_delta_eigen) / geom_dist_ref;
 
  168         double cos_sq_comparison;
 
  169         if (cos_theta_ref * cos_theta_ref < (1 - src_sin_tol * src_sin_tol)) {
 
  170             cos_sq_comparison = (cos_theta_src - cos_theta_ref) * (cos_theta_src - cos_theta_ref) /
 
  171                                 (1 - cos_theta_ref * cos_theta_ref);
 
  173             cos_sq_comparison = (cos_theta_src - cos_theta_ref) * (cos_theta_src - cos_theta_ref) /
 
  174                                 (src_sin_tol * src_sin_tol);
 
  179         if (cos_sq_comparison > src_sin_tol * src_sin_tol) {
 
  185         Eigen::Vector3d cross_ref =
 
  186                 proj_ref_delta_eigen.head<3>().cross(proj_ref_ctr_delta_eigen.head<3>()) / geom_dist_ref;
 
  187         double sin_theta_ref = cross_ref.dot(ndarray::asEigenMatrix(ref_ctr));
 
  190         double sin_comparison;
 
  191         if (
abs(cos_theta_src) < src_sin_tol) {
 
  192             sin_comparison = (sin_theta_src - sin_theta_ref) / src_sin_tol;
 
  194             sin_comparison = (sin_theta_src - sin_theta_ref) / cos_theta_ref;
 
  198         if (
abs(sin_comparison) < src_sin_tol) {
 
int check_spoke(double cos_theta_src, double sin_theta_src, ndarray::Array< double, 1, 1 > const &ref_ctr, ndarray::Array< double, 1, 1 > const &proj_ref_ctr_delta, double proj_ref_ctr_dist_sq, std::pair< size_t, size_t > const &candidate_range, ndarray::Array< uint16_t, 1, 1 > const &ref_id_array, ndarray::Array< double, 2, 1 > const &reference_array, double src_sin_tol)
Check the opening angle between the first spoke of our pattern for the source object against the refe...
 
std::pair< size_t, size_t > find_candidate_reference_pair_range(float src_dist, ndarray::Array< float, 1, 1 > const &ref_dist_array, float max_dist_rad)
Find the range of reference spokes within a spoke distance tolerance of our source spoke.
 
std::vector< std::pair< size_t, size_t > > create_pattern_spokes(ndarray::Array< double, 1, 1 > const &src_ctr, ndarray::Array< double, 2, 1 > const &src_delta_array, ndarray::Array< double, 1, 1 > const &src_dist_array, ndarray::Array< double, 1, 1 > const &ref_ctr, ndarray::Array< double, 1, 1 > const &proj_ref_ctr_delta, ndarray::Array< float, 1, 1 > const &ref_dist_array, ndarray::Array< uint16_t, 1, 1 > const &ref_id_array, ndarray::Array< double, 2, 1 > const &reference_array, double max_dist_rad, size_t n_match)
Create the individual spokes that make up the pattern now that the shift and rotation are within tole...
 
Angle abs(Angle const &a)
 
A base class for image defects.