geometry.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. (function() {
  2. if (typeof geo == 'undefined') {
  3. geo = {};
  4. }
  5. var tolerance = 1e-10;
  6. function eq(a, b) {
  7. return (Math.abs(a - b) < tolerance);
  8. }
  9. function gt(a, b) {
  10. return (a - b > -tolerance);
  11. }
  12. function lt(a, b) {
  13. return gt(b, a);
  14. }
  15. geo.eq = eq;
  16. geo.gt = gt;
  17. geo.lt = lt;
  18. geo.LineSegment = function(x1, y1, x2, y2) {
  19. this.x1 = x1;
  20. this.y1 = y1;
  21. this.x2 = x2;
  22. this.y2 = y2;
  23. // Ax + By = C
  24. this.a = y2 - y1;
  25. this.b = x1 - x2;
  26. this.c = x1 * this.a + y1 * this.b;
  27. if (eq(this.a, 0) && eq(this.b, 0)) {
  28. throw new Error(
  29. 'Cannot construct a LineSegment with two equal endpoints.');
  30. }
  31. };
  32. geo.LineSegment.prototype.intersect = function(that) {
  33. var d = (this.x1 - this.x2) * (that.y1 - that.y2) -
  34. (this.y1 - this.y2) * (that.x1 - that.x2);
  35. if (eq(d, 0)) {
  36. // The two lines are parallel or very close.
  37. return {
  38. x : NaN,
  39. y : NaN
  40. };
  41. }
  42. var t1 = this.x1 * this.y2 - this.y1 * this.x2,
  43. t2 = that.x1 * that.y2 - that.y1 * that.x2,
  44. x = (t1 * (that.x1 - that.x2) - t2 * (this.x1 - this.x2)) / d,
  45. y = (t1 * (that.y1 - that.y2) - t2 * (this.y1 - this.y2)) / d,
  46. in1 = (gt(x, Math.min(this.x1, this.x2)) && lt(x, Math.max(this.x1, this.x2)) &&
  47. gt(y, Math.min(this.y1, this.y2)) && lt(y, Math.max(this.y1, this.y2))),
  48. in2 = (gt(x, Math.min(that.x1, that.x2)) && lt(x, Math.max(that.x1, that.x2)) &&
  49. gt(y, Math.min(that.y1, that.y2)) && lt(y, Math.max(that.y1, that.y2)));
  50. return {
  51. x : x,
  52. y : y,
  53. in1 : in1,
  54. in2 : in2
  55. };
  56. };
  57. geo.LineSegment.prototype.x = function(y) {
  58. // x = (C - By) / a;
  59. if (this.a) {
  60. return (this.c - this.b * y) / this.a;
  61. } else {
  62. // a == 0 -> horizontal line
  63. return NaN;
  64. }
  65. };
  66. geo.LineSegment.prototype.y = function(x) {
  67. // y = (C - Ax) / b;
  68. if (this.b) {
  69. return (this.c - this.a * x) / this.b;
  70. } else {
  71. // b == 0 -> vertical line
  72. return NaN;
  73. }
  74. };
  75. geo.LineSegment.prototype.length = function() {
  76. return Math.sqrt(
  77. (this.y2 - this.y1) * (this.y2 - this.y1) +
  78. (this.x2 - this.x1) * (this.x2 - this.x1));
  79. };
  80. geo.LineSegment.prototype.offset = function(x, y) {
  81. return new geo.LineSegment(
  82. this.x1 + x, this.y1 + y,
  83. this.x2 + x, this.y2 + y);
  84. };
  85. })();