line.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #ifndef _LINE_HPP_
  2. #define _LINE_HPP_
  3. #include "point.h"
  4. NAMESPACE_POINT_BEGIN (NAMESPACE_POINT)
  5. struct line
  6. {
  7. double a,b,c;
  8. line()
  9. :a(0)
  10. ,b(0)
  11. ,c(0)
  12. {
  13. }
  14. line(double k,double b_)
  15. :a(k)
  16. ,b(-1)
  17. ,c(b_)
  18. {
  19. }
  20. line(double a_,double b_,double c_)
  21. :a(a_)
  22. ,b(b_)
  23. ,c(c_)
  24. {
  25. }
  26. line(const point&p0,const point&p1)
  27. {
  28. set(p0,p1);
  29. }
  30. void clear()
  31. {
  32. a=b=c=0;
  33. }
  34. bool empty() const
  35. {
  36. return a==0 && b==0 && c==0;
  37. }
  38. void set(const point&p0,const point&p1)
  39. {
  40. auto abc=p0.get_abc(p1);
  41. a=std::get<0>(abc);
  42. b=std::get<1>(abc);
  43. c=std::get<2>(abc);
  44. }
  45. std::string to_string()const
  46. {
  47. char buf[256];
  48. int len=sprintf(buf,"a=%.3lf,b=%.3lf,c=%.3lf",a,b,c);
  49. return std::string(buf,len);
  50. }
  51. double cos_k()const
  52. {
  53. if(b==0)
  54. return 0;
  55. double k=-a/b;
  56. return 1/sqrt(1+k*k);
  57. }
  58. double sin_k()const
  59. {
  60. if(b==0)
  61. return 1;
  62. double k=-a/b;
  63. return k/sqrt(1+k*k);
  64. }
  65. double arg()const
  66. {
  67. return acos(cos_k())*(sin_k()>0?1:-1);
  68. }
  69. static bool eq(double a,double b,double e)
  70. {
  71. return fabs(a-b)<e;
  72. }
  73. point projection(const point&lv)const
  74. {
  75. line pp(-b,a,b*lv.x-a*lv.y);
  76. return crossing(pp);
  77. }
  78. double dist(const point&v)const
  79. {
  80. return v.dist(projection(v));
  81. }
  82. bool parallel(const line&l2)const
  83. {
  84. return eq(cos_k(),l2.cos_k(),0.0001) && eq(sin_k(),l2.sin_k(),0.0001);
  85. }
  86. //返回交点
  87. point crossing(const line&l)const
  88. {
  89. if(parallel(l))
  90. return point();
  91. return point ( (c*l.b-l.c*b) /(l.a*b-a*l.b) ,
  92. (c*l.a-l.c*a) /(l.b*a-b*l.a) );
  93. }
  94. bool contain(const point&p,double e)const
  95. {
  96. return contain(p.x,p.y,e);
  97. }
  98. bool contain(double x,double y,double e)const
  99. {
  100. return fabs(a*x+b*y+c)<e;
  101. }
  102. };
  103. struct line_v:line//线段
  104. {
  105. std::array<point,2> v;
  106. line_v()
  107. {
  108. v[0].set(0,0);
  109. v[1].set(0,0);
  110. }
  111. line_v(const point&p0,const point&p1)
  112. :line(p0,p1)
  113. {
  114. v[0]=p0;
  115. v[1]=p1;
  116. }
  117. point&operator[](int i) { return v[i]; }
  118. const point&operator[](int i)const { return v[i]; }
  119. std::string to_string()const
  120. {
  121. char buf[256];
  122. int len=sprintf(buf,"[(%.3lf,%.3lf),(%.3lf,%.3lf)]",v[0].x,v[0].y,v[1].x,v[1].y);
  123. return std::string(buf,len);
  124. }
  125. point crossing(const line&l)const
  126. {
  127. point pt=line::crossing(l);
  128. return contain(pt)?pt:point();
  129. }
  130. point crossing(const line_v&l)const
  131. {
  132. point pt=line::crossing(l);
  133. return contain(pt)&&l.contain(pt)?pt:point();
  134. }
  135. bool is_same(const line_v&l,double e=0.0001)const
  136. {
  137. return line::contain(l[0],e) && line::contain(l[1],e);
  138. }
  139. point projection(const point&p)const
  140. {
  141. point pt=line::projection(p);
  142. return contain(pt)?pt:point();
  143. }
  144. line_v projection(const line_v&lv)const
  145. {
  146. std::array<point,2> o,t;
  147. o[0]=line::projection(lv[0]);
  148. o[1]=line::projection(lv[1]);
  149. if(o[1]<o[0]) o[0].swap(o[1]);
  150. t[0]=v[0];
  151. t[1]=v[1];
  152. if(t[1]<t[0]) t[0].swap(t[1]);
  153. if(o[1] < t[0] || t[1] < o[0])
  154. return line_v(point(0,0),point(0,0));
  155. return line_v(point::max_(t[0],o[0]),point::min_(t[1],o[1]));
  156. }
  157. bool empty()const
  158. {
  159. return length()<0.01;
  160. }
  161. double length()const
  162. {
  163. return v[0].dist(v[1]);
  164. }
  165. bool contain(const point&p,double e=0.0001)const
  166. {
  167. return contain(p.x,p.y,e);
  168. }
  169. bool contain(double x,double y,double e=0.0001)const
  170. {
  171. return eq(v[0].dist(v[1]),v[0].dist(x,y)+v[1].dist(x,y),0.0001);
  172. }
  173. double dist(const point&v)const
  174. {
  175. point p=projection(v);
  176. if(p.empty())
  177. return -1;
  178. return v.dist(p);
  179. }
  180. };
  181. NAMESPACE_POINT_END(NAMESPACE_POINT)
  182. #endif