All files R2Vector.ts

69.84% Statements 44/63
54.55% Branches 12/22
47.37% Functions 9/19
69.35% Lines 43/62
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 1751x 1x 1x               1x       4335x 4335x         1x 4335x     1x 4335x       1x             1x     1x       1x         1x       1x       1x       1x       1x                                                                       1x 845x               1x 3042x 3042x 1638x             1404x                     1x 1014x 1014x 546x   468x                             1x 3097x   321x   321x   841x   452x   321x   841x       1x 338x   1x       1x
import {S2Point} from "./S2Point";
import {Decimal} from './decimal';
import {S2} from "./S2";
 
/**
 * R2Vector represents a vector in the two-dimensional space. It defines the
 * basic geometrical operations for 2D vectors, e.g. cross product, addition,
 * norm, comparison etc.
 *
 */
export class R2Vector {
  private _x: decimal.Decimal;
  private _y: decimal.Decimal;
  constructor(_x:number|decimal.Decimal, _y:number|decimal.Decimal) {
    this._x = new Decimal(_x) as decimal.Decimal;
    this._y = new Decimal(_y) as decimal.Decimal;
    // this._x = new Decimal(_x) as decimal.Decimal;
    // this._y = new Decimal(_y) as decimal.Decimal;
  }
 
  get x() {
    return this._x;
  }
 
  get y() {
    return this._y;
  }
 
 
  public get(index:number):decimal.Decimal{
    if (index > 1) {
      throw new Error(`Index out fo bounds error ${index}`);
    }
    return index == 0 ? this._x : this._y;
  }
 
  static fromPointFace(p:S2Point, face:number): R2Vector {
    return p.toR2Vector(face);
  }
  public static  add(p1:R2Vector, p2:R2Vector):R2Vector {
    return new R2Vector(p1._x.plus(p2._x), p1._y.plus(p2._y));
  }
 
  public static mul(p:R2Vector, _m:number|decimal.Decimal):R2Vector {
    const m:decimal.Decimal = new Decimal(_m) as decimal.Decimal;
    return new R2Vector(m.times(p._x), m.times(p._y));
  }
 
  public norm2():decimal.Decimal {
    return this.x.pow(2).plus(this.y.pow(2));
  }
 
  public static dotProd(p1:R2Vector, p2:R2Vector):decimal.Decimal {
    return p1.x.times(p2.x).plus(p1.y.times(p2.y));
  }
 
  public dotProd(that:R2Vector):decimal.Decimal {
    return R2Vector.dotProd(this, that);
  }
 
  public crossProd(that:R2Vector):decimal.Decimal {
    return this.x.times(that.y).minus(this.y.times(that.x));
  }
 
  public lessThan(vb:R2Vector):boolean {
    if (this.x.lt(vb.x)) {
      return true;
    }
    if (vb.x.lt(this.x)) {
      return false;
    }
    if (this.y.lt(vb.y)) {
      return true;
    }
    return false;
  }
 
//
// @Override
// public boolean equals(Object that) {
//   if (!(that instanceof R2Vector)) {
//     return false;
//   }
//   R2Vector thatPoint = (R2Vector) that;
//   return this.x == thatPoint.x && this.y == thatPoint.y;
// }
 
// /**
//  * Calcualates hashcode based on stored coordinates. Since we want +0.0 and
//  * -0.0 to be treated the same, we ignore the sign of the coordinates.
//  */
// @Override
// public int hashCode() {
//   long value = 17;
//   value += 37 * value + Double.doubleToLongBits(Math.abs(x));
//   value += 37 * value + Double.doubleToLongBits(Math.abs(y));
//   return (int) (value ^ (value >>> 32));
// }
//
 
  public static fromSTVector(stVector: R2Vector):R2Vector{
    return new R2Vector(
      R2Vector.singleStTOUV(stVector.x),
      R2Vector.singleStTOUV(stVector.y)
    );
    
  }
 
  // from S2Projections.stToUV (QUADRATIC)
  public static singleStTOUV(_s:number|decimal.Decimal):decimal.Decimal {
    const s = S2.toDecimal(_s);
    if (s.gte(0)) {
      return S2.toDecimal(1)
              .dividedBy(3)
              .times(
                  s.plus(1).pow(2).minus(1)
              );
      // return (1 / 3.) * ((1 + s) * (1 + s) - 1);
    } else {
      return S2.toDecimal(1)
          .dividedBy(3)
          .times(
              S2.toDecimal(1)
                  .minus(S2.toDecimal(1).minus(s).pow(2)
                  )
          );
      // return (1 / 3.) * (1 - (1 - s) * (1 - s));
    }
 
  }
  public static singleUVToST(_x:number|decimal.Decimal) {
    const x = S2.toDecimal(_x);
    if (x.gte(0)) {
      return Decimal.sqrt(x.times(3).plus(1)).minus(1);
    } else {
      return S2.toDecimal(1)
          .minus(
              Decimal.sqrt(
                  S2.toDecimal(1).minus(x.times(3)
              )
              )
          )
    }
  }
 
  /**
   * To be used only if this vector is representing uv.
   * @param face
   * @returns {S2Point}
   */
  public toPoint(face:number) {
    switch (face) {
      case 0:
        return new S2Point(1, this.x, this.y);
      case 1:
        return new S2Point(this.x.neg(), 1, this.y);
      case 2:
        return new S2Point(this.x.neg(), this.y.neg(), 1);
      case 3:
        return new S2Point(-1, this.y.neg(), this.x.neg());
      case 4:
        return new S2Point(this.y, -1, this.x.neg());
      default:
        return new S2Point(this.y, this.x, -1);
    }
  }
 
  public toSt(which) {
    return which == 0?R2Vector.singleUVToST(this.x): R2Vector.singleUVToST(this.y);
  }
  public toString():string {
    return "(" + this.x.toString() + ", " + this.y.toString() + ")";
  }
 
}