/** * Multiplies the vector by a scalar value. * * @param d the value to multiply by * @return a new vector with the value v * d */ public Vector2D multiply(double d) { return create(x * d, y * d); }
/** * Divides the vector by a scalar value. * * @param d the value to divide by * @return a new vector with the value v / d */ public Vector2D divide(double d) { return create(x / d, y / d); }
public Vector2D subtract(Vector2D v) { return create(x - v.x, y - v.y); }
public Vector2D negate() { return create(-x , -y); }
public Vector2D add(Vector2D v) { return create(x + v.x, y + v.y); }
/** * Computes the weighted sum of this vector * with another vector, * with this vector contributing a fraction * of <tt>frac</tt> to the total. * <p> * In other words, * <pre> * sum = frac * this + (1 - frac) * v * </pre> * * @param v the vector to sum * @param frac the fraction of the total contributed by this vector * @return the weighted sum of the two vectors */ public Vector2D weightedSum(Vector2D v, double frac) { return create( frac * x + (1.0 - frac) * v.x, frac * y + (1.0 - frac) * v.y); }
public Vector2D rotate(double angle) { double cos = Math.cos(angle); double sin = Math.sin(angle); return create( x * cos - y * sin, x * sin + y * cos ); }
/** * Rotates a vector by a given number of quarter-circles (i.e. multiples of 90 * degrees or Pi/2 radians). A positive number rotates counter-clockwise, a * negative number rotates clockwise. Under this operation the magnitude of * the vector and the absolute values of the ordinates do not change, only * their sign and ordinate index. * * @param numQuarters * the number of quarter-circles to rotate by * @return the rotated vector. */ public Vector2D rotateByQuarterCircle(int numQuarters) { int nQuad = numQuarters % 4; if (numQuarters < 0 && nQuad != 0) { nQuad = nQuad + 4; } switch (nQuad) { case 0: return create(x, y); case 1: return create(-y, x); case 2: return create(-x, -y); case 3: return create(y, -x); } Assert.shouldNeverReachHere(); return null; }
public Vector2D normalize() { double length = length(); if (length > 0.0) return divide(length); return create(0.0, 0.0); }
/** * Returns an array of pts such that p0 - p[0] - [p1] is CW. * * @param p0 * @param p1 * @param p2 * @return */ private static Vector2D normalizedOffset(Coordinate p0, Coordinate p1, Coordinate p2) { Vector2D u1 = Vector2D.create(p0, p1).normalize(); Vector2D u2 = Vector2D.create(p0, p2).normalize(); Vector2D offset = u1.add(u2).normalize(); return offset; }
public void testIsParallel() throws Exception { assertTrue(Vector2D.create(0,1).isParallel(Vector2D.create(0,2))); assertTrue(Vector2D.create(1,1).isParallel(Vector2D.create(2,2))); assertTrue(Vector2D.create(-1,-1).isParallel(Vector2D.create(2,2))); assertTrue(! Vector2D.create(1,-1).isParallel(Vector2D.create(2,2))); }
private Coordinate displaceFromFlatCorner(Coordinate nearPt, Coordinate p1, Coordinate p2, double dist) { // compute perpendicular bisector of p1-p2 Vector2D bisecVec = Vector2D.create(p2, p1).rotateByQuarterCircle(1); Vector2D offset = bisecVec.normalize().multiply(dist); return offset.translate(vertexPt); } }
private Coordinate displaceFromCorner(Coordinate nearPt, Coordinate p1, Coordinate p2, double dist) { Coordinate[] corner = orientCorner(nearPt, p1, p2); // compute perpendicular bisector of p1-p2 Vector2D u1 = Vector2D.create(nearPt, corner[0]).normalize(); Vector2D u2 = Vector2D.create(nearPt, corner[1]).normalize(); double ang = u1.angle(u2); Vector2D innerBisec = u2.rotate(ang / 2); Vector2D offset = innerBisec.multiply(dist); if (! isInsideCorner(vertexPt, nearPt, corner[0], corner[1])) { offset = offset.multiply(-1); } return offset.translate(vertexPt); }
boolean isInsideCorner = isInsideCorner(vertexPt, nearPt, corner[0], corner[1]); Vector2D u1 = Vector2D.create(nearPt, corner[0]).normalize(); Vector2D u2 = Vector2D.create(nearPt, corner[1]).normalize(); double cornerAng = u1.angle(u2); Vector2D pointwiseDisplacement = Vector2D.create(nearPt, vertexPt).normalize(); double stretchAng = pointwiseDisplacement.angleTo(bisec); double stretchAngClamp = MathUtil.clamp(stretchAng, -maxAngToBisec, maxAngToBisec);
Vector2D v = Vector2D.create(Math.cos(angleRad), Math.sin(angleRad));
public void addSide(int level, Coordinate p0, Coordinate p1) { if (level == 0) addSegment(p0, p1); else { Vector2D base = Vector2D.create(p0, p1); Coordinate midPt = base.multiply(0.5).translate(p0); Vector2D heightVec = base.multiply(THIRD_HEIGHT); Vector2D offsetVec = heightVec.rotateByQuarterCircle(1); Coordinate offsetPt = offsetVec.translate(midPt); int n2 = level - 1; Coordinate thirdPt = base.multiply(ONE_THIRD).translate(p0); Coordinate twoThirdPt = base.multiply(TWO_THIRDS).translate(p0); // construct sides recursively addSide(n2, p0, thirdPt); addSide(n2, thirdPt, offsetPt); addSide(n2, offsetPt, twoThirdPt); addSide(n2, twoThirdPt, p1); } }