      1 //= require 'point.class'
      2
      3 (function() {
      4
      5   /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */
      6
      7   var global = this,
      8       fabric = global.fabric || (global.fabric = { });
      9
     10   if (fabric.Intersection) {
     11     fabric.warn('fabric.Intersection is already defined');
     12     return;
     13   }
     14
     15   /**
     16    * @class Intersection
     17    * @memberOf fabric
     18    */
     19   function Intersection(status) {
     20     if (arguments.length > 0) {
     21       this.init(status);
     22     }
     23   }
     24
     25   fabric.Intersection = Intersection;
     26
     27   fabric.Intersection.prototype = /** @scope fabric.Intersection.prototype */ {
     28
     29     /**
     30      * @method init
     31      * @param {String} status
     32      */
     33     init: function (status) {
     34       this.status = status;
     35       this.points = [];
     36     },
     37
     38     /**
     39      * @method appendPoint
     40      * @param {String} status
     41      */
     42     appendPoint: function (point) {
     43       this.points.push(point);
     44     },
     45
     46     /**
     47      * @method appendPoints
     48      * @param {String} status
     49      */
     50     appendPoints: function (points) {
     51       this.points = this.points.concat(points);
     52     }
     53   };
     54
     55   /**
     56    * @static
     57    * @method intersectLineLine
     58    */
     59   fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {
     60     var result,
     61         ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
     62         ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
     63         u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
     64     if (u_b != 0) {
     65       var ua = ua_t / u_b,
     66           ub = ub_t / u_b;
     67       if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
     68         result = new Intersection("Intersection");
     69         result.points.push(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));
     70       }
     71       else {
     72         result = new Intersection("No Intersection");
     73       }
     74     }
     75     else {
     76       if (ua_t == 0 || ub_t == 0) {
     77         result = new Intersection("Coincident");
     78       }
     79       else {
     80         result = new Intersection("Parallel");
     81       }
     82     }
     83     return result;
     84   };
     85
     86   /**
     87    * @method intersectLinePolygon
     88    */
     89   fabric.Intersection.intersectLinePolygon = function(a1,a2,points){
     90     var result = new Intersection("No Intersection"),
     91         length = points.length;
     92
     93     for (var i = 0; i < length; i++) {
     94       var b1 = points[i],
     95           b2 = points[(i+1) % length],
     96           inter = Intersection.intersectLineLine(a1, a2, b1, b2);
     97
     98       result.appendPoints(inter.points);
     99     }
    100     if (result.points.length > 0) {
    101       result.status = "Intersection";
    102     }
    103     return result;
    104   };
    105
    106   /**
    107    * @method intersectPolygonPolygon
    108    */
    109   fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {
    110     var result = new Intersection("No Intersection"),
    111         length = points1.length;
    112
    113     for (var i = 0; i < length; i++) {
    114       var a1 = points1[i],
    115           a2 = points1[(i+1) % length],
    116           inter = Intersection.intersectLinePolygon(a1, a2, points2);
    117
    118       result.appendPoints(inter.points);
    119     }
    120     if (result.points.length > 0) {
    121       result.status = "Intersection";
    122     }
    123     return result;
    124   };
    125
    126   /**
    127    * @method intersectPolygonRectangle
    128    */
    129   fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {
    130     var min = r1.min(r2),
    131         max = r1.max(r2),
    132         topRight = new fabric.Point(max.x, min.y),
    133         bottomLeft = new fabric.Point(min.x, max.y),
    134         inter1 = Intersection.intersectLinePolygon(min, topRight, points),
    135         inter2 = Intersection.intersectLinePolygon(topRight, max, points),
    136         inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),
    137         inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),
    138         result = new Intersection("No Intersection");
    139
    140     result.appendPoints(inter1.points);
    141     result.appendPoints(inter2.points);
    142     result.appendPoints(inter3.points);
    143     result.appendPoints(inter4.points);
    144     if (result.points.length > 0) {
    145       result.status="Intersection";
    146     }
    147     return result;
    148   };
    149
    150 })();