-- MapperImpl.mesa -- Last changed by Doug Wyatt, September 22, 1980 5:31 PM DIRECTORY Mapper, Vector USING [Add, Sub, Det], Memory USING [NewZone]; MapperImpl: PROGRAM IMPORTS Memory,Mapper,Vector EXPORTS Mapper SHARES Mapper = { OPEN Mapper; zone: UNCOUNTED ZONE = Memory.NewZone["MapperImpl"]; Data: PUBLIC TYPE = RECORD [ m: Matrix, -- transformation matrix t: Vec, -- translation vector det: REAL, -- determinant of m ortho: BOOLEAN -- orthogonal flag ]; DataRef: TYPE = LONG POINTER TO Data; tProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ Map: TMap, InverseMap: TInv, Translate: CTranslate, Concat: TConcat, Ortho: COrtho, Read: CRead, Copy: CCopy, Free: CFree ]]; aProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ Map: AMap, InverseMap: AInv, Translate: CTranslate, Concat: AConcat, Ortho: COrtho, Read: CRead, Copy: CCopy, Free: CFree ]]; sProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ Map: SMap, InverseMap: SInv, Translate: CTranslate, Concat: SConcat, Ortho: COrtho, Read: CRead, Copy: CCopy, Free: CFree ]]; rProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ Map: RMap, InverseMap: RInv, Translate: CTranslate, Concat: RConcat, Ortho: COrtho, Read: CRead, Copy: CCopy, Free: CFree ]]; eProcs: LONG POINTER TO READONLY Procs = zone.NEW[Procs = [ Map: RMap, InverseMap: EInv, Translate: CTranslate, Concat: RConcat, Ortho: COrtho, Read: CRead, Copy: CCopy, Free: CFree ]]; -- Procedure for creating a Mapper object NewMapper: PUBLIC PROCEDURE[] RETURNS[Handle] = { d: DataRef = zone.NEW[Data _ [ m: [1,0,0,1], t: [0,0], det: 1, ortho: TRUE ]]; RETURN[zone.NEW[Object _ [procs: tProcs, data: d]]]; }; -- Operations on a Mapper object -- Translation only TMap: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; IF t THEN v^_Vector.Add[v^,d.t]; }; -- Alto screen transformation: scaling by [1,-1] AMap: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=[x: v.x, y: -v.y]; v^_(IF t THEN Vector.Add[w,d.t] ELSE w); }; -- Scaling, but no rotation SMap: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=[x: d.m.a11*v.x, y: d.m.a22*v.y]; v^_(IF t THEN Vector.Add[w,d.t] ELSE w); }; -- Rotation and more.. the most general transformation RMap: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=[x: d.m.a11*v.x+d.m.a12*v.y, y: d.m.a21*v.x+d.m.a22*v.y]; v^_(IF t THEN Vector.Add[w,d.t] ELSE w); }; MapperError: PUBLIC ERROR = CODE; TInv: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; IF t THEN v^_Vector.Sub[v^,d.t]; }; AInv: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=IF t THEN Vector.Sub[v^,d.t] ELSE v^; v^_[x: w.x, y: -w.y]; }; SInv: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=IF t THEN Vector.Sub[v^,d.t] ELSE v^; v^_[x: w.x/d.m.a11, y: w.y/d.m.a22]; }; RInv: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { d: DataRef=self.data; w: Vec=IF t THEN Vector.Sub[v^,d.t] ELSE v^; v^_[ x: (d.m.a22*w.x-d.m.a12*w.y)/d.det, y: (d.m.a11*w.y-d.m.a21*w.x)/d.det ]; }; EInv: PROCEDURE[self: Handle, v: POINTER TO Vec, t: BOOLEAN] = { ERROR MapperError; }; Install: PROCEDURE[self: Handle] = { d: DataRef=self.data; d.det_Vector.Det[d.m]; -- compute new determinant SELECT TRUE FROM (d.det=0) => { self.procs_eProcs; d.ortho_FALSE }; (d.m.a12#0 OR d.m.a21#0) => { self.procs_rProcs; d.ortho_FALSE }; (d.m.a11=1 AND d.m.a22=-1) => { self.procs_aProcs; d.ortho_TRUE }; (d.m.a11#1 OR d.m.a22#1) => { self.procs_sProcs; d.ortho_TRUE }; ENDCASE => { self.procs_tProcs; d.ortho_TRUE }; }; TConcat: PROCEDURE[self: Handle, m: POINTER TO Matrix] = { d: DataRef=self.data; d.m_m^; Install[self]; }; AConcat: PROCEDURE[self: Handle, m: POINTER TO Matrix] = { d: DataRef=self.data; d.m_[a11: m.a11, a12: m.a12, a21: -m.a21, a22: -m.a22]; Install[self]; }; SConcat: PROCEDURE[self: Handle, m: POINTER TO Matrix] = { d: DataRef=self.data; mm: Matrix_[ a11: d.m.a11*m.a11, a12: d.m.a11*m.a12, a21: d.m.a22*m.a21, a22: d.m.a22*m.a22 ]; d.m_mm; Install[self]; }; RConcat: PROCEDURE[self: Handle, m: POINTER TO Matrix] = { d: DataRef=self.data; mm: Matrix_[ a11: d.m.a11*m.a11 + d.m.a12*m.a21, a12: d.m.a11*m.a12 + d.m.a12*m.a22, a21: d.m.a21*m.a11 + d.m.a22*m.a21, a22: d.m.a21*m.a12 + d.m.a22*m.a22 ]; d.m_mm; Install[self]; }; CTranslate: PROCEDURE[self: Handle, v: POINTER TO Vec] = { d: DataRef=self.data; d.t_Map[self,v^]; }; COrtho: PROCEDURE[self: Handle] RETURNS[BOOLEAN] = { d: DataRef=self.data; RETURN[d.ortho]; }; CRead: PROCEDURE[self: Handle, m: POINTER TO Matrix, v: POINTER TO Vec] = { d: DataRef=self.data; m^_d.m; v^_d.t; }; CCopy: PROCEDURE[self: Handle] RETURNS[Handle] = { d: DataRef=self.data; dd: DataRef = zone.NEW[Data _ d^]; RETURN[zone.NEW[Object _ [procs: self.procs, data: dd]]]; }; CFree: PROCEDURE[selfPtr: LONG POINTER TO Handle] = { self: Handle_selfPtr^; d: DataRef_self.data; selfPtr^_NIL; zone.FREE[@d]; zone.FREE[@self]; }; }.(670)