geometry.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <iostream>
  2. #ifdef HAS_OPENCV3
  3. #include <opencv2/core.hpp> //Any OPENCV3 code
  4. #else
  5. #include <opencv2/core/core.hpp> //Any Opencv2 code
  6. #endif
  7. using namespace cv;
  8. #include "geometry.h"
  9. #define likely(x) __builtin_expect(!!(x), 1)
  10. #define unlikely(x) __builtin_expect(!!(x), 0)
  11. double dist(Point a, Point b)
  12. {
  13. return cv::norm(a-b);
  14. }
  15. double inner_angle(Point a, Point middle, Point b)
  16. {
  17. Point v1 = a - middle;
  18. Point v2 = b - middle;
  19. double v1_length = dist(Point(0, 0), v1);
  20. double v2_length = dist(Point(0, 0), v2);
  21. return acos( (v1.x*v2.x + v1.y*v2.y) / (v1_length*v2_length) );
  22. }
  23. CoordinateSystem::CoordinateSystem(double angle, Point a)
  24. {
  25. theta = angle;
  26. origin = a;
  27. precompute();
  28. assert(map(a) == Point(0,0));
  29. assert(unmap(Point(0,0)) == a);
  30. }
  31. CoordinateSystem::CoordinateSystem(Point a, Point b)
  32. {
  33. theta = atan2(b.y-a.y, b.x-a.x);
  34. origin = a;
  35. precompute();
  36. assert(map(a) == Point(0,0));
  37. assert(unmap(Point(0,0)) == a);
  38. assert(map(b).y == 0);
  39. assert(map(b).x > 0);
  40. }
  41. void CoordinateSystem::precompute() {
  42. double costheta = cos(theta);
  43. double sintheta = sin(theta);
  44. R(0,0) = costheta;
  45. R(0,1) = -sintheta;
  46. R(1,0) = sintheta;
  47. R(1,1) = costheta;
  48. Rt(0,0) = costheta;
  49. Rt(0,1) = sintheta;
  50. Rt(1,0) = -sintheta;
  51. Rt(1,1) = costheta;
  52. }
  53. Point CoordinateSystem::map(Point tomap) {
  54. //that's the algorithm: res = Rt*(tomap - origin)
  55. cv::Vec<double,2> p_as_vector;
  56. Point p;
  57. p = tomap - origin;
  58. p_as_vector[0] = p.x;
  59. p_as_vector[1] = p.y;
  60. cv::Vec<double,2> res_as_vector = Rt*p_as_vector;
  61. return Point(res_as_vector);
  62. }
  63. Point CoordinateSystem::unmap(Point tounmap) {
  64. cv::Vec<double,2> q_as_vector;
  65. q_as_vector[0] = tounmap.x;
  66. q_as_vector[1] = tounmap.y;
  67. Point RQ = Point(R*q_as_vector);
  68. return Point(RQ + origin);
  69. }
  70. Point
  71. map_point(double theta, Point origin, Point tomap)
  72. {
  73. auto cs = CoordinateSystem(theta, origin);
  74. return cs.map(tomap);
  75. }
  76. Point
  77. unmap_point(double theta, Point origin, Point tounmap)
  78. {
  79. return CoordinateSystem(theta, origin).unmap(tounmap);
  80. }
  81. //that's the algorithm: res = Rt*(tomap - origin)
  82. cv::Vec<double,3>
  83. get_line(Point p, Point q)
  84. {
  85. cv::Vec<double,3> line; //the three positions are a,b,c as in: ax + by + c = 0
  86. Point vector = q-p;
  87. line(0) = - vector.y;
  88. line(1) = vector.x;
  89. line(2) = vector.y * p.x - vector.x * p.y;
  90. assert(is_in_line(line, p));
  91. assert(is_in_line(line, q));
  92. return line;
  93. }
  94. bool
  95. is_in_line(cv::Vec<double,3> line, Point p)
  96. {
  97. return line_value(line, p) == 0;
  98. }
  99. bool
  100. is_above_line(cv::Vec<double,3> line, Point p)
  101. {
  102. return line_value(line, p) > 0;
  103. }
  104. double line_value(cv::Vec<double,3> line, Point p)
  105. {
  106. return line(0)*p.x + line(1)*p.y + line(2);
  107. }
  108. cv::Point
  109. further_point_from_line(cv::Vec<double,3> line, std::vector<Point> points)
  110. {
  111. //distance = abs(a*p.x+b*p.y+c) / sqrt(a^2+b^2)
  112. Point further = points[0];
  113. double maxdist = -1;
  114. for(Point p: points)
  115. {
  116. double numerator = abs(line(0)*p.x + line(1)*p.y + line(2));
  117. if(numerator > maxdist) {
  118. maxdist = numerator;
  119. further = p;
  120. }
  121. }
  122. return further;
  123. }