-- CGMatrix.mesa
-- Last changed by Doug Wyatt, August 23, 1982 3:27 pm

DIRECTORY
GraphicsBasic USING [Transformation, Vec];

CGMatrix: CEDAR DEFINITIONS = { OPEN GraphicsBasic;

Ref: TYPE = REF Rep;
Rep: TYPE = RECORD[m: Transformation,
id: Id, trivial,rectangular: BOOLEAN, determinant: REAL];

-- The above represents a 3 by 3 matrix:
--   a b 0
--   c d 0
--   e f 1

Id: TYPE = LONG CARDINAL; -- unique identifier for the 2 by 2 submatrix [[a b] [c d]]

Error: ERROR[type: ErrorType];
ErrorType: TYPE = {singularMatrix, bug};

New: PROC RETURNS[Ref];
-- returns a new identity matrix

Make: PROC[Transformation] RETURNS[Ref];
-- creates a new matrix

IsTrivial: PROC[self: Ref] RETURNS[BOOLEAN] = INLINE { RETURN[self.trivial] };
-- returns TRUE iff [[a b] [c d]] = [[1 0] [0 1]]

Map: PROC[self: Ref, v: Vec] RETURNS[Vec] = INLINE {
RETURN[IF self.trivial THEN [v.x+self.m.e, v.y+self.m.f] ELSE MapH[self,v,1]] };

MapRel: PROC[self: Ref, v: Vec] RETURNS[Vec] = INLINE {
RETURN[IF self.trivial THEN v ELSE MapH[self,v,0]] };

MapH: PROC[self: Ref, v: Vec, h: [0..1]] RETURNS[Vec];

Inv: PROC[self: Ref, v: Vec] RETURNS[Vec] = INLINE { RETURN[
IF self.trivial THEN [v.x-self.m.e, v.y-self.m.f] ELSE InvH[self,v,1]] };

InvRel: PROC[self: Ref, v: Vec] RETURNS[Vec] = INLINE { RETURN[
IF self.trivial THEN v ELSE InvH[self,v,0]] };

InvH: PROC[self: Ref, v: Vec, h: [0..1]] RETURNS[Vec];

Translate: PROC[self: Ref, e,f: REAL] = INLINE {
v: Vec ← Map[self,[e,f]]; [self.m.e,self.m.f] ← v };
-- self ← [[1 0 0][0 1 0][e f 1]] x self

Concat: PROC[self: Ref, a,b,c,d: REAL];
-- self ← [[a b 0][c d 0][0 0 1]] x self

ConcatTransformation: PROC[self: Ref, m: Transformation];
-- self ← m x self

Invert: PROC[self: Ref];
-- self ← self^-1

Copy: PROC[self: Ref] RETURNS[Ref];
-- make a copy of the matrix

Assign: PROC[self: Ref, from: Ref] = INLINE { self^ ← from^ };
-- set the matrix equal to another matrix

GetTrans: PROC[self: Ref] RETURNS[Vec] = INLINE { RETURN[[self.m.e,self.m.f]] };
-- get the translation components

SetTrans: PROC[self: Ref, v: Vec] = INLINE { [self.m.e,self.m.f] ← v };
-- set the translation components

}.