RVHUtilsImplB.mesa
Last Edited by: Arnon, June 20, 1985 4:44:33 pm PDT
DIRECTORY
RealFns USING [Sin, Cos],
RatNums,
ClientStateInfo,
RVHandleUtils;
RVHUtilsImplB: CEDAR PROGRAM
IMPORTS RatNums, ClientStateInfo, RVHandleUtils
EXPORTS RVHandleUtils =
BEGIN OPEN CSI: ClientStateInfo, RN: RatNums, RVHandleUtils;
AddVertexToPolygon: PUBLIC PROC [vhandlefirst: VertexHandle, x,y: RN.RatNum, state: CSI.State ← CSI.defaultState] RETURNS [VertexHandle] = {
vhandlefirst is thought of as being on the polygonal outline of a figure. The new vertex [x,y] is added so as to come after the vertex which precedes vhandlefirst (call it vhandlelast), and before vhandlefirst, in the counterclockwise ordering of vertices. vhandlefirst is returned, so that subsequently added vertices will always be inserted just before vhandlefirst.
The current coding (specifically case of three or more vertices previously) assumes that the figure is nothing more than a polygon, i.e. has no internal edges.
vhandlethis, vhandlelast: VertexHandle;
ahthistofirst, ahthistolast, ahfirsttothis, ahlasttothis, ahthis, ahfirst : AdjacencyHandle;
ahlist, ahlistthis, ahlistfirst, ahlistlast : AdjacencyHandleList;
leftRegionVisitedValue: BOOL;
Make a VertexHandle for the new vertex
vhandlethis ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[x, y], index: vertexIndex, adjacentVertices: NIL, visited: FALSE] ];
vertexIndex ← vertexIndex + 1;
IF vhandlefirst = NIL THEN RETURN [vhandlethis] --This is first vertex(Figure empty prevsly)
ELSE vhandlethis.visited ← vhandlefirst.visited; -- copy visited value
ahlistfirst ← vhandlefirst.adjacentVertices;
IF ahlistfirst = NIL THEN { -- One vertex previously --
ahfirst ← NEW[Adjacency ← [ vertex: vhandlethis, leftState: state, leftRegionVisited: FALSE, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ]; -- set flag fields = FALSE
ahthis← NEW[Adjacency ← [ vertex: vhandlefirst, leftState: NIL, leftRegionVisited: FALSE, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
vhandlethis.adjacentVertices ← CONS[ ahthis, NIL ];
vhandlethis.adjacentVertices.rest ← vhandlethis.adjacentVertices; -- make circular --
vhandlefirst.adjacentVertices ← CONS[ ahfirst, NIL ];
vhandlefirst.adjacentVertices.rest ← vhandlefirst.adjacentVertices; -- make circular --
RETURN [ vhandlefirst ];
};
Find vhandlelast (Note that we know at this point that ahlistfirst # NIL)
IF ahlistfirst.rest = ahlistfirst THEN vhandlelast ← ahlistfirst.first.vertex ELSE vhandlelast ← PreviousOutlineVertex[vhandlefirst]; -- check specially for case of two vertices previously, since in that case we can't go looking for the previous outline vertex by expecting to find a vertex adjacent to vhandlefirst with leftRegionExterior = TRUE, because in the two vertex case, the single vertex adjacent to vhandlefirst has leftRegionExterior = FALSE in order to remain correct when more vertices are added to the polygon.
ahlistlast ← vhandlelast.adjacentVertices;
Get value of visited field (all vertices in the polygon must have same field value)
leftRegionVisitedValue ← ahlistfirst.first.leftRegionVisited;
Create AdjacencyHandleList for the new vertex
ahthistofirst ← NEW[Adjacency ← [ vertex: vhandlefirst, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahthistofirst, NIL ];
ahthistolast← NEW[Adjacency ← [ vertex: vhandlelast, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistolast, ahlist ];
ahlist.rest ← ahlistthis; -- make circular --
vhandlethis.adjacentVertices ← ahlistthis;
IF ahlistfirst.rest = ahlistfirst THEN { -- Two vertices previously --
Update AdjacencyHandleList of first vertex (note that it had length one)
ahfirsttothis ← NEW[Adjacency ← [ vertex: vhandlethis, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahfirsttothis, ahlistfirst ];
ahlistfirst.rest ← ahlist; -- make circular; destroy previous circular link --
vhandlefirst.adjacentVertices ← ahlist;
Update AdjacencyHandleList of previous last vertex (note that it had length one) --
ahlasttothis ← NEW[Adjacency ← [ vertex: vhandlethis, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE , intersectionPolygonEdge: FALSE] ];
ahlist ← CONS[ ahlasttothis, ahlistlast ];
ahlistlast.rest ← ahlist; -- make circular; destroy previous circular link --
vhandlelast.adjacentVertices ← ahlist;
}
ELSE { -- Three or more vertices previously --
Update AdjacencyHandleList of first vertex in vertexhandlelist (have it point to the new vertex; delete the edge to previous last vertex). Note that vhandlefirst and vhandlelast, like all vertices on the polygon, had exactly two adjacencies previously
IF ahlistfirst.first.vertex = vhandlelast THEN ahlistfirst.first.vertex ← vhandlethis ELSE ahlistfirst.rest.first.vertex ← vhandlethis;
Update AdjacencyHandleList of last vertex in vertexhandlelist (have it point to the new vertex; delete the edge to first vertex)
IF ahlistlast.first.vertex = vhandlefirst THEN ahlistlast.first.vertex ← vhandlethis ELSE ahlistlast.rest.first.vertex ← vhandlethis;
};
RETURN [ vhandlefirst ];
};
ExpandNontrivialPolygon: PROC[v, w:VertexHandle, point: Point] RETURNS[y, z: VertexHandle] = {
[v,w] is a counterclockwise-oriented edge of a polygon which is assumed to already have at least three vertices (i.e. have a nonempty interior). point is an external point, which is imbedded in a vertex x. An edge from v to x is created, and an edge [y: x , z: w ] from x to w is created. The edge [x,w] is returned so that the polygon can be further expanded by a new vertex occurring after x in counterclockwise order. The edge [v,w] is deleted.
ahlsave: AdjacencyHandleList;
Create a VertexHandle for the new vertex.
x ← NEW[ Vertex ← [coordinates: point, adjacentVertices: NIL] ];
Get adjacency information needed to create the new edges.
[vTow, wTov] ← FindAdjacency[ v, w];
Set up the edge from v to x (and delete that w is adjacent to v).
vTow.vertex ← x;
Edge from w to x (and delete that v is adjacent to w).
wTov.vertex ← x;
Fill in edge from x to w
ah ← NEW[ Adjacency ← [vertex: w,
leftState: vTow.leftState,
leftRegionVisited : vTow.leftRegionVisited,
leftRegionExterior : vTow.leftRegionExterior ] -- should be FALSE
];
x.adjacentVertices ← CONS[ ah, x.adjacentVertices ];
ahlsave ← x.adjacentVertices; -- save pointer to last list cell for making circular list
Edge from x to v.
ah ← NEW[ Adjacency ← [vertex: v,
leftState: wTov.leftState,
leftRegionVisited : wTov.leftRegionVisited,
leftRegionExterior : wTov.leftRegionExterior ] -- should be TRUE
];
x.adjacentVertices ← CONS[ ah, x.adjacentVertices ];
ahlsave.rest ← x.adjacentVertices; -- make list of adjacencies circular
RETURN[ x, w];
};
Sausify: PUBLIC PROC [brush:VertexHandle, start, end:Point] RETURNS[sausage:VertexHandle]={
Cartesian Product of brush and vector [start,end] to make a sausage. brush is assumed to be a convex polygon with counterclockwise ordered vertices. sausage is the same sort of polygon.
outline:BOOLTRUE;
delta:Point←[end.x-start.x,end.y-start.y];
temp:VertexHandle;
done:BOOLFALSE;
w:VertexHandle𡤋rush;
v:VertexHandle←PreviousOutlineVertex[w];
firstv:VertexHandle←v;
sausage←InitVertexHandle[];
Find an initialvertex (firstv) on the unswept boundary
WHILE NOT done DO temp←NEW[Vertex←[coordinates:[v.coordinates.x+delta.x,v.coordinates.y+delta.y],adjacentVertices:NIL,visited:FALSE]];
IF CCW[temp,v,w] THEN done←TRUE ELSE[v,w]←StepVertex[v,w,outline];
ENDLOOP;
firstv←v;
done←FALSE;
Fill in unswept boundary up to transition to swept boundary
WHILE NOT done DO temp←NEW[Vertex←[coordinates:[v.coordinates.x+delta.x,v.coordinates.y+delta.y],adjacentVertices:NIL,visited:FALSE]];
IF CCW[temp,v,w]THEN{
sausage�VertexToPolygon[sausage,v.coordinates.x,v.coordinates.y];
[v,w]←StepVertex[v,w,outline];
}
ELSE done←TRUE;
ENDLOOP;
sausage�VertexToPolygon[sausage,v.coordinates.x,v.coordinates.y];
--put in unswept image of this point; swept image will be added by next loop.
done←FALSE;
FIll in swept boundary
WHILE NOT done DO temp←NEW[Vertex←[coordinates:[v.coordinates.x+delta.x,v.coordinates.y+delta.y],adjacentVertices:NIL,visited:FALSE]];
sausage�VertexToPolygon[sausage,temp.coordinates.x,temp.coordinates.y];
IF CCW[temp,v,w] THEN done←TRUE ELSE[v,w]←StepVertex[v,w,outline];
ENDLOOP;
Remainder of unswept boundary,back to firstv
WHILE v#firstv DO
sausage�VertexToPolygon[sausage,v.coordinates.x,v.coordinates.y];
[v,w]←StepVertex[v,w,outline];
ENDLOOP;
RETURN[sausage];
};
Ngon: PUBLIC PROC [N: CARDINAL, xCenter, yCenter, radius: RN.RatNum] RETURNS [gon:VertexHandle] ~ {
Make an N-gon as per the input parameters
PI: REAL𡤃.14159;
I: CARDINAL;
theta, x, y: RN.RatNum;
gon ← InitVertexHandle[];
FOR I IN [1..N] DO
theta←(I*2.0*PI)/N;
x←xCenter+radius*RealFns.Cos[theta];
y←yCenter+radius*RealFns.Sin[theta];
gon�VertexToPolygon[gon,x,y];
ENDLOOP;
};
Diamond: PUBLIC PROC [top: Point, scale: RN.RatNum, state: CSI.State] RETURNS [diamond:VertexHandle] ~ {
Make a diamond of height scale and width 1/2 scale, upwards or downwards from top as specified by the sign of scale.
topX: RN.RatNum ← top.x;
topY: RN.RatNum ← top.y;
leftX, leftY, bottomY, rightX: RN.RatNum;
scale2: RN.RatNum ← RN.RatNumDivide[ scale, RN.RatNumFromSmallCards[1,2,1] ];
scale4: RN.RatNum ← RN.RatNumDivide[ scale, RN.RatNumFromSmallCards[1,4,1] ];
diamond ← AddVertexToPolygon[InitVertexHandle[], topX, topY, state];
leftX ← RN.RatNumSubtract[ topX, scale4];
leftY ← RN.RatNumSubtract[ topY, scale2];
diamond ← AddVertexToPolygon[diamond, leftX, leftY, state];
bottomY ← RN.RatNumSubtract[ topY, scale];
diamond ← AddVertexToPolygon[diamond, topX, bottomY, state];
rightX ← RN.RatNumAdd[ topX, scale4];
diamond ← AddVertexToPolygon[diamond, rightX, leftY, state];
};
DiamondRightUp: PUBLIC PROC [v, w: VertexHandle, state: CSI.State] ~ {
Grow a diamond to the right and upwards. [v, w] is assumed to be an external edge of a structure, and will be interpreted as the lower left edge of the new diamond, i.e. v will be the diamond's left vertex and w its bottom. The diamond height (scale) and width (1/2 scale) will be computed from [v, w].
vHandleLeft: VertexHandle ← v;
vHandleBottom: VertexHandle ← w;
left: Point ← vHandleLeft.coordinates;
bottom: Point ← vHandleBottom.coordinates;
vHandleRight, vHandleTop: VertexHandle;
rightX, rightY: RN.RatNum;
topX, topY: RN.RatNum;
scale2: RN.RatNum ← RN.RatNumSubtract[ left.y, bottom.y ];
scale4: RN.RatNum ← RN.RatNumSubtract[ bottom.x, left.x ];
ahRightToTop, ahRightToBottom, ahTopToLeft, ahTopToRight: AdjacencyHandle;
ahLeftToTop, ahBottomToRight: AdjacencyHandle;
ahlist, ahlistRight, ahlistTop, ahlistLeft, ahlistBottom : AdjacencyHandleList;
leftRegionVisitedValue: BOOL;
Make a VertexHandle for the right vertex
rightX ← RN.RatNumAdd[ bottom.x, scale4];
rightY ← left.y;
vHandleRight ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[rightX, rightY], index: vertexIndex, adjacentVertices: NIL, visited: vHandleLeft.visited] ];
vertexIndex ← vertexIndex + 1;
Make a VertexHandle for the top vertex
topX ← bottom.x;
topY ← RN.RatNumAdd[ left.y, scale2];
vHandleTop ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[topX, topY], index: vertexIndex, adjacentVertices: NIL, visited: vHandleLeft.visited] ];
vertexIndex ← vertexIndex + 1;
Get adjacency lists for left and bottom, and visited value
ahlistLeft ← vHandleLeft.adjacentVertices;
ahlistBottom ← vHandleBottom.adjacentVertices;
leftRegionVisitedValue ← ahlistLeft.first.leftRegionVisited;
Create adjacency lists for right and top
ahRightToTop ← NEW[Adjacency ← [ vertex: vHandleTop, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahRightToTop, NIL ];
ahRightToBottom← NEW[Adjacency ← [ vertex: vHandleBottom, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistRight ← CONS[ ahRightToBottom, ahlist ];
ahlist.rest ← ahlistRight; -- make circular --
vHandleRight.adjacentVertices ← ahlistRight;
ahTopToLeft ← NEW[Adjacency ← [ vertex: vHandleLeft, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahTopToLeft, NIL ];
ahTopToRight← NEW[Adjacency ← [ vertex: vHandleRight, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistTop ← CONS[ ahTopToRight, ahlist ];
ahlist.rest ← ahlistTop; -- make circular --
vHandleTop.adjacentVertices ← ahlistTop;
Update adjacency list for left
ahLeftToTop ← NEW[Adjacency ← [ vertex: vHandleTop, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahLeftToTop, NIL ];
WHILE ahlistLeft.rest.first.vertex # vHandleBottom DO ahlistLeft ← ahlistLeft.rest ENDLOOP;
ahlistLeft.rest.first.leftState ← state; -- edge previously on exterior is no longer so
ahlistLeft.rest.first.leftRegionExterior ← FALSE;
ahlistLeft.rest.first.leftRegionVisited ← leftRegionVisitedValue; -- needed?
ahlist.rest ← ahlistLeft.rest;
ahlistLeft.rest ← ahlist;
Update adjacency list for bottom
ahBottomToRight ← NEW[Adjacency ← [ vertex: vHandleRight, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahBottomToRight, NIL ];
WHILE ahlistBottom.first.vertex # vHandleLeft DO ahlistBottom ← ahlistBottom.rest ENDLOOP;
ahlist.rest ← ahlistBottom.rest;
ahlistBottom.rest ← ahlist;
};
DiamondLeftUp: PUBLIC PROC [v, w: VertexHandle, state: CSI.State] ~ {
Grow a diamond to the right and downwards. [v, w] is assumed to be an external edge of a structure, and will be interpreted as the lower right edge of the new diamond, i.e. v will be the diamond's bottom vertex and w its right. The diamond height (scale) and width (1/2 scale) will be computed from [v, w].
vHandleBottom: VertexHandle ← v;
vHandleRight: VertexHandle ← w;
bottom: Point ← vHandleBottom.coordinates;
right: Point ← vHandleRight.coordinates;
vHandleTop, vHandleLeft: VertexHandle;
topX, topY: RN.RatNum;
leftX, leftY: RN.RatNum;
scale2: RN.RatNum ← RN.RatNumSubtract[ right.y, bottom.y ];
scale4: RN.RatNum ← RN.RatNumSubtract[ right.x, bottom.x ];
ahTopToLeft, ahTopToRight, ahLeftToBottom, ahLeftToTop: AdjacencyHandle;
ahBottomtoLeft, ahRightToTop: AdjacencyHandle;
ahlist, ahlistRight, ahlistTop, ahlistLeft, ahlistBottom : AdjacencyHandleList;
leftRegionVisitedValue: BOOL;
Make a VertexHandle for the top vertex
topX ← bottom.x;
topY ← RN.RatNumAdd[ right.y, scale2];
vHandleTop ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[topX, topY], index: vertexIndex, adjacentVertices: NIL, visited: vHandleBottom.visited] ];
vertexIndex ← vertexIndex + 1;
Make a VertexHandle for the left vertex
leftX ← RN.RatNumSubtract[ bottom.x, scale4];
leftY ← right.y;
vHandleLeft ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[leftX, leftY], index: vertexIndex, adjacentVertices: NIL, visited: vHandleBottom.visited] ];
vertexIndex ← vertexIndex + 1;
Get adjacency lists for bottom and right, and visited value
ahlistBottom ← vHandleBottom.adjacentVertices;
ahlistRight ← vHandleRight.adjacentVertices;
leftRegionVisitedValue ← ahlistRight.first.leftRegionVisited;
Create adjacency lists for top and left
ahTopToLeft ← NEW[Adjacency ← [ vertex: vHandleLeft, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahTopToLeft, NIL ];
ahTopToRight← NEW[Adjacency ← [ vertex: vHandleRight, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistTop ← CONS[ ahTopToRight, ahlist ];
ahlist.rest ← ahlistTop; -- make circular --
vHandleRight.adjacentVertices ← ahlistTop;
ahLeftToBottom ← NEW[Adjacency ← [ vertex: vHandleBottom, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahLeftToBottom, NIL ];
ahLeftToTop← NEW[Adjacency ← [ vertex: vHandleTop, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistLeft ← CONS[ ahLeftToTop, ahlist ];
ahlist.rest ← ahlistLeft; -- make circular --
vHandleTop.adjacentVertices ← ahlistLeft;
Update adjacency list for bottom
ahBottomtoLeft ← NEW[Adjacency ← [ vertex: vHandleLeft, leftState: NIL, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahBottomtoLeft, NIL ];
WHILE ahlistBottom.rest.first.vertex # vHandleRight DO ahlistBottom ← ahlistBottom.rest ENDLOOP;
ahlistBottom.rest.first.leftState ← state; -- edge previously on exterior is no longer so
ahlistBottom.rest.first.leftRegionExterior ← FALSE;
ahlistBottom.rest.first.leftRegionVisited ← leftRegionVisitedValue; -- needed?
ahlist.rest ← ahlistBottom.rest;
ahlistBottom.rest ← ahlist;
Update adjacency list for right
ahRightToTop ← NEW[Adjacency ← [ vertex: vHandleTop, leftState: state, leftRegionVisited: leftRegionVisitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlist ← CONS[ ahRightToTop, NIL ];
WHILE ahlistRight.first.vertex # vHandleBottom DO ahlistRight ← ahlistRight.rest ENDLOOP;
ahlist.rest ← ahlistRight.rest;
ahlistRight.rest ← ahlist;
};
DiamondGrid: PUBLIC PROC [top: Point, scale: RN.RatNum, state: CSI.State, size: CARDINAL, visitedValue: BOOL] RETURNS [diamondGrid: VertexHandle] = {
size must be at least 2
gridArray: ARRAY [1..20] OF ARRAY [1..20] OF VertexHandle;
scale2: RN.RatNum ← RN.RatNumDivide[ scale, RN.RatNumFromSmallCards[1,2,1] ];
scale4: RN.RatNum ← RN.RatNumDivide[ scale, RN.RatNumFromSmallCards[1,4,1] ];
newVertexX, newVertexY: RN.RatNum;
topX: RN.RatNum ← top.x;
topY: RN.RatNum ← top.y;
ahthistonext, ahthistoprev, ahthistoprev2, ah: AdjacencyHandle;
ahlistnext, ahlistprev, ahlistthis, ahlist, ahlsave: AdjacencyHandleList;
Create vertices
FOR i: CARDINAL IN [1..size] DO
FOR j: CARDINAL IN [1..size] DO
newVertexX ← RN.RatNumAdd[
topX,
RN.RatNumAdd[
RN.RatNumMultiply[scale4, RN.RatNumFromSmallCards[MIN[1, i-1], i-1, 1] ],
RN.RatNumMultiply[scale4, RN.RatNumFromSmallCards[MIN[1, j-1], j-1, 1] ]
]
];
newVertexY ← RN.RatNumAdd[
topY,
RN.RatNumSubtract[
RN.RatNumMultiply[scale2, RN.RatNumFromSmallCards[MIN[1, i-1], i-1, 1] ],
RN.RatNumMultiply[scale2, RN.RatNumFromSmallCards[MIN[1, j-1], j-1, 1] ]
]
];
gridArray[i][j] ← NEW[ Vertex ← [coordinates: MakePointFromRatNums[newVertexX, newVertexY], index: vertexIndex, adjacentVertices: NIL, visited: visitedValue] ];
vertexIndex ← vertexIndex + 1;
ENDLOOP;
ENDLOOP;
Corner vertices adjacencies (2 per vertex), lower left first
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[1][2], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[2][1], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev, ahlistnext ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[1][1].adjacentVertices ← ahlistthis;
lower right
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[2][size], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[1][size-1], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev, ahlistnext ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[1][size].adjacentVertices ← ahlistthis;
upper right
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[size][size-1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[size-1][size], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev, ahlistnext ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[size][size].adjacentVertices ← ahlistthis;
upper left
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[size-1][1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[size][2], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev, ahlistnext ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[size][1].adjacentVertices ← ahlistthis;
non-corner boundary vertices (3 adjacencies for each); left side first (top to bottom); go backwards (counterclockwise) through adjacencies
FOR i: CARDINAL DECREASING IN [2..size-1] DO
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[i-1][1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[i][2], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistprev ← CONS[ ahthistoprev, ahlistnext ];
ahthistoprev2← NEW[Adjacency ← [ vertex: gridArray[i+1][1], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev2, ahlistprev ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[i][1].adjacentVertices ← ahlistthis;
ENDLOOP;
bottom row vertices (left to right)
FOR j: CARDINAL IN [2..size-1] DO
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[1][j+1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[2][j], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistprev ← CONS[ ahthistoprev, ahlistnext ];
ahthistoprev2← NEW[Adjacency ← [ vertex: gridArray[1][j-1], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev2, ahlistprev ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[1][j].adjacentVertices ← ahlistthis;
ENDLOOP;
right side vertices (bottom to top)
FOR i: CARDINAL IN [2..size-1] DO
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[i+1][size], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[i][size-1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistprev ← CONS[ ahthistoprev, ahlistnext ];
ahthistoprev2← NEW[Adjacency ← [ vertex: gridArray[i-1][size], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev2, ahlistprev ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[i][size].adjacentVertices ← ahlistthis;
ENDLOOP;
top row vertices (right to left)
FOR j: CARDINAL DECREASING IN [2..size-1] DO
ahthistonext ← NEW[Adjacency ← [ vertex: gridArray[size][j-1], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistnext ← CONS[ ahthistonext, NIL ];
ahthistoprev← NEW[Adjacency ← [ vertex: gridArray[size-1][j], leftState: state, leftRegionVisited: visitedValue, leftRegionExterior: FALSE, intersectionPolygonEdge: FALSE ] ];
ahlistprev ← CONS[ ahthistoprev, ahlistnext ];
ahthistoprev2← NEW[Adjacency ← [ vertex: gridArray[size][j+1], leftState: NIL, leftRegionVisited: visitedValue, leftRegionExterior: TRUE, intersectionPolygonEdge: FALSE ] ];
ahlistthis ← CONS[ ahthistoprev2, ahlistprev ];
ahlistnext.rest ← ahlistthis; -- make circular --
gridArray[size][j].adjacentVertices ← ahlistthis;
ENDLOOP;
interior vertices (4 adjacencies for each)
FOR i: CARDINAL IN [2..size-1] DO
FOR j: CARDINAL IN [2..size-1] DO
ah ← NEW[ Adjacency ← [vertex: gridArray[i+1][j],
leftState: state,
leftRegionVisited : visitedValue,
leftRegionExterior: FALSE,
intersectionPolygonEdge: FALSE]
];
ahlist ← CONS[ ah, NIL ];
ahlsave ← ahlist; -- save pointer to last list cell for making circular list
ah ← NEW[ Adjacency ← [vertex: gridArray[i][j-1],
leftState: state,
leftRegionVisited : visitedValue,
leftRegionExterior: FALSE,
intersectionPolygonEdge: FALSE]
];
ahlist ← CONS[ ah, ahlist ];
ah ← NEW[ Adjacency ← [vertex: gridArray[i-1][j],
leftState: state,
leftRegionVisited : visitedValue,
leftRegionExterior: FALSE,
intersectionPolygonEdge: FALSE]
];
ahlist ← CONS[ ah, ahlist ];
ah ← NEW[ Adjacency ← [vertex: gridArray[i][j+1],
leftState: state,
leftRegionVisited : visitedValue,
leftRegionExterior: FALSE,
intersectionPolygonEdge: FALSE]
];
ahlist ← CONS[ ah, ahlist ];
ahlsave.rest ← ahlist; -- make list of adjacencies circular
gridArray[i][j].adjacentVertices ← ahlist;
ENDLOOP;
ENDLOOP;
diamondGrid ← gridArray[1][1];
};
END.