object Vec {
val X_AXIS = Vec(1,0)
val Y_AXIS = Vec(0,1)
}
case class Vec(x: Double, y: Double) {
def dotProduct(v: Vec) = x*v.x+y*v.y
def crossProduct(v: Vec) = x*v.y-y*v.x;
def length = math.sqrt(x*x+y*y)
def rotate(theta: Double) = {
val sin = math.sin(theta);
val cos = math.cos(theta);
Vec(x*cos-y*sin,
x*sin+y*cos);
}
def rotate90 = Vec(-y, x)
def +(v: Vec) = Vec(x+v.x, y+v.y)
def -(v: Vec) = Vec(x-v.x, y-v.y)
def *(d: Double) = Vec(x*d, y*d)
def /(d: Double) = Vec(x/d, y/d)
def unary_- = Vec(-x, -y)
override def toString = f"Vec($x%.3f, $y%.3f)"
}
object Matrix {
def rotationMatrix(theta: Double) = {
val v = Vec.X_AXIS.rotate(theta)
Matrix(v, v.rotate90)
}
def apply(a: Double, b: Double,
c: Double, d: Double): Matrix = Matrix(Vec(a,c), Vec(b,d))
}
case class Matrix(c1: Vec, c2: Vec) {
def *(v: Vec) = c1*v.x + c2*v.y
def *(d: Double) = Matrix(c1*d, c2*d)
def determinant = c1.crossProduct(c2)
def inverse = Matrix( c2.y, -c2.x,
-c1.y, c1.x) * (1/determinant)
override def toString = f"Matrix(${c1.x}%.3f, ${c2.x}%.3f\n" +
f" ${c1.y}%.3f, ${c2.y}%.3f)"
}
case class CoordinateSystem(origin: Vec, xAxis: Vec, yAxis: Vec) {
val matrix = Matrix(xAxis, yAxis)
val inverseMatrix = matrix.inverse
def translate(v: Vec) = matrix*v + origin
def translateBack(v: Vec) = inverseMatrix*(v-origin)
}
val cs = CoordinateSystem(Vec(500,100),
Vec(1,1),
Vec(-1,1))
val v = Vec(2,3)
val v2 = cs.translate(v)
println(v2)
println(cs.translateBack(v2))