line.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #ifndef _LINE_HPP_
  2. #define _LINE_HPP_
  3. #include "point.h"
  4. struct line
  5. {
  6. double a,b,c;
  7. line()
  8. :a(0)
  9. ,b(0)
  10. ,c(0)
  11. {
  12. }
  13. line(double k,double b_)
  14. :a(k)
  15. ,b(-1)
  16. ,c(b_)
  17. {
  18. }
  19. line(double a_,double b_,double c_)
  20. :a(a_)
  21. ,b(b_)
  22. ,c(c_)
  23. {
  24. }
  25. line(const point&p0,const point&p1)
  26. {
  27. set(p0,p1);
  28. }
  29. void clear()
  30. {
  31. a=b=c=0;
  32. }
  33. bool empty() const
  34. {
  35. return a==0 && b==0 && c==0;
  36. }
  37. void set(const point&p0,const point&p1)
  38. {
  39. auto abc=p0.get_abc(p1);
  40. a=std::get<0>(abc);
  41. b=std::get<1>(abc);
  42. c=std::get<2>(abc);
  43. }
  44. std::string to_string()const
  45. {
  46. char buf[256];
  47. int len=sprintf(buf,"a=%.3lf,b=%.3lf,c=%.3lf",a,b,c);
  48. return std::string(buf,len);
  49. }
  50. double cos_k()const
  51. {
  52. if(b==0)
  53. return 0;
  54. double k=-a/b;
  55. return 1/sqrt(1+k*k);
  56. }
  57. double sin_k()const
  58. {
  59. if(b==0)
  60. return 1;
  61. double k=-a/b;
  62. return k/sqrt(1+k*k);
  63. }
  64. double arg()const
  65. {
  66. return acos(cos_k())*(sin_k()>0?1:-1);
  67. }
  68. static bool eq(double a,double b,double e)
  69. {
  70. return fabs(a-b)<e;
  71. }
  72. point projection(const point&lv)const
  73. {
  74. line pp(-b,a,b*lv.x-a*lv.y);
  75. return crossing(pp);
  76. }
  77. double dist(const point&v)const
  78. {
  79. return v.dist(projection(v));
  80. }
  81. bool parallel(const line&l2)const
  82. {
  83. return eq(cos_k(),l2.cos_k(),0.0001) && eq(sin_k(),l2.sin_k(),0.0001);
  84. }
  85. point crossing(const line&l)const
  86. {
  87. if(parallel(l))
  88. return point();
  89. return point ( (c*l.b-l.c*b) /(l.a*b-a*l.b) ,
  90. (c*l.a-l.c*a) /(l.b*a-b*l.a) );
  91. }
  92. bool contain(const point&p,double e)const
  93. {
  94. return contain(p.x,p.y,e);
  95. }
  96. bool contain(double x,double y,double e)const
  97. {
  98. return fabs(a*x+b*y+c)<e;
  99. }
  100. };
  101. struct line_v:line//线段
  102. {
  103. std::array<point,2> v;
  104. point angle;
  105. line_v()
  106. {
  107. v[0].set(0,0);
  108. v[1].set(0,0);
  109. }
  110. line_v(const point&p0,const point&p1)
  111. :line(p0,p1)
  112. {
  113. v[0]=p0;
  114. v[1]=p1;
  115. recalc();
  116. }
  117. line_v widen(double length) const
  118. {
  119. point pt1(v[0].x-length*cos(),v[0].y-length*sin());
  120. point pt2(v[1].x+length*cos(),v[1].y+length*sin());
  121. return line_v(pt1,pt2);
  122. }
  123. void swap_point()
  124. {
  125. point tmp=v[0];
  126. v[0]=v[1];
  127. v[1]=tmp;
  128. recalc();
  129. }
  130. void recalc()
  131. {
  132. double dx = v[1].x - v[0].x;
  133. double dy = v[1].y - v[0].y;
  134. double r = sqrt(dx*dx + dy*dy);
  135. double cos = dx/r;
  136. double sin = dy/r;
  137. angle = point(cos,sin);
  138. }
  139. void set_point(int i,const point&p)
  140. {
  141. v[i]=p;
  142. recalc();
  143. }
  144. double cos() const {return angle.x;}
  145. double sin() const {return angle.y;}
  146. point&operator[](int i) { return v[i]; }
  147. const point&operator[](int i)const { return v[i]; }
  148. std::string to_string()const
  149. {
  150. char buf[256];
  151. int len=sprintf(buf,"[(%.3lf,%.3lf),(%.3lf,%.3lf)]",v[0].x,v[0].y,v[1].x,v[1].y);
  152. return std::string(buf,len);
  153. }
  154. point crossing(const line&l)const
  155. {
  156. point pt=line::crossing(l);
  157. return contain(pt)?pt:point();
  158. }
  159. point crossing(const line_v&l)const
  160. {
  161. point pt=line::crossing(l);
  162. return contain(pt)&&l.contain(pt)?pt:point();
  163. }
  164. bool is_same(const line_v&l,double e=0.0001)const
  165. {
  166. return line::contain(l[0],e) && line::contain(l[1],e);
  167. }
  168. point projection(const point&p)const
  169. {
  170. point pt=line::projection(p);
  171. return contain(pt)?pt:point();
  172. }
  173. line_v projection(const line_v&lv)const
  174. {
  175. std::array<point,2> o,t;
  176. o[0]=line::projection(lv[0]);
  177. o[1]=line::projection(lv[1]);
  178. if(o[1]<o[0]) o[0].swap(o[1]);
  179. t[0]=v[0];
  180. t[1]=v[1];
  181. if(t[1]<t[0]) t[0].swap(t[1]);
  182. if(o[1] < t[0] || t[1] < o[0])
  183. return line_v(point(0,0),point(0,0));
  184. return line_v(point::max(t[0],o[0]),point::min(t[1],o[1]));
  185. }
  186. bool empty()const
  187. {
  188. return length()<0.01;
  189. }
  190. double length()const
  191. {
  192. return v[0].dist(v[1]);
  193. }
  194. bool contain(const point&p,double e=0.0001)const
  195. {
  196. return contain(p.x,p.y,e);
  197. }
  198. bool contain(double x,double y,double e=0.0001)const
  199. {
  200. return eq(v[0].dist(v[1]),v[0].dist(x,y)+v[1].dist(x,y),e);
  201. }
  202. double dist(const point&v)const
  203. {
  204. point p=projection(v);
  205. if(p.empty())
  206. return -1;
  207. return v.dist(p);
  208. }
  209. const line &as_line()const
  210. {
  211. return *this;
  212. }
  213. };
  214. struct line_r:line
  215. {
  216. std::array<point,2> v;
  217. line_r()
  218. {
  219. v[0].set(0,0);
  220. v[1].set(0,0);
  221. }
  222. line_r(const point&p0,const point&p1)
  223. :line(p0,p1)
  224. {
  225. v[0]=p0;
  226. v[1]=p1;
  227. }
  228. point&operator[](int i) { return v[i]; }
  229. const point&operator[](int i)const { return v[i]; }
  230. std::string to_string()const
  231. {
  232. char buf[256];
  233. int len=sprintf(buf,"[(%.3lf,%.3lf),(%.3lf,%.3lf)]",v[0].x,v[0].y,v[1].x,v[1].y);
  234. return std::string(buf,len);
  235. }
  236. point crossing(const line&l)const
  237. {
  238. point pt=line::crossing(l);
  239. return contain(pt)?pt:point();
  240. }
  241. point crossing(const line_r&l)const
  242. {
  243. point pt=line::crossing(l);
  244. return contain(pt)&&l.contain(pt)?pt:point();
  245. }
  246. point projection(const point&p)const
  247. {
  248. point pt=line::projection(p);
  249. return contain(pt)?pt:point();
  250. }
  251. bool invalid()const
  252. {
  253. return v[0].dist(v[1])<0.01;
  254. }
  255. bool contain(const point&p,double e=0.0001)const
  256. {
  257. return contain(p.x,p.y,e);
  258. }
  259. bool is_same_direction(const line_r &lr)
  260. {
  261. bool f=false;
  262. if(v[0]==lr[0]){
  263. if(contain(lr[1]))
  264. f=true;
  265. }
  266. else{
  267. f=(contain(lr[0]) && contain(lr[1]) && !lr.contain(v[0]))|| (lr.contain(v[0]) && lr.contain(v[1]) && !contain(lr[0]));
  268. }
  269. return f;
  270. }
  271. bool contain(double x,double y,double e=0.0001)const
  272. {
  273. return line::contain(x,y,e)?in_contain(x,y,e)||out_contain(x,y,e):false;
  274. }
  275. bool in_contain(const point &p,double e=0.0001)
  276. {
  277. return in_contain(p.x,p.y,e);
  278. }
  279. bool in_contain(double x,double y,double e=0.0001)const
  280. {
  281. return line::contain(x,y,e)?eq(v[0].dist(v[1]),v[0].dist(x,y)+v[1].dist(x,y),e):false;
  282. }
  283. bool out_contain(double x,double y,double e=0.0001)const
  284. {
  285. return line::contain(x,y,e)?(v[0].dist(x,y)>=v[1].dist(x,y)):false;
  286. }
  287. double dist(const point&v)const
  288. {
  289. point p=projection(v);
  290. if(p.empty())
  291. return -1;
  292. return v.dist(p);
  293. }
  294. const line &as_line()const
  295. {
  296. return *this;
  297. }
  298. };
  299. #endif