line.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. int intersectLine2Line2(Line2 a, Line2 b) {
  2. vec2 s1 = vSub(a.end, a.start);
  3. vec2 s2 = vSub(b.end, b.start);
  4. float det = vCross2(s1, s2);
  5. if(fabsf(det) < 1e-5f) {
  6. return C3DLAS_PARALLEL;
  7. }
  8. float invdet = 1.f / det;
  9. float x02 = a.start.x - b.start.x;
  10. float y02 = a.start.y - b.start.y;
  11. float s = (s1.x * y02 - s1.y * x02) * invdet;
  12. if(s >= 0.f && s <= 1.f) {
  13. float t = (s2.x * y02 - s2.y * x02) * invdet;
  14. if(t >= 0.f && t <= 1.f) {
  15. return C3DLAS_INTERSECT;
  16. }
  17. }
  18. return C3DLAS_DISJOINT;
  19. }
  20. float distLine2Line2(Line2 a, Line2 b) {
  21. vec2 s1 = vSub(a.end, a.start);
  22. vec2 s2 = vSub(b.end, b.start);
  23. float det = vCross2(s1, s2);
  24. if(fabsf(det) < 1e-5f) { // parallel lines
  25. if(s1.x == 0) return fabs(a.start.y - b.start.y); // vertical lines
  26. float m = s1.y / s1.x;
  27. float c1 = a.start.y - (m * a.start.x);
  28. float c2 = b.start.y - (m * b.start.x);
  29. return fabs((c1 - c2) / sqrt(1 + m * m));
  30. }
  31. float invdet = 1.f / det;
  32. float x02 = a.start.x - b.start.x;
  33. float y02 = a.start.y - b.start.y;
  34. float s = (s1.x * y02 - s1.y * x02) * invdet;
  35. float t = (s2.x * y02 - s2.y * x02) * invdet;
  36. if(s >= 0.f && s <= 1.f && t >= 0.f && t <= 1.f) {
  37. return 0; // intersecting lines
  38. }
  39. // one or both of the ends is the closest point on its line
  40. s = fclamp(s, 0, 1);
  41. t = fclamp(t, 0, 1);
  42. vec2 pa = vLerp(a.start, a.end, s);
  43. vec2 pb = vLerp(b.start, b.end, t);
  44. return vDist(pa, pb);
  45. }
  46. // Quad *must* be a rectangle
  47. float distLine2Rect2(Line2 a, Quad2 q) {
  48. // check the lines around the outside
  49. float d[4];
  50. for(int i = 0; i < 4; i++) {
  51. d[i] = distLine2Line2(a, (Line2){q.v[i], q.v[(i + 1) % 4]});
  52. if(d[i] == 0) return 0;
  53. }
  54. // check if the line is entirely inside the rectangle,
  55. // if one point (and therefore both points) is inside the quad
  56. vec2 ab = vSub(q.v[1], q.v[0]);
  57. vec2 am = vSub(a.start, q.v[0]);
  58. vec2 bc = vSub(q.v[2], q.v[1]);
  59. vec2 bm = vSub(a.start, q.v[1]);
  60. float dabam = vDot(ab, am);
  61. if(dabam <= 0) {
  62. float dabab = vDot(ab, ab);
  63. if(dabam <= dabab) {
  64. float dbcbm = vDot(bc, bm);
  65. if(0 <= dbcbm) {
  66. float dbcbc = vDot(bc, bc);
  67. if(dbcbm <= dbcbc) return 0;
  68. }
  69. }
  70. }
  71. // the line is outside; one of the corners is closest, find which one
  72. return MIN(MIN(d[0], d[1]), MIN(d[2], d[3]));
  73. }
  74. // Quad *must* be a rectangle
  75. int intersectLine2Rect2(Line2 a, Quad2 q) {
  76. // check if it intersects the boundaries
  77. if(intersectLine2Line2(a, (Line2){q.v[0], q.v[1]}) == C3DLAS_INTERSECT) return C3DLAS_INTERSECT;
  78. if(intersectLine2Line2(a, (Line2){q.v[1], q.v[2]}) == C3DLAS_INTERSECT) return C3DLAS_INTERSECT;
  79. if(intersectLine2Line2(a, (Line2){q.v[2], q.v[3]}) == C3DLAS_INTERSECT) return C3DLAS_INTERSECT;
  80. if(intersectLine2Line2(a, (Line2){q.v[3], q.v[0]}) == C3DLAS_INTERSECT) return C3DLAS_INTERSECT;
  81. // check if one point (and therefore both points) is inside the quad
  82. vec2 ab = vSub(q.v[1], q.v[0]);
  83. vec2 bc = vSub(q.v[2], q.v[1]);
  84. vec2 am = vSub(a.start, q.v[0]);
  85. vec2 bm = vSub(a.start, q.v[1]);
  86. float dabam = vDot(ab, am);
  87. float dbcbm = vDot(bc, bm);
  88. float dabab = vDot(ab, ab);
  89. float dbcbc = vDot(bc, bc);
  90. if(0 <= dabam && dabam <= dabab && 0 <= dbcbm && dbcbm <= dbcbc) return C3DLAS_INTERSECT;
  91. return C3DLAS_DISJOINT;
  92. }