function Plane() {
  this.corner = new Array();
  this.a = 0;
  this.b = 0;
  this.c = 0;
  this.d = 0;
  
//  1---2 corners
//  |   |
//  4---3
  this.init = 
    function(x0, y0, x1, y1, z) {
      this.corner[1] = new Point3D();
      this.corner[1].x = x0;
      this.corner[1].y = y0;
      this.corner[1].z = z;
                
      this.corner[2] = new Point3D();
      this.corner[2].x = x1;
      this.corner[2].y = y1;
      this.corner[2].z = z;

      this.corner[3] = new Point3D();
      this.corner[3].x = x1;
      this.corner[3].y = y1;
      this.corner[3].z = 0;

      this.corner[4] = new Point3D();
      this.corner[4].x = x0;
      this.corner[4].y = y0;
      this.corner[4].z = 0;

      this.findCoefficients();
    }
    
  this.findCoefficients = 
    function() {
      this.a = this.corner[1].y * (this.corner[2].z - this.corner[3].z) +
               this.corner[2].y * (this.corner[3].z - this.corner[1].z) +
               this.corner[3].y * (this.corner[1].z - this.corner[2].z);
              
      this.b = this.corner[1].z * (this.corner[2].x - this.corner[3].x) + 
               this.corner[2].z * (this.corner[3].x - this.corner[1].x) +
               this.corner[3].z * (this.corner[1].x - this.corner[2].x);
               
      this.c = this.corner[1].x * (this.corner[2].y - this.corner[3].y) +
               this.corner[2].x * (this.corner[3].y - this.corner[1].y) +
               this.corner[3].x * (this.corner[1].y - this.corner[2].y);
               
      this.d = -this.corner[1].x * (this.corner[2].y * this.corner[3].z - this.corner[3].y * this.corner[2].z) -
                this.corner[2].x * (this.corner[3].y * this.corner[1].z - this.corner[1].y * this.corner[3].z) -
                this.corner[3].x * (this.corner[1].y * this.corner[2].z - this.corner[2].y * this.corner[1].z);
    }
    
  this.containsPoint =
    function(pt) {
      var a1, a2, a3, a4;
  
      a1 = angleBetween3DPoints(this.corner[1], pt, this.corner[2]);
      a2 = angleBetween3DPoints(this.corner[2], pt, this.corner[3]);
      a3 = angleBetween3DPoints(this.corner[3], pt, this.corner[4]);
      a4 = angleBetween3DPoints(this.corner[4], pt, this.corner[1]);
  
      var result = Math.abs(a1+a2+a3+a4-(2 * Math.PI))
  
      return (result < 0.01);
    }  

  this.intersectedByLineBetweenPoints =
    function(p1, p2) {
      var iPoint = new Point3D();
      var e,f,g,t;
      var denom;
      var length;
  
// The line (L) is defined by the 2 points as follows :
// L:  X=P1.X+(P2.X-P1.X)*T,Y=P1.Y+(P2.Y-P1.Y)*T,Z=P1.Z+(P2.Z-P1.Z)*T
// or  X=P1.X+E*T,Y=P1.Y+F*T,Z=P1.Z+G*T

// find the E,F,G multipliers for the "T" parameter
      e = p2.x - p1.x;
      f = p2.y - p1.y; 
      g = p2.z - p1.z;

// solve for T...
      denom = this.a*e + this.b*f + this.c*g;
   
      if (denom == 0) return false;
     
      t = -(this.d + (this.a * p1.x) + (this.b * p1.y) + (this.c * p1.z)) / denom;

// plug T into the line equation to find the X,Y,Z intersection point
      iPoint.x = p1.x + (e * t);
      iPoint.y = p1.y + (f * t);
      iPoint.z = p1.z + (g * t);

// make sure the intersection point lies on our finite line
      length = p1.distanceTo(p2);
   
      var di1 = p1.distanceTo(iPoint);
      var di2 = p2.distanceTo(iPoint);

//p1.show('point #1');
//p2.show('point #2');
//log('e = ' + e + ' f = ' + f + ' g = ' + g + ' t = ' + t);
//log('denom = ' + denom + ' length = ' + length);
//iPoint.show('IPoint');
//log('di1 = ' + di1 + ' di2 = ' + di2);

      if (di1 < length) {
        var di2 = p2.distanceTo(iPoint);
        return ( (di2 < length) && this.containsPoint(iPoint) );
      }
      return false;
    }  
    
 this.intersected =
    function(p1, p2, iPoint) {
      var e,f,g,t;
      var denom;
      var length;
  
// The line (L) is defined by the 2 points as follows :
// L:  X=P1.X+(P2.X-P1.X)*T,Y=P1.Y+(P2.Y-P1.Y)*T,Z=P1.Z+(P2.Z-P1.Z)*T
// or  X=P1.X+E*T,Y=P1.Y+F*T,Z=P1.Z+G*T

// find the E,F,G multipliers for the "T" parameter
      e = p2.x - p1.x;
      f = p2.y - p1.y; 
      g = p2.z - p1.z;

// solve for T...
      denom = this.a*e + this.b*f + this.c*g;
   
      if (denom == 0) return false;
     
      t = -(this.d + (this.a * p1.x) + (this.b * p1.y) + (this.c * p1.z)) / denom;

// plug T into the line equation to find the X,Y,Z intersection point
      iPoint.x = p1.x + (e * t);
      iPoint.y = p1.y + (f * t);
      iPoint.z = p1.z + (g * t);

// make sure the intersection point lies on our finite line
      length = p1.distanceTo(p2);
   
      var di1 = p1.distanceTo(iPoint);
      var di2 = p2.distanceTo(iPoint);

//p1.show('point #1');
//p2.show('point #2');
//log('e = ' + e + ' f = ' + f + ' g = ' + g + ' t = ' + t);
//log('denom = ' + denom + ' length = ' + length);
//iPoint.show('IPoint');
//log('di1 = ' + di1 + ' di2 = ' + di2);

      if (di1 < length) {
        var di2 = p2.distanceTo(iPoint);
        return ( (di2 < length) && this.containsPoint(iPoint) );
      }
      return false;
    }  
    
    
  this.show = 
    function() {
      this.corner[1].show('point #1');
      this.corner[2].show('point #2');
      this.corner[3].show('point #3');
      this.corner[4].show('point #4');
      log('a = ' + this.a + ' b = ' + this.b + ' c = ' + this.c + ' d = ' + this.d);
    }
}