34 #include <visp3/core/vpImageCircle.h>
35 #include <visp3/core/vpMath.h>
51 #ifdef HAVE_OPENCV_CORE
53 : m_center(vec[1], vec[0])
69 void computeIntersectionsLeftBorderOnly(
const float &u_c,
const float &umin_roi,
const float &radius,
74 float theta1 = std::acos((umin_roi - u_c) / radius);
76 float theta2 = -1.f * theta1;
77 float theta_min = std::min<float>(theta1, theta2);
78 float theta_max = std::max<float>(theta1, theta2);
79 delta_theta = theta_max - theta_min;
80 if ((u_c < umin_roi) && (std::abs(delta_theta - (2 * M_PIf)) < (2.f * std::numeric_limits<float>::epsilon()))) {
94 void computeIntersectionsRightBorderOnly(
const float &u_c,
const float &umax_roi,
const float &radius,
99 float theta1 = std::acos((umax_roi - u_c) / radius);
101 float theta2 = -1.f * theta1;
102 float theta_min = std::min<float>(theta1, theta2);
103 float theta_max = std::max<float>(theta1, theta2);
104 delta_theta = (2.f * M_PIf) - (theta_max - theta_min);
105 if ((u_c > umax_roi) && (std::abs(delta_theta - (2 * M_PIf)) < (2.f * std::numeric_limits<float>::epsilon()))) {
119 void computeIntersectionsTopBorderOnly(
const float &v_c,
const float &vmin_roi,
const float &radius,
124 float theta1 = std::asin((v_c - vmin_roi) / radius);
129 theta2 = M_PIf - theta1;
132 theta2 = -theta1 - M_PIf;
134 float theta_min = std::min<float>(theta1, theta2);
135 float theta_max = std::max<float>(theta1, theta2);
136 if ((std::abs(theta_max - theta_min) * radius) < 1.f) {
139 delta_theta = 2.f * M_PIf;
141 else if (theta1 > 0.f) {
142 delta_theta = (2.f * M_PIf) - (theta_max - theta_min);
145 delta_theta = theta_max - theta_min;
147 if ((v_c < vmin_roi) && (std::abs(delta_theta - (2 * M_PIf)) < (2.f * std::numeric_limits<float>::epsilon()))) {
161 void computeIntersectionsBottomBorderOnly(
const float &v_c,
const float &vmax_roi,
const float &radius,
166 float theta1 = std::asin((v_c - vmax_roi) / radius);
171 theta2 = M_PIf - theta1;
174 theta2 = -theta1 - M_PIf;
176 float theta_min = std::min<float>(theta1, theta2);
177 float theta_max = std::max<float>(theta1, theta2);
178 if ((std::abs(theta_max - theta_min) * radius) < 1.f) {
181 delta_theta = 2.f * M_PIf;
183 else if (theta1 > 0.f) {
184 delta_theta = theta_max - theta_min;
187 delta_theta = (2.f * M_PIf) - (theta_max - theta_min);
189 if ((v_c > vmax_roi) && (std::abs(delta_theta - (2 * M_PIf)) < (2.f * std::numeric_limits<float>::epsilon()))) {
208 void computePerpendicularAxesIntersections(
const float &u_c,
const float &v_c,
const float &radius,
209 const float &crossing_u,
const float &crossing_v,
210 std::pair<float, float> &theta_u_cross_min, std::pair<float, float> &theta_u_cross_max,
211 std::pair<float, float> &theta_v_cross_min, std::pair<float, float> &theta_v_cross_max)
216 float theta_u_cross = std::asin((v_c - crossing_u) / radius);
218 float theta_u_cross_2 = 0.f;
219 if (theta_u_cross > 0) {
220 theta_u_cross_2 = M_PIf - theta_u_cross;
223 theta_u_cross_2 = -M_PIf - theta_u_cross;
226 float u_ucross = u_c + (radius * std::cos(theta_u_cross));
227 float u_ucross2 = u_c + (radius * std::cos(theta_u_cross_2));
229 if (u_ucross < u_ucross2) {
230 theta_u_cross_min.first = theta_u_cross;
231 theta_u_cross_min.second = u_ucross;
232 theta_u_cross_max.first = theta_u_cross_2;
233 theta_u_cross_max.second = u_ucross2;
236 theta_u_cross_min.first = theta_u_cross_2;
237 theta_u_cross_min.second = u_ucross2;
238 theta_u_cross_max.first = theta_u_cross;
239 theta_u_cross_max.second = u_ucross;
245 float theta_v_cross = std::acos((crossing_v - u_c) / radius);
247 float theta_v_cross_2 = -theta_v_cross;
250 float v_vcross = v_c - (radius * std::sin(theta_v_cross));
251 float v_vcross2 = v_c - (radius * std::sin(theta_v_cross_2));
253 if (v_vcross < v_vcross2) {
254 theta_v_cross_min.first = theta_v_cross;
255 theta_v_cross_min.second = v_vcross;
256 theta_v_cross_max.first = theta_v_cross_2;
257 theta_v_cross_max.second = v_vcross2;
260 theta_v_cross_min.first = theta_v_cross_2;
261 theta_v_cross_min.second = v_vcross2;
262 theta_v_cross_max.first = theta_v_cross;
263 theta_v_cross_max.second = v_vcross;
278 void computeIntersectionsTopLeft(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &vmin_roi,
const float &radius,
281 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
282 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
283 float crossing_u = vmin_roi;
284 float crossing_v = umin_roi;
285 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v,
286 crossing_theta_u_min, crossing_theta_u_max,
287 crossing_theta_v_min, crossing_theta_v_max);
288 float theta_u_min = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
289 float theta_u_max = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
290 float u_umin = crossing_theta_u_min.second;
291 float u_umax = crossing_theta_u_max.second;
292 float v_vmin = crossing_theta_v_min.second;
293 float v_vmax = crossing_theta_v_max.second;
294 if ((u_umin < umin_roi) && (u_umax >= umin_roi) && (v_vmin < vmin_roi) && (v_vmax >= vmin_roi)) {
297 delta_theta = theta_u_max - theta_v_max;
299 else if ((u_umin >= umin_roi) && (u_umax >= umin_roi) && (v_vmin >= vmin_roi) && (v_vmax >= vmin_roi)) {
302 delta_theta = (theta_v_min - theta_u_min) + (theta_u_max - theta_v_max);
304 else if ((u_umin < umin_roi) && (u_umax < umin_roi) && (v_vmin >= vmin_roi) && (v_vmax >= vmin_roi)) {
308 computeIntersectionsLeftBorderOnly(u_c, umin_roi, radius, delta_theta);
310 else if ((u_umin >= umin_roi) && (u_umax >= umin_roi) && (v_vmin <= vmin_roi) && (v_vmax <= vmin_roi)) {
314 computeIntersectionsTopBorderOnly(v_c, vmin_roi, radius, delta_theta);
329 void computeIntersectionsTopRight(
const float &u_c,
const float &v_c,
const float &vmin_roi,
const float &umax_roi,
const float &radius,
332 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
333 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
334 computePerpendicularAxesIntersections(u_c, v_c, radius, vmin_roi, umax_roi,
335 crossing_theta_u_min, crossing_theta_u_max,
336 crossing_theta_v_min, crossing_theta_v_max);
337 float theta_u_min = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
338 float theta_u_max = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
339 float u_umin = crossing_theta_u_min.second;
340 float u_umax = crossing_theta_u_max.second;
341 float v_vmin = crossing_theta_v_min.second;
342 float v_vmax = crossing_theta_v_max.second;
343 if ((u_umin <= umax_roi) && (v_vmin < vmin_roi) && (u_umax >= umax_roi) && (v_vmax >= vmin_roi)) {
346 delta_theta = theta_v_max - theta_u_min;
347 if (delta_theta < 0) {
349 delta_theta += 2.f * M_PIf;
352 else if ((u_umin <= umax_roi) && (v_vmin >= vmin_roi) && (u_umax <= umax_roi) && (v_vmax >= vmin_roi)) {
355 delta_theta = (2 * M_PIf) - ((theta_u_min - theta_u_max) + (theta_v_min - theta_v_max));
357 else if ((u_umin >= umax_roi) && (v_vmin >= vmin_roi) && (u_umax >= umax_roi) && (v_vmax >= vmin_roi)) {
361 computeIntersectionsRightBorderOnly(u_c, umax_roi, radius, delta_theta);
363 else if ((u_umin <= umax_roi) && (v_vmin <= vmin_roi) && (u_umax <= umax_roi) && (v_vmax <= vmin_roi)) {
367 computeIntersectionsTopBorderOnly(v_c, vmin_roi, radius, delta_theta);
382 void computeIntersectionsBottomLeft(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &vmax_roi,
const float &radius,
385 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
386 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
387 float crossing_u = vmax_roi;
388 float crossing_v = umin_roi;
389 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v,
390 crossing_theta_u_min, crossing_theta_u_max,
391 crossing_theta_v_min, crossing_theta_v_max);
392 float theta_u_min = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
393 float theta_u_max = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
394 float u_umin = crossing_theta_u_min.second;
395 float u_umax = crossing_theta_u_max.second;
396 float v_vmin = crossing_theta_v_min.second;
397 float v_vmax = crossing_theta_v_max.second;
398 if ((u_umin < umin_roi) && (u_umax >= umin_roi) && (v_vmin <= vmax_roi) && (v_vmax > vmax_roi)) {
401 delta_theta = theta_v_min - theta_u_max;
403 else if ((u_umin >= umin_roi) && (u_umax >= umin_roi) && (v_vmin <= vmax_roi) && (v_vmax <= vmax_roi)) {
406 delta_theta = (theta_v_min - theta_u_max) + (theta_u_min - theta_v_max);
408 else if ((u_umin < umin_roi) && (u_umax < umin_roi) && (v_vmin <= vmax_roi) && (v_vmax <= vmax_roi)) {
412 computeIntersectionsLeftBorderOnly(u_c, umin_roi, radius, delta_theta);
414 else if ((u_umin >= umin_roi) && (u_umax >= umin_roi) && (v_vmin >= vmax_roi) && (v_vmax >= vmax_roi)) {
418 computeIntersectionsBottomBorderOnly(v_c, vmax_roi, radius, delta_theta);
433 void computeIntersectionsBottomRight(
const float &u_c,
const float &v_c,
const float &vmax_roi,
const float &umax_roi,
const float &radius,
436 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
437 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
438 float crossing_u = vmax_roi;
439 float crossing_v = umax_roi;
440 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v,
441 crossing_theta_u_min, crossing_theta_u_max,
442 crossing_theta_v_min, crossing_theta_v_max);
443 float theta_u_min = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
444 float theta_u_max = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
445 float u_umin = crossing_theta_u_min.second;
446 float u_umax = crossing_theta_u_max.second;
447 float v_vmin = crossing_theta_v_min.second;
448 float v_vmax = crossing_theta_v_max.second;
449 if ((u_umin <= umax_roi) && (u_umax > umax_roi) && (v_vmin <= vmax_roi) && (v_vmax > vmax_roi)) {
452 delta_theta = theta_u_min - theta_v_min;
453 if (delta_theta < 0) {
455 delta_theta += 2.f * M_PIf;
458 else if ((u_umin <= umax_roi) && (u_umax <= umax_roi) && (v_vmin <= vmax_roi) && (v_vmax <= vmax_roi)) {
461 delta_theta = (2.f * M_PIf) - ((theta_v_min - theta_v_max) + (theta_u_max - theta_u_min));
463 else if ((u_umin > umax_roi) && (u_umax > umax_roi) && (v_vmin <= vmax_roi) && (v_vmax <= vmax_roi)) {
467 computeIntersectionsRightBorderOnly(u_c, umax_roi, radius, delta_theta);
469 else if ((u_umin <= umax_roi) && (u_umax <= umax_roi) && (v_vmin > vmax_roi) && (v_vmax > vmax_roi)) {
473 computeIntersectionsBottomBorderOnly(v_c, vmax_roi, radius, delta_theta);
489 void computeIntersectionsTopLeftBottom(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &vmin_roi,
490 const float &vmax_roi,
const float &radius,
float &delta_theta)
493 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
494 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
495 float crossing_u_top = vmin_roi;
496 float crossing_v = umin_roi;
497 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_top, crossing_v,
498 crossing_theta_u_min, crossing_theta_u_max,
499 crossing_theta_v_min, crossing_theta_v_max);
500 float theta_u_min_top = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
501 float theta_u_max_top = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
502 float u_umin_top = crossing_theta_u_min.second;
503 float u_umax_top = crossing_theta_u_max.second;
504 float v_vmin = crossing_theta_v_min.second;
505 float v_vmax = crossing_theta_v_max.second;
508 float crossing_u_bottom = vmax_roi;
509 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_bottom, crossing_v,
510 crossing_theta_u_min, crossing_theta_u_max,
511 crossing_theta_v_min, crossing_theta_v_max);
512 float theta_u_min_bottom = crossing_theta_u_min.first;
513 float theta_u_max_bottom = crossing_theta_u_max.first;
514 float u_umin_bottom = crossing_theta_u_min.second;
515 float u_umax_bottom = crossing_theta_u_max.second;
516 if ((u_umin_top >= umin_roi) && (u_umin_bottom >= umin_roi) && (v_vmin >= vmin_roi) && (v_vmax <= vmax_roi)) {
518 delta_theta = (theta_v_min - theta_u_min_top) + (theta_u_max_top - theta_u_max_bottom) + (theta_u_min_bottom - theta_v_max);
520 else if ((u_umin_top <= umin_roi) && (v_vmin <= vmin_roi) && (u_umin_bottom <= umin_roi) && (v_vmax >= vmax_roi)) {
522 delta_theta = (theta_u_max_top - theta_u_max_bottom);
524 else if ((u_umax_top <= umin_roi) && (u_umax_bottom <= umin_roi) && (v_vmin >= vmin_roi) && (v_vmax <= vmax_roi)) {
526 computeIntersectionsLeftBorderOnly(u_c, umin_roi, radius, delta_theta);
528 else if ((u_umax_bottom > umin_roi) && (v_vmin >= vmin_roi)) {
530 computeIntersectionsBottomLeft(u_c, v_c, umin_roi, vmax_roi, radius, delta_theta);
532 else if ((u_umax_top > umin_roi) && (v_vmax <= vmax_roi)) {
534 computeIntersectionsTopLeft(u_c, v_c, umin_roi, vmin_roi, radius, delta_theta);
550 void computeIntersectionsTopRightBottom(
const float &u_c,
const float &v_c,
const float &umax_roi,
const float &vmin_roi,
const float &vmax_roi,
551 const float &radius,
float &delta_theta)
554 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
555 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
556 float crossing_u_top = vmin_roi;
557 float crossing_v = umax_roi;
558 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_top, crossing_v,
559 crossing_theta_u_min, crossing_theta_u_max,
560 crossing_theta_v_min, crossing_theta_v_max);
561 float theta_u_min_top = crossing_theta_u_min.first, theta_v_min = crossing_theta_v_min.first;
562 float theta_u_max_top = crossing_theta_u_max.first, theta_v_max = crossing_theta_v_max.first;
563 float u_umin_top = crossing_theta_u_min.second;
564 float u_umax_top = crossing_theta_u_max.second;
565 float v_vmin = crossing_theta_v_min.second;
566 float v_vmax = crossing_theta_v_max.second;
569 float crossing_u_bottom = vmax_roi;
570 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_bottom, crossing_v,
571 crossing_theta_u_min, crossing_theta_u_max,
572 crossing_theta_v_min, crossing_theta_v_max);
573 float theta_u_min_bottom = crossing_theta_u_min.first;
574 float theta_u_max_bottom = crossing_theta_u_max.first;
575 float u_umin_bottom = crossing_theta_u_min.second;
576 float u_umax_bottom = crossing_theta_u_max.second;
577 if ((u_umax_top <= umax_roi) && (u_umax_bottom <= umax_roi) && (v_vmin >= vmin_roi) && (v_vmax <= vmax_roi)) {
579 delta_theta = (2.f * M_PIf) - ((theta_u_min_top - theta_u_max_top) + (theta_v_min - theta_v_max) + (theta_u_max_bottom - theta_u_min_bottom));
581 else if ((u_umin_top <= umax_roi) && (u_umax_top > umax_roi) && (v_vmin <= vmin_roi) && (u_umin_bottom <= umax_roi) && (u_umax_bottom > umax_roi) && (v_vmax >= vmax_roi)) {
583 delta_theta = (theta_u_max_top - theta_u_max_bottom);
585 else if ((u_umin_top >= umax_roi) && (u_umin_bottom >= umax_roi) && (v_vmin >= vmin_roi) && (v_vmax <= vmax_roi)) {
587 computeIntersectionsRightBorderOnly(u_c, umax_roi, radius, delta_theta);
589 else if ((u_umin_bottom <= umax_roi) && (v_vmin >= vmin_roi)) {
591 computeIntersectionsBottomRight(u_c, v_c, vmax_roi, umax_roi, radius, delta_theta);
593 else if ((u_umin_top <= umax_roi) && (v_vmax <= vmax_roi)) {
595 computeIntersectionsTopRight(u_c, v_c, vmin_roi, umax_roi, radius, delta_theta);
610 void computeIntersectionsTopBottomOnly(
const float &u_c,
const float &v_c,
const float &vmin_roi,
const float &vmax_roi,
const float &radius,
616 float theta_u_cross_top = std::asin((v_c - vmin_roi) / radius);
618 float theta_u_cross_top_2 = 0.f;
619 if (theta_u_cross_top > 0) {
620 theta_u_cross_top_2 = M_PIf - theta_u_cross_top;
623 theta_u_cross_top_2 = -M_PIf - theta_u_cross_top;
627 float u_ucross_top = u_c + (radius * std::cos(theta_u_cross_top));
628 float u_ucross_top_2 = u_c + (radius * std::cos(theta_u_cross_top_2));
630 float theta_u_cross_top_min = 0.f, theta_u_cross_top_max = 0.f;
631 if (u_ucross_top < u_ucross_top_2) {
632 theta_u_cross_top_min = theta_u_cross_top;
633 theta_u_cross_top_max = theta_u_cross_top_2;
636 theta_u_cross_top_min = theta_u_cross_top_2;
637 theta_u_cross_top_max = theta_u_cross_top;
643 float theta_u_cross_bottom = std::asin((v_c - vmax_roi) / radius);
645 float theta_u_cross_bottom_2 = 0.f;
646 if (theta_u_cross_bottom > 0) {
647 theta_u_cross_bottom_2 = M_PIf - theta_u_cross_bottom;
650 theta_u_cross_bottom_2 = -M_PIf - theta_u_cross_bottom;
654 float u_ucross_bottom = u_c + (radius * std::cos(theta_u_cross_bottom));
655 float u_ucross_bottom_2 = u_c + (radius * std::cos(theta_u_cross_bottom_2));
658 float theta_u_cross_bottom_min = 0.f, theta_u_cross_bottom_max = 0.f;
659 if (u_ucross_bottom < u_ucross_bottom_2) {
660 theta_u_cross_bottom_min = theta_u_cross_bottom;
661 theta_u_cross_bottom_max = theta_u_cross_bottom_2;
664 theta_u_cross_bottom_min = theta_u_cross_bottom_2;
665 theta_u_cross_bottom_max = theta_u_cross_bottom;
670 delta_theta = (2.f * M_PIf) - ((theta_u_cross_top_min - theta_u_cross_top_max) + (theta_u_cross_bottom_max - theta_u_cross_bottom_min));
685 void computeIntersectionsLeftRightTop(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &umax_roi,
686 const float &vmin_roi,
const float &radius,
float &delta_theta)
689 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
690 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
691 float crossing_u = vmin_roi;
692 float crossing_v_left = umin_roi;
693 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v_left,
694 crossing_theta_u_min, crossing_theta_u_max,
695 crossing_theta_v_min, crossing_theta_v_max);
696 float theta_u_min = crossing_theta_u_min.first;
697 float theta_u_max = crossing_theta_u_max.first;
698 float u_umin = crossing_theta_u_min.second;
699 float u_umax = crossing_theta_u_max.second;
700 float theta_v_min_left = crossing_theta_v_min.first;
701 float theta_v_max_left = crossing_theta_v_max.first;
702 float v_vmin_left = crossing_theta_v_min.second;
703 float v_vmax_left = crossing_theta_v_max.second;
706 float crossing_v_right = umax_roi;
707 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v_right,
708 crossing_theta_u_min, crossing_theta_u_max,
709 crossing_theta_v_min, crossing_theta_v_max);
710 float theta_v_min_right = crossing_theta_v_min.first;
711 float theta_v_max_right = crossing_theta_v_max.first;
712 float v_vmin_right = crossing_theta_v_min.second;
713 float v_vmax_right = crossing_theta_v_max.second;
715 if ((u_umin >= umin_roi) && (u_umax <= umax_roi) && (v_vmin_left >= vmin_roi) && (v_vmin_right >= vmin_roi)) {
717 delta_theta = (theta_v_min_left - theta_u_min) + (theta_u_max - theta_v_min_right) + (theta_v_max_right - theta_v_max_left);
719 else if ((u_umin <= umin_roi) && (u_umax >= umax_roi) && (v_vmax_left >= vmin_roi) && (v_vmax_right >= vmin_roi)) {
721 delta_theta = (theta_v_max_right - theta_v_max_left);
723 else if ((v_vmax_left <= vmin_roi) && (v_vmax_right <= vmin_roi) && (u_umin >= umin_roi) && (u_umax <= umax_roi)) {
725 computeIntersectionsTopBorderOnly(v_c, vmin_roi, radius, delta_theta);
727 else if ((u_umax >= umin_roi) && (v_vmax_left >= vmin_roi)) {
729 computeIntersectionsTopLeft(u_c, v_c, umin_roi, vmin_roi, radius, delta_theta);
731 else if ((u_umin <= umax_roi) && (v_vmax_right >= vmin_roi)) {
733 computeIntersectionsTopRight(u_c, v_c, vmin_roi, umax_roi, radius, delta_theta);
749 void computeIntersectionsLeftRightBottom(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &umax_roi,
750 const float &vmax_roi,
const float &radius,
float &delta_theta)
753 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
754 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
755 float crossing_u = vmax_roi;
756 float crossing_v_left = umin_roi;
757 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v_left,
758 crossing_theta_u_min, crossing_theta_u_max,
759 crossing_theta_v_min, crossing_theta_v_max);
760 float theta_u_min = crossing_theta_u_min.first;
761 float theta_u_max = crossing_theta_u_max.first;
762 float u_umin = crossing_theta_u_min.second;
763 float u_umax = crossing_theta_u_max.second;
764 float theta_v_min_left = crossing_theta_v_min.first;
765 float theta_v_max_left = crossing_theta_v_max.first;
766 float v_vmin_left = crossing_theta_v_min.second;
770 float crossing_v_right = umax_roi;
771 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u, crossing_v_right,
772 crossing_theta_u_min, crossing_theta_u_max,
773 crossing_theta_v_min, crossing_theta_v_max);
774 float theta_v_min_right = crossing_theta_v_min.first;
775 float theta_v_max_right = crossing_theta_v_max.first;
776 float v_vmin_right = crossing_theta_v_min.second;
779 if ((u_umin >= umin_roi) && (u_umax <= umax_roi) && (v_vmin_left <= vmax_roi) && (v_vmin_right <= vmax_roi)) {
781 delta_theta = (theta_v_min_left - theta_v_min_right) + (theta_v_max_right - theta_u_max) + (theta_u_min - theta_v_max_left);
783 else if ((u_umin <= umin_roi) && (u_umax >= umax_roi) && (v_vmin_left <= vmax_roi) && (v_vmin_right <= vmax_roi)) {
785 delta_theta = (theta_v_min_left - theta_v_min_right);
787 else if ((v_vmin_left >= vmax_roi) && (v_vmin_right >= vmax_roi) && (u_umin >= umin_roi) && (u_umax <= umax_roi)) {
789 computeIntersectionsBottomBorderOnly(v_c, vmax_roi, radius, delta_theta);
791 else if ((u_umax >= umin_roi) && (v_vmin_right >= vmax_roi)) {
793 computeIntersectionsBottomLeft(u_c, v_c, umin_roi, vmax_roi, radius, delta_theta);
795 else if ((u_umin <= umax_roi) && (v_vmin_right <= vmax_roi)) {
797 computeIntersectionsBottomRight(u_c, v_c, vmax_roi, umax_roi, radius, delta_theta);
812 void computeIntersectionsLeftRightOnly(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &umax_roi,
const float &radius,
819 float theta_v_cross_left = std::acos((umin_roi - u_c) / radius);
821 float theta_v_cross_left_2 = -theta_v_cross_left;
824 float v_vcross_left = v_c - (radius * std::sin(theta_v_cross_left));
825 float v_vcross_left_2 = v_c - (radius * std::sin(theta_v_cross_left_2));
827 float theta_v_cross_left_min = 0.f, theta_v_cross_left_max = 0.f;
828 if (v_vcross_left < v_vcross_left_2) {
829 theta_v_cross_left_min = theta_v_cross_left;
830 theta_v_cross_left_max = theta_v_cross_left_2;
833 theta_v_cross_left_min = theta_v_cross_left_2;
834 theta_v_cross_left_max = theta_v_cross_left;
841 float theta_v_cross_right = std::acos((umax_roi - u_c) / radius);
843 float theta_v_cross_right_2 = -theta_v_cross_right;
846 float v_vcross_right = v_c - (radius * std::sin(theta_v_cross_right));
847 float v_vcross_right_2 = v_c - (radius * std::sin(theta_v_cross_right_2));
850 float theta_v_cross_right_min = 0.f, theta_v_cross_right_max = 0.f;
851 if (v_vcross_right < v_vcross_right_2) {
852 theta_v_cross_right_min = theta_v_cross_right;
853 theta_v_cross_right_max = theta_v_cross_right_2;
856 theta_v_cross_right_min = theta_v_cross_right_2;
857 theta_v_cross_right_max = theta_v_cross_right;
862 delta_theta = (theta_v_cross_left_min - theta_v_cross_right_min) + (theta_v_cross_right_max - theta_v_cross_left_max);
879 void computeIntersectionsAllAxes(
const float &u_c,
const float &v_c,
const float &umin_roi,
const float &umax_roi,
880 const float &vmin_roi,
const float &vmax_roi,
const float &radius,
float &delta_theta)
883 std::pair<float, float> crossing_theta_u_min, crossing_theta_u_max;
884 std::pair<float, float> crossing_theta_v_min, crossing_theta_v_max;
885 float crossing_u_top = vmin_roi;
886 float crossing_v_left = umin_roi;
887 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_top, crossing_v_left,
888 crossing_theta_u_min, crossing_theta_u_max,
889 crossing_theta_v_min, crossing_theta_v_max);
890 float theta_u_min_top = crossing_theta_u_min.first;
891 float theta_u_max_top = crossing_theta_u_max.first;
892 float theta_v_min_left = crossing_theta_v_min.first;
893 float theta_v_max_left = crossing_theta_v_max.first;
896 float crossing_u_bottom = vmax_roi;
897 float crossing_v_right = umax_roi;
898 computePerpendicularAxesIntersections(u_c, v_c, radius, crossing_u_bottom, crossing_v_right,
899 crossing_theta_u_min, crossing_theta_u_max,
900 crossing_theta_v_min, crossing_theta_v_max);
901 float theta_u_min_bottom = crossing_theta_u_min.first;
902 float theta_u_max_bottom = crossing_theta_u_max.first;
903 float theta_v_min_right = crossing_theta_v_min.first;
904 float theta_v_max_right = crossing_theta_v_max.first;
905 delta_theta = (theta_v_min_left - theta_u_min_top) + (theta_u_max_top - theta_v_min_right);
906 delta_theta += (theta_v_max_right - theta_u_max_bottom) + (theta_u_min_bottom - theta_v_max_left);
911 float delta_theta = 0.f;
913 float u_c =
static_cast<float>(center.
get_u());
914 float v_c =
static_cast<float>(center.
get_v());
915 float radius = m_radius;
916 float roi_w =
static_cast<float>(roi.
getWidth());
917 float roi_h =
static_cast<float>(roi.
getHeight());
919 float umin_roi =
static_cast<float>(topLeft.
get_u());
920 float vmin_roi =
static_cast<float>(topLeft.
get_v());
921 float umax_roi = umin_roi + roi_w;
922 float vmax_roi = vmin_roi + roi_h;
923 bool touchLeftBorder = (u_c - radius) <= umin_roi;
924 bool touchRightBorder = (u_c + radius) >= umax_roi;
925 bool touchTopBorder = (v_c - radius) <= vmin_roi;
926 bool touchBottomBorder = (v_c + radius) >= vmax_roi;
927 bool isHorizontallyOK = ((!touchLeftBorder) && (!touchRightBorder));
928 bool isVerticallyOK = ((!touchTopBorder) && (!touchBottomBorder));
929 if (isHorizontallyOK && isVerticallyOK && roi.
isInside(m_center)) {
933 delta_theta = 2.f * M_PIf;
935 else if (touchBottomBorder && (!touchLeftBorder) && (!touchRightBorder) && (!touchTopBorder)) {
937 computeIntersectionsBottomBorderOnly(v_c, vmax_roi, radius, delta_theta);
939 else if ((!touchBottomBorder) && touchLeftBorder && (!touchRightBorder) && (!touchTopBorder)) {
941 computeIntersectionsLeftBorderOnly(u_c, umin_roi, radius, delta_theta);
943 else if ((!touchBottomBorder) && (!touchLeftBorder) && touchRightBorder && (!touchTopBorder)) {
945 computeIntersectionsRightBorderOnly(u_c, umax_roi, radius, delta_theta);
947 else if ((!touchBottomBorder) && (!touchLeftBorder) && (!touchRightBorder) && touchTopBorder) {
949 computeIntersectionsTopBorderOnly(v_c, vmin_roi, radius, delta_theta);
951 else if (touchBottomBorder && touchLeftBorder && (!touchRightBorder) && (!touchTopBorder)) {
953 computeIntersectionsBottomLeft(u_c, v_c, umin_roi, vmax_roi, radius, delta_theta);
955 else if (touchBottomBorder && (!touchLeftBorder) && touchRightBorder && (!touchTopBorder)) {
957 computeIntersectionsBottomRight(u_c, v_c, vmax_roi, umax_roi, radius, delta_theta);
959 else if ((!touchBottomBorder) && touchLeftBorder && (!touchRightBorder) && touchTopBorder) {
961 computeIntersectionsTopLeft(u_c, v_c, umin_roi, vmin_roi, radius, delta_theta);
963 else if ((!touchBottomBorder) && (!touchLeftBorder) && touchRightBorder && touchTopBorder) {
965 computeIntersectionsTopRight(u_c, v_c, vmin_roi, umax_roi, radius, delta_theta);
967 else if (touchBottomBorder && touchTopBorder && touchLeftBorder && (!touchRightBorder)) {
969 computeIntersectionsTopLeftBottom(u_c, v_c, umin_roi, vmin_roi, vmax_roi, radius, delta_theta);
971 else if (touchBottomBorder && touchTopBorder && (!touchLeftBorder) && touchRightBorder) {
973 computeIntersectionsTopRightBottom(u_c, v_c, umax_roi, vmin_roi, vmax_roi, radius, delta_theta);
975 else if (touchBottomBorder && touchTopBorder && (!touchLeftBorder) && (!touchRightBorder)) {
977 computeIntersectionsTopBottomOnly(u_c, v_c, vmin_roi, vmax_roi, radius, delta_theta);
979 else if ((!touchBottomBorder) && touchTopBorder && touchLeftBorder && touchRightBorder) {
981 computeIntersectionsLeftRightTop(u_c, v_c, umin_roi, umax_roi, vmin_roi, radius, delta_theta);
983 else if (touchBottomBorder && (!touchTopBorder) && touchLeftBorder && touchRightBorder) {
985 computeIntersectionsLeftRightBottom(u_c, v_c, umin_roi, umax_roi, vmax_roi, radius, delta_theta);
987 else if (touchLeftBorder && touchRightBorder && (!touchTopBorder) && (!touchBottomBorder)) {
989 computeIntersectionsLeftRightOnly(u_c, v_c, umin_roi, umax_roi, radius, delta_theta);
991 else if (touchLeftBorder && touchRightBorder && touchTopBorder && touchBottomBorder) {
993 computeIntersectionsAllAxes(u_c, v_c, umin_roi, umax_roi, vmin_roi, vmax_roi, radius, delta_theta);
996 std::cerr <<
"touchLeft = " << (touchLeftBorder ?
"true" :
"false") <<
"\ttouchRight = " << (touchRightBorder ?
"true" :
"false") << std::endl;
997 std::cerr <<
"touchTop = " << (touchTopBorder ?
"true" :
"false") <<
"\ttouchBottom = " << (touchBottomBorder ?
"true" :
"false") << std::endl;
998 std::cerr <<
"u_c = " << u_c <<
"\tv_c = " << v_c <<
"\tradius = " << radius << std::endl;
999 std::cerr <<
"umin_roi = " << umin_roi <<
"\tumax_roi = " << umax_roi << std::endl;
1000 std::cerr <<
"vmin_roi = " << vmin_roi <<
"\tvmax_roi = " << vmax_roi << std::endl << std::flush;
1004 if ((delta_theta < 0) || (delta_theta >(2.f * M_PIf))) {
1006 if ((rest < roundingTolerance) && ((delta_theta < -M_PIf) || (delta_theta > M_PIf))) {
1008 delta_theta = 2.f * M_PIf;
1022 return delta_theta * m_radius;
1025 #if (VISP_CXX_STANDARD == VISP_CXX_STANDARD_98)
1029 void incrementIfIsInMask(
const vpImage<bool> &mask,
const int &width,
const int &height,
const int &x,
const int &y,
1030 unsigned int &count)
1032 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1046 const float xm =
static_cast<float>(m_center.
get_u()), ym =
static_cast<float>(m_center.
get_v());
1047 const float r_float =
static_cast<float>(m_radius);
1051 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1053 auto incrementIfIsInMask = [](
const vpImage<bool> &mask,
const int &width,
const int &height,
const int &x,
const int &y,
1054 unsigned int &count) {
1055 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1065 unsigned int count = 0;
1067 const float thetaStop = M_PI_2f;
1069 int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
1070 int y1 = 0, y2 = 0, y3 = 0, y4 = 0;
1071 while (theta < thetaStop) {
1072 float cos_theta = std::cos(theta);
1073 float sin_theta = std::sin(theta);
1074 float rcos_pos = r_float * cos_theta;
1075 float rsin_pos = r_float * sin_theta;
1076 x1 =
static_cast<int>(xm + rcos_pos);
1077 y1 =
static_cast<int>(ym + rsin_pos);
1078 x2 =
static_cast<int>(xm - rsin_pos);
1079 y2 =
static_cast<int>(ym + rcos_pos);
1080 x3 =
static_cast<int>(xm - rcos_pos);
1081 y3 =
static_cast<int>(ym - rsin_pos);
1082 x4 =
static_cast<int>(xm + rsin_pos);
1083 y4 =
static_cast<int>(ym - rcos_pos);
1084 incrementIfIsInMask(mask, width, height, x1, y1, count);
1085 incrementIfIsInMask(mask, width, height, x2, y2, count);
1086 incrementIfIsInMask(mask, width, height, x3, y3, count);
1087 incrementIfIsInMask(mask, width, height, x4, y4, count);
1093 float dthetaCosPos = 1.f / (r_float * cos_theta);
1094 float dthetaCosNeg = -1.f / (r_float * cos_theta);
1095 float dthetaSinPos = 1.f / (r_float * sin_theta);
1096 float dthetaSinNeg = -1.f / (r_float * sin_theta);
1097 float dthetaPos = 0.f;
1098 if ((sin_theta < 0.f) && (cos_theta > 0.f)) {
1100 dthetaPos = std::min<float>(dthetaCosPos, dthetaSinNeg);
1102 else if ((sin_theta > 0.f) && (cos_theta < 0.f)) {
1104 dthetaPos = std::min<float>(dthetaCosNeg, dthetaSinPos);
1106 else if ((sin_theta < 0.f) && (cos_theta < 0.f)) {
1108 dthetaPos = std::min<float>(dthetaCosNeg, dthetaSinNeg);
1110 else if ((sin_theta > 0.f) && (cos_theta > 0.f)) {
1112 dthetaPos = std::min<float>(dthetaCosPos, dthetaSinPos);
1116 if (cos_theta > 0.f) {
1117 dthetaPos = dthetaCosNeg;
1120 dthetaPos = dthetaCosPos;
1125 if (sin_theta > 0.f) {
1126 dthetaPos = dthetaSinNeg;
1129 dthetaPos = dthetaSinPos;
1149 vpRect bbox(m_center -
vpImagePoint(m_radius, m_radius), 2 * m_radius, 2 * m_radius);
1155 return (m_radius * m_radius) / 4;
1160 return (m_radius * m_radius) / 4;
error that can be emitted by ViSP classes.
float computeAngularCoverageInRoI(const vpRect &roi, const float &roundingTolerance=0.001f) const
vpImagePoint getCenter() const
float computeArcLengthInRoI(const vpRect &roi, const float &roundingTolerance=0.001f) const
unsigned int computePixelsInMask(const vpImage< bool > &mask) const
Count the number of pixels of the circle whose value in the mask is true.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
unsigned int getWidth() const
unsigned int getHeight() const
static float getAngleBetweenMinPiAndPi(const float &theta)
static bool equal(double x, double y, double threshold=0.001)
static float modulo(const float &value, const float &modulo)
Gives the rest of value divided by modulo when the quotient can only be an integer.
Defines a rectangle in the plane.
bool isInside(const vpImagePoint &ip) const
vpImagePoint getTopLeft() const