<> <> <> <> <> <> <> <> DIRECTORY D2Basic USING [Number, Pos, Rect]; CStitching: CEDAR DEFINITIONS = BEGIN <<-- Types.>> Number: TYPE = D2Basic.Number; Pos: TYPE = D2Basic.Pos; Rect: TYPE = D2Basic.Rect; <<-- WARNING: Conventions are different from D2Basic and ChipNDale:>> <<-- In CornerStitching, lower left border is inclusive; upper right border is exclusive.>> <<-- (In original D2Basic all borders are inclusive).>> all: Rect = [Number.FIRST, Number.FIRST, Number.LAST, Number.LAST]; Tile: TYPE = REF --READONLY-- TileRec; TileRec: TYPE = RECORD [ --all fields readonly eN, sW: Tile _ NIL, nE, wS: LONG POINTER TO TileRec _ NIL, pos: Pos, value: REF _ NIL -- NIL for space tiles ]; <<-- Tiles are recollected whenever they are not part of a tesselation! dont keep on to tiles. >> <<-- Corner stitching with ref's is too circular for the current Cedar safestorage, >> <<-- therefore two stitches are made pointers (idea of Mark Brown). >> <<-- eN... eastern-most neighbour to the North; capitalization enlightens asymetry)>> <<-- pos: lower left corner>> <<>> Tesselation: TYPE = REF TesselationRec; TesselationRec: TYPE = RECORD [ --do never use NEW state: State,--readonly, not all implementations use this field immute: PRIVATE BOOL _ FALSE, current, southEast: PRIVATE Tile _, --readonly tileCount: PRIVATE INT _ 1, --readonly stopFlag: REF BOOL, data: REF ]; <<-- use only NewTesselation to create Tesselations (Finalization!)>> <<-- data: reserved for clients>> <<-- stopFlag: reserved for clients>> <<>> State: TYPE = RECORD [ --readonly r: Rect_all, yf: Number_LAST[Number], --fathers limitting y ys: Number_LAST[Number] --lowest sons lowest y ]; <<>> <<-- All procedures sharing a Tesselation must be synchrounized by caller; >> <<-- CStitching itself does not monitor clients (even if using the same Tesselation). >> <<-- But synchrounization errors can propagate to unrelated Tesselation.>> <<>> <<>> <<-- Worlds.>> NewTesselation: PROC [data: REF _ NIL, stopFlag: REF BOOL _ NIL] RETURNS [Tesselation]; <<--creates a new Tesselation>> ResetTesselation: PROC [plane: Tesselation]; <<--returns the tile memory; Tesselation is ready for fresh usage>> DumpCache: PROC; <<--returns cached memory used global for Tiles of all Tesselations>> <<>> <<>> <<-- Modifying.>> ChangeRect: PROC [plane: Tesselation, rect: Rect, new: REF _ NIL]; <<--change the rect having new as tile value>> <<--beware: rect must lie completely in the changeable area (even for identity changes)>> ChangeTile: PROC [plane: Tesselation, tile: Tile, new: REF _ NIL]; <<--change a tile >> <<--beware: tile must lie completely in the changeable area (even for identity changes) >> ChangeEnumerateArea: PROC [plane: Tesselation, rect: Rect, eachRect: RectProc, data: REF _ NIL, skip: REF _]; <<--For each rectangle in rect (with value # skip) call "eachRect"; (rect must be changeable)>> <<--eachRect is must not change any point outside its rect area.>> <<--outside eachRect's rect the maximal size properties dont hold while the enumeration.>> RectProc: TYPE = PROC [plane: Tesselation, rect: Rect, oldValue: REF, data: REF]; <<>> <<-- Enumerations.>> FindTile: PROC [plane: Tesselation, pos: Pos] RETURNS [Tile]; <<--finds the tile which contains the point at pos>> TileProc: TYPE = PROC [tile: Tile, data: REF]; <<>> EnumerateArea: PROC [plane: Tesselation, rect: Rect, eachTile: TileProc, data: REF _ NIL, skip: REF _ NIL]; <<--enumerates all the tiles covering points of rect in plane. >> <<--while the enumeration the plane must not be changed>> <<--data: passed through to the eachTile procedure. >> <<--skip: tiles with value skip will be ignored and not enumerated. >> <<-- To get every tile, set skip to some value not existing value (e.g. NEW[INT]). >> <<--rect must must be changeable or the maximal size properties dont hold>> <<>> <<>> <<-- In EnumerateArea the order of enumeration is well defined. A tile appears in the enumeration immediately after the last of its children. Where tileA is defined to be a child of tileB iff its sW stitch points to tileB. Children are ordered such that the southernmost is the last. For tiles touching the western and southern borders these rules do not apply, these tiles are parent-less. Such tiles appear at some point after all the parent-less tiles touching touching a given parent-less tile's northern and western borders have been enumerated.>> ListArea: PROC [plane: Tesselation, rect: Rect, skip: REF _ NIL] RETURNS [LIST OF REF Region]; <<--Returns a list of regions describing the area rect in the tesselation plane.>> <<--Regions with tile value skip are not returned.>> <<--rect must must be changeable or the maximal size properties dont hold>> <<>> Region: TYPE = RECORD [rect: Rect, value: REF]; -- value NIL for space tiles <<>> <<-- Stepping from Tile to Tile.>> <<>> <<-- Coordinates increase from south to north, and west to east. All tile worlds are >> <<-- bordered by tiles at infinity so bounded searches wil never find NIL tiles. >> <<-- never need worry about tile = NIL. >> <<-- The tiles at infinity are not stitched to tiles in the Tesselation, rather they are >> <<-- stitched to each other in the manner of the bevelled edges of a picture frame. >> <<-- The meanings of the stepping routines are as follows ...>> <<-- EN  eastern most tile to the north>> <<-- NE  northern most tile to the east>> <<-- WS  western most tile to the south>> <<-- SW  southern most tile to the west>> EN: PROC [tile: Tile] RETURNS [Tile] = INLINE { RETURN [tile.eN] }; NE: PROC [tile: Tile] RETURNS [Tile] = INLINE { TRUSTED { RETURN [LOOPHOLE[tile.nE]] } }; WS: PROC [tile: Tile] RETURNS [Tile] = INLINE { TRUSTED { RETURN [LOOPHOLE[tile.wS]] } }; SW: PROC [tile: Tile] RETURNS [Tile] = INLINE { RETURN [tile.sW] }; <<>> <<>> <<-- Enquiries>> Area: PROC [t: Tile] RETURNS [Rect] = TRUSTED INLINE { <<--rect of tile; (upper and right border exclusive)>> RETURN [[x1: t.pos.x, y1: t.pos.y, x2: t.nE.pos.x, y2: t.eN.pos.y]] }; NEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.eN.pos.y]}; EEdge: PROC [t: Tile] RETURNS [Number] = TRUSTED INLINE {RETURN [t.nE.pos.x]}; SEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.pos.y]}; WEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.pos.x]}; <<>> IsEmpty: PROC [plane: Tesselation, rect: Rect _ all, skip: REF _ NIL] RETURNS [BOOL]; <<--returns whether rect in plane has only tiles with value skip.>> <<--rect must must be changeable >> BBox: PROC [plane: Tesselation, rect: Rect _ all, skip: REF _ NIL] RETURNS [bBox: Rect]; <<--returns a minimal bounding box for non-skip tiles in rect>> <<--rect must must be changeable.>> <<>> <<>> END.