DIRECTORY G3dBasic, G3dPolygon, G3dShape, G3dTriangle, G3dVector, ImplicitCubeTet, ImplicitDebug, ImplicitMinimal, ImplicitStorage, IO, Random, Rope; ImplicitMinimalImpl: CEDAR PROGRAM IMPORTS G3dBasic, G3dPolygon, G3dShape, G3dVector, ImplicitCubeTet, ImplicitDebug, ImplicitStorage, IO, Random, Rope EXPORTS ImplicitMinimal ~ BEGIN Triple: TYPE ~ G3dBasic.Triple; Cube: TYPE ~ ImplicitCubeTet.Cube; CubeProc: TYPE ~ ImplicitCubeTet.CubeProc; Corner: TYPE ~ ImplicitCubeTet.Corner; Tetrahedron: TYPE ~ ImplicitCubeTet.Tetrahedron; TetProc: TYPE ~ ImplicitCubeTet.TetProc; TwoCorners: TYPE ~ ImplicitCubeTet.TwoCorners; Function: TYPE ~ ImplicitMinimal.Function; TriangleProc: TYPE ~ ImplicitMinimal.TriangleProc; Centers: TYPE ~ ImplicitStorage.Centers; IDs: TYPE ~ ImplicitStorage.IDs; Edges: TYPE ~ ImplicitStorage.Edges; Faces: TYPE ~ ImplicitStorage.Faces; Vertices: TYPE ~ ImplicitStorage.Vertices; ROPE: TYPE ~ Rope.ROPE; Error: PUBLIC ERROR [reason: ROPE] = CODE; Propagate: PUBLIC PROC [ function: Function, level, size: REAL, clientData: REF ANY NIL, start: Triple [], action: CubeProc] RETURNS [centers: REF Centers] ~ { IF action # NIL THEN { Inner: PROC [c: REF Cube] ~ { TestFace: PROC [i, j, k: INT, c1, c2, c3, c4: REF Corner, face: {l, r, b, t, n, f}] ~ { Set: PROC [x, y, z: REAL, i, j, k: INT] RETURNS [c: REF Corner] ~ { c NEW[Corner [[i, j, k], [x, y, z], 0.0, unset, FALSE]]; SetCornerValue[c]; }; newCube: REF Cube; state: ImplicitCubeTet.CornerState c1.state; lbn, lbf, ltn, ltf, rbn, rbf, rtn, rtf: REF Corner; IF c2.state = state AND c3.state = state AND c4.state = state THEN RETURN; -- do this IF ImplicitStorage.AddCenter[centers, [i, j, k]] THEN RETURN; -- before this SELECT face FROM l => { -- have right (rbn, rbf, rtn, rtf); make left (lbn, lbf, ltn, ltf) x: REAL c1.pos.x-size; i: INT c1.id.i-1; rbn c1; rbf c2; rtn c3; rtf c4; lbn Set[x, rbn.pos.y, rbn.pos.z, i, rbn.id.j, rtn.id.k]; lbf Set[x, rbf.pos.y, rbf.pos.z, i, rbf.id.j, rbf.id.k]; ltn Set[x, rtn.pos.y, rtn.pos.z, i, rtn.id.j, rtn.id.k]; ltf Set[x, rtf.pos.y, rtf.pos.z, i, rtf.id.j, rtf.id.k]; }; r => { -- have left (lbn, lbf, ltn, ltf); make right (rbn, rbf, rtn, rtf) x: REAL c1.pos.x+size; i: INT c1.id.i+1; lbn c1; lbf c2; ltn c3; ltf c4; rbn Set[x, lbn.pos.y, lbn.pos.z, i, lbn.id.j, lbn.id.k]; rbf Set[x, lbf.pos.y, lbf.pos.z, i, lbf.id.j, lbf.id.k]; rtn Set[x, ltn.pos.y, ltn.pos.z, i, ltn.id.j, ltn.id.k]; rtf Set[x, ltf.pos.y, ltf.pos.z, i, ltf.id.j, ltf.id.k]; }; b => { -- have top (ltn, ltf, rtn, rtf); make bottom (lbn, lbf, rbn, rbf) y: REAL c1.pos.y-size; j: INT c1.id.j-1; ltn c1; ltf c2; rtn c3; rtf c4; lbn Set[ltn.pos.x, y, ltn.pos.z, ltn.id.i, j, ltn.id.k]; lbf Set[ltf.pos.x, y, ltf.pos.z, ltf.id.i, j, ltf.id.k]; rbn Set[rtn.pos.x, y, rtn.pos.z, rtn.id.i, j, rtn.id.k]; rbf Set[rtf.pos.x, y, rtf.pos.z, rtf.id.i, j, rtf.id.k]; }; t => { -- have bottom (lbn, lbf, rbn, rbf); make top (ltn, ltf, rtn, rtf) y: REAL c1.pos.y+size; j: INT c1.id.j+1; lbn c1; lbf c2; rbn c3; rbf c4; ltn Set[lbn.pos.x, y, lbn.pos.z, lbn.id.i, j, lbn.id.k]; ltf Set[lbf.pos.x, y, lbf.pos.z, lbf.id.i, j, lbf.id.k]; rtn Set[rbn.pos.x, y, rbn.pos.z, rbn.id.i, j, rbn.id.k]; rtf Set[rbf.pos.x, y, rbf.pos.z, rbf.id.i, j, rbf.id.k]; }; n => { -- have far (lbf, ltf, rbf, rtf); make near (lbn, ltn, rbn, rtn) z: REAL c1.pos.z-size; k: INT c1.id.k-1; lbf c1; ltf c2; rbf c3; rtf c4; lbn Set[lbf.pos.x, lbf.pos.y, z, lbf.id.i, lbf.id.j, k]; ltn Set[ltf.pos.x, ltf.pos.y, z, ltf.id.i, ltf.id.j, k]; rbn Set[rbf.pos.x, rbf.pos.y, z, rbf.id.i, rbf.id.j, k]; rtn Set[rtf.pos.x, rtf.pos.y, z, rtf.id.i, rtf.id.j, k]; }; f => { -- have near (lbn, ltn, rbn, rtn); make far (lbf, ltf, rbf, rtf) z: REAL c1.pos.z+size; k: INT c1.id.k+1; lbn c1; ltn c2; rbn c3; rtn c4; lbf Set[lbn.pos.x, lbn.pos.y, z, lbn.id.i, lbn.id.j, k]; ltf Set[ltn.pos.x, ltn.pos.y, z, ltn.id.i, ltn.id.j, k]; rbf Set[rbn.pos.x, rbn.pos.y, z, rbn.id.i, rbn.id.j, k]; rtf Set[rtn.pos.x, rtn.pos.y, z, rtn.id.i, rtn.id.j, k]; }; ENDCASE; newCube ImplicitCubeTet.SetCube[lbn.id, lbn, lbf, ltn, ltf, rbn, rbf, rtn, rtf, start]; IF NOT action[newCube, NIL] THEN RETURN; cubes CONS[newCube, cubes]; }; TestFace[c.id.i-1, c.id.j, c.id.k, c.lbn, c.lbf, c.ltn, c.ltf, l]; TestFace[c.id.i+1, c.id.j, c.id.k, c.rbn, c.rbf, c.rtn, c.rtf, r]; TestFace[c.id.i, c.id.j-1, c.id.k, c.lbn, c.lbf, c.rbn, c.rbf, b]; TestFace[c.id.i, c.id.j+1, c.id.k, c.ltn, c.ltf, c.rtn, c.rtf, t]; TestFace[c.id.i, c.id.j, c.id.k-1, c.lbn, c.ltn, c.rbn, c.rtn, n]; TestFace[c.id.i, c.id.j, c.id.k+1, c.lbf, c.ltf, c.rbf, c.rtf, f]; }; SetCornerValue: PROC [c: REF Corner] ~ { c.state IF (c.value (function[c.pos, clientData]-level)) < 0.0 THEN negative ELSE positive; c.on ABS[c.value] < 0.000001; -- constant unrelated to tet size }; pt: Triple IF start = [] THEN FindStart[start, function, size, level, clientData] ELSE start; id: G3dTriangle.IntTriple ImplicitCubeTet.IDFromPoint[pt, size, pt]; c: REF Cube ImplicitCubeTet.MakeCube[id, size, pt]; cubes: LIST OF REF Cube LIST[c]; SetCornerValue[c.lbn]; SetCornerValue[c.lbf]; SetCornerValue[c.ltn]; SetCornerValue[c.ltf]; SetCornerValue[c.rbn]; SetCornerValue[c.rbf]; SetCornerValue[c.rtn]; SetCornerValue[c.rtf]; centers ImplicitStorage.NewCenters[]; WHILE cubes # NIL DO -- need list (can't put all cubes on process stack) c: REF Cube cubes.first; cubes cubes.rest; Inner[c]; ENDLOOP; }; }; Abort: ERROR = CODE; nOn: INT 0; Triangulate: PUBLIC PROC [ function: Function, level, size: REAL, clientData: REF ANY NIL, start: Triple [], triangleAction: TriangleProc] RETURNS [error: ROPE NIL] ~ { ENABLE Abort => {error "aborted"; GOTO Bad}; CubeAction: CubeProc ~ { TetAction: TetProc ~ { tetID tetID+1; vertices ProcessTet[ function, clientData, level, tet, tetID, ids, edges, vertices, epsilon, triangleAction]; }; ImplicitCubeTet.Decompose[cube, TetAction, scratchTet]; }; ids: REF IDs ImplicitStorage.NewIDs[]; edges: REF Edges ImplicitStorage.NewEdges[]; tetID: INT nOn 0; epsilon: REAL 0.001*size; vertices: Vertices NEW[G3dShape.VertexSequenceRep[10]]; scratchTet: REF Tetrahedron NEW[Tetrahedron]; ImplicitDebug.SetDebug[[edges: edges]]; vertices.valid[normal] TRUE; [] Propagate[function, level, size, clientData, start, CubeAction]; EXITS Bad => NULL; }; ProcessTet: PUBLIC PROC [ function: Function, clientData: REF ANY, level: REAL, tet: REF Tetrahedron, tetID: INT, ids: REF IDs, edges: REF Edges, vertices: Vertices, epsilon: REAL, action: TriangleProc] RETURNS [Vertices] ~ { VIDfromEdge: PROC [e: ImplicitCubeTet.TetEdge] RETURNS [vid: INT -1] ~ { VIDfromCorners: PROC [c: TwoCorners] RETURNS [vid: INT -1] ~ { AddVertex: PROC [p: Triple] RETURNS [vid: INT] ~ { v: G3dShape.Vertex NEW[G3dShape.VertexRep [point: p]]; v.normal Normal[p, function, epsilon, clientData]; vertices G3dShape.AddToVertexSequence[vertices, v]; ImplicitDebug.SetDebug[[vertices: vertices]]; ImplicitStorage.SetEdge[edges, c.a.id, c.b.id, vid vertices.length-1]; }; VIDfromCorner: PROC [c: REF Corner] RETURNS [vid: INT] ~ { IF (vid ImplicitStorage.GetID[ids, c.id]) = -1 THEN ImplicitStorage.SetID[ids, c.id, vid AddVertex[c.pos]]; }; SELECT TRUE FROM c.a.on AND ids # NIL => {vid VIDfromCorner[c.a]; nOn nOn+1}; c.b.on AND ids # NIL => {vid VIDfromCorner[c.b]; nOn nOn+1}; c.a.state # c.b.state => IF (vid ImplicitStorage.GetEdge[edges, c.a.id, c.b.id]) = -1 THEN vid AddVertex[ Converge[c.a.pos, c.b.pos, c.a.value, level, function, clientData]]; ENDCASE; }; vid VIDfromCorners[ImplicitCubeTet.CornersFromEdge[e, tet]]; }; Intersect: ImplicitCubeTet.TetIntersectProc ~ { DoIntersect: PROC [i1, i2, i3: INT] ~ { Eq: PROC [s, t: Triple] RETURNS [b: BOOL] ~ {b G3dVector.Distance[s, t] < epsilon}; IF i1 = i2 OR i1 = i3 OR i2 = i3 THEN NULL -- ERROR ELSE { a: Triple vertices[i1].point; b: Triple vertices[i2].point; c: Triple vertices[i3].point; IF G3dPolygon.TriangleArea[a, b, c] < minArea OR Eq[a, b] OR Eq[a, c] OR Eq[b, c] THEN ImplicitDebug.Write[ IO.PutFR1["degenerate triangle (tetID: %g)\n", IO.int[tetID]]] ELSE IF NOT action[i1, i2, i3, vertices] THEN ERROR Abort; }; }; id0: INT VIDfromEdge[e1]; id1: INT VIDfromEdge[e2]; id2: INT VIDfromEdge[e3]; DoIntersect[id0, id1, id2]; IF nEdges = 4 THEN DoIntersect[id0, id2, VIDfromEdge[e4]]; }; minArea: REAL 0.2897354*epsilon*epsilon; -- constant determined from solid angle of tet ImplicitDebug.SetDebug[[tet: tet]]; ImplicitCubeTet.IntersectWithSurface[tet, Intersect]; RETURN[vertices]; }; ShapeFromFunction: PUBLIC PROC [ function: Function, level, size: REAL, clientData: REF ANY NIL, start: Triple [], statusAction: TriangleProc NIL] RETURNS [s: G3dShape.Shape NIL] ~ { Tri: TriangleProc ~ { triangle: G3dBasic.NatSequence NEW[G3dBasic.NatSequenceRep[3]]; triangle[0] i1; triangle[1] i2; triangle[2] i3; triangle.length 3; triangles G3dBasic.AddToSurfaceSequence[triangles, [NIL, triangle]]; points vertices; IF statusAction # NIL THEN RETURN[statusAction[i1, i2, i3, vertices]]; }; points: Vertices NIL; triangles: G3dBasic.SurfaceSequence NIL; startPt: Triple IF start = [] THEN FindStart[[], function, size, level, clientData] ELSE start; error: ROPE Triangulate[function, level, size, clientData, startPt, Tri]; IF points = NIL OR points.length = 0 THEN error Rope.Cat[error, IF error # NIL THEN ", " ELSE NIL, "no vertices"]; IF triangles = NIL OR triangles.length = 0 THEN error Rope.Cat[error, IF error # NIL THEN ", " ELSE NIL, "no triangles"]; IF error # NIL THEN Error[error] ELSE s NEW[G3dShape.ShapeRep [vertices:points, surfaces:triangles, type:$Triangulated]]; }; FindStart: PUBLIC PROC [ ballpark: Triple, function: Function, size, level: REAL, clientData: REF ANY NIL] RETURNS [c: Triple] ~ { Found: TYPE ~ RECORD [bad: BOOL, p: Triple]; Find: PROC [sign: {negative, positive}] RETURNS [found: Found [FALSE, ballpark]] ~ { value: REAL; FOR i: NAT IN [0..5000) DO found.p.x found.p.x+size*(Random.NextInt[rs]/REAL[LAST[INT]]-0.5); found.p.y found.p.y+size*(Random.NextInt[rs]/REAL[LAST[INT]]-0.5); found.p.z found.p.z+size*(Random.NextInt[rs]/REAL[LAST[INT]]-0.5); value function[found.p, clientData]-level; IF (sign = positive AND value > 0.0) OR (sign = negative AND value < 0.0) THEN RETURN; size size*1.005; ENDLOOP; found.bad TRUE; }; rs: Random.RandomStream Random.Create[]; pos: Found Find[positive]; neg: Found Find[negative]; IF pos.bad OR neg.bad THEN Error[Rope.Cat["can't find (", IF pos.bad THEN "+" ELSE "-", ") starting point"]] ELSE c Converge[pos.p, neg.p, 1.0, level, function, clientData]; }; Converge: PUBLIC PROC [ pos, neg: Triple, val, level: REAL, function: Function, clientData: REF ANY] RETURNS [p: Triple] ~ { p G3dVector.Midpoint[pos, neg]; IF val < 0.0 THEN {c: Triple neg; neg pos; pos c}; THROUGH [0..8) DO IF (function[p, clientData]-level) > 0.0 THEN pos p ELSE neg p; p G3dVector.Midpoint[pos, neg]; ENDLOOP; }; Normal: PUBLIC PROC [point: Triple, function: Function, delta: REAL, clientData: REF ANY] RETURNS [n: Triple] ~ { v: REAL function[point, clientData]; x: REAL v-function[[point.x+delta, point.y, point.z], clientData]; y: REAL v-function[[point.x, point.y+delta, point.z], clientData]; z: REAL v-function[[point.x, point.y, point.z+delta], clientData]; n G3dVector.Unit[[x, y, z]]; }; END.  ImplicitMinimalImpl.mesa Copyright c 1992 by Xerox Corporation. All rights reserved. Bloomenthal, March 10, 1993 11:45 am PST Types and Errors Cubic Partitioning of Implicit Surface A Minimal Polygonizer corner.on is a mechanism whereby small triangles can be eliminated; the idea is to subordinate an edge id to a corner id if the corner if the distance between corner and surface is negligible. Consider, for example, the surface intersecting the tetrahedron near one of its corners. This may occur in one of three ways; the first is when a single surface/edge intersection is negligibly close to the tetrahedron corner; in effect, this simply shifts slightly the location of the intersection. The other two cases are when either two or three of the intersections are negligibly close to the corner, as shown below: [Artwork node; type 'Artwork on' to command tool] The transition on the left (indicated by the red arrow) shows three blue surface/edge intersections, each of which are considered negligibly close to the tetrahedron corner; this closeness is indicated by the red outline of the blue circles. After the transition, these three circles are subordinated to the corner itself, shown as a red circle. Triangle 1 has become degenerate, with all three of its vertex ids being equal to the corner vertex id. Triangle 2 is also degenerate, with two of its vertex ids being equal to the corner vertex id. Triangle 3 remains non-degenerate. The transition on the left differs in that the middle blue vertex is not considered negligibly close to the corner; thus, upon the transition, Triangle 1 becomes degenerate, with two of its vertex ids equal to the corner id. Triangles 2 and 3 remain non-degenerate. The green circles represent surface/edge intersections from another tetrahedron; Triangle 2 on the left contains one such intersection; initially it is non-degenerate but after the transition becomes degenerate. Topological consistency is retained, however, from one tetrahedra to the next. There are two important consequences of this scheme. The first is that whether a corner is considered `on' or not must be determined consistently; that is, if a particular corner is computed first for one tetrahedron and then later for a different tetrahedron, whether it is `on' or not must be determined equally both times (if this consistency is not maintained, then redundant vertices will be calculated and the Euler relation will not hold). The second consequence is that, if a corner is on, it must must yield an identical surface id for all those edges connecting to it. The first consequence is simply accommodated for an implicit function: namely, the implicit function remains constant at the given corner and the test on = function (corner) < epsilon should yield consistent results for a given corner. Note that epsilon is not a unit of distance, and should bear no relation to the tetrahedron size; rather, it is purely a mathematical quantity. The second consequence is somewhat subtler. It is tempting to associate the vertex id with the corner itself: corner.vid = AddVertex[corner.position] However, this presumes that each time the corner is visited, the same vid is available, which implies that the corner is retained in memory. This is undesirable, in that each corner includes the following information: locationID: IntTriple, position: Triple, value: REAL, state: {positive, negative}, on: BOOLEAN Rather, we prefer to propagate the corners along with the cube propagation, computing four new corners for each new cube; the number of corners held in memory is thus a function of the number of cubes placed on the cube stack, but this is, in general, significantly less than the total number of corners created during the entire propagation. This does mean some corners are recomputed. For example, in the figure below, the initial cube, marked `1,' consists of the eight red circles. In propagating to the right and to above, the blue circles are computed. If the upper left cube propagates to the right, then the blue circles outlined in orange are re-computed; if the lower right cube propagates upward, then the blue circles outlined in yellow are re-computed. [Artwork node; type 'Artwork on' to command tool] The edges , however, cannot rely strictly on the six-dimensional hashing scheme to determine vertex ids that are associated with a corner, if that corner is not constantly resident in memory. Thus, an additional hash table for corner ids is required; only those corners negligibly close to the surface need store their associated vertex id in the hash table; when determining the vertex id for an intersected edge, if one of the edge corners is negligibly close, then the hash table for corner vertex ids is consulted. Geometry opposite usual gradient so surface normals point outwards ʻ7NewlineDelimiter J m1Postfix16.0 24 .div 1 1 textColor- L"BPostfix.3333 1. .4 textColorbcbcfIJffkJ J   'J5:J5:J5:J5:J"BPostfix.3333 1. .4 textColorIJJ J    'J5:J5:J5:J5:J"BPostfix.3333 1. .4 textColor IJJ J   'J5:J5:J5:J5:J"BPostfix.3333 1. .4 textColor IJJ J    'J5:J5:J5:J5:J"@Postfix.3333 1. .4 textColor GJJ J    'J5:J5:J5:J5:J"@Postfix.3333 1. .4 textColor GJJ J    'J5:J5:J5:J5:JJJYJ (JJJ DJ DJ DJ DJDJDJ(Postfix0.320 0.931 0.362 textColor ( 6BJ  J( !Postfix0.320 0.931 0.362 textColor!AJJ  5_JFJ/5J "J[J[J'"3Postfix.3333 1. .4 textColor 3HJJJ JJJ0.0 24 .div 1 1 textColor&Postfix0.0 24 .div 1 1 textColorJJ( Postfix0.320 0.931 0.362 textColor JJ J JJJ JJ0.0 24 .div 1 1 textColor.( Postfix0.320 0.931 0.362 textColorbn ( Postfix0.320 0.931 0.362 textColor  J0.0 1.0 1.0 textColor J !  XJJ7JJ (J$.J J J!9J /J'JJEJ0 1.0 1.0 textColorJJ( Postfix0.320 0.931 0.362 textColor  JJ J J J J JJJ JJ J( Postfix0.320 0.931 0.362 textColor?  J(Postfix0.320 0.931 0.362 textColor2 @( Postfix0.320 0.931 0.362 textColor)  2J":J    4J5J-JHJ( Postfix0.320 0.931 0.362 textColor-  :.0J:>JIblock16.0 24 .div 1 1 textColorI artworkFigure InterpressMInterpress/Xerox/3.0 fjkj=xjxjrj5YʡXerox RGBLinearAY[Akkxjrjz0o !0ߡXerox RGBLinearg[z0okkxjrjd'0o !0<ߡXerox RGBLineard0o[C~G[kkxjrjpszEH2{Xerox RGBLinear[qszHkkxjrjYʡXerox RGBLinearAY[AkkxjrjYʡXerox RGBLinear[kkxjrjDYAuX%Xerox RGBLinear[b~GkkxjrjD~!G. N%Xerox RGBLinearb~GkkxjrjELt+Xerox RGBLinearFGLBT Ub~GFGLBkkxjrjt=塣v?kkxjrj/1kkxjrjGۡIkkxjrj_RB$!%J!!xjXerox RGBLinear%LBkXerox RGBLinearDf!BDf!p?%Lp? J?~p??~B J?~J%LJ JDf!JDf!B JkkxjrjB$!%J!!xjXerox RGBLinear%LBkXerox RGBLinearDf!BDf!p?%Lp? J?~p??~B J?~J%LJ JDf!JDf!B JkkxjrjP)[B$!%J!!xjXerox RGBLinear%LBkXerox RGBLinearDf!BDf!p?%Lp? J?~p??~B J?~J%LJ JDf!JDf!B Jkkxjrjt=塣v?kkxjrj/1kkxjrjGۡIkkxjrj`e[!!xjXerox RGBLinearkkkxjrjLo2dQLXerox RGBLinear%LBd0oC~G%LBkkxjrj5t=塣v?kkxjrj5/1kkxjrj5GۡIkkxjrj- QRB$!%J!!xjXerox RGBLinear%LBkXerox RGBLinearDf!BDf!p?%Lp? J?~p??~B J?~J%LJ JDf!JDf!B JkkxjrjB$!%J!!xjXerox RGBLinear%LBkXerox RGBLinearDf!BDf!p?%Lp? J?~p??~B J?~J%LJ JDf!JDf!B JkkxjrjE7:wcEur@%!!xjXerox RGBLinearb~Gkkkxjrj2t=塣v?kkxjrj2/1kkxjrj2GۡIkkxjrj2`e[!!xjXerox RGBLinearkkkxjrjwcEur@%!!xjXerox RGBLinearb~GkkkxjrjƊwe[!!xjXerox RGBLinear[kkkxjrjwe[!!xjXerox RGBLinear[kkkxjrj5we[!!xjXerox RGBLinear[kkkxjrjƊwe[!!xjXerox RGBLinear[kkkxjrjwe[!!xjXerox RGBLinear[kkkxjrjƊwe[!!xjXerox RGBLinear[kkkxjrj&Ɗwe[!!xjXerox RGBLinear[kkkxjrj2we[!!xjXerox RGBLinear[kkkxjxeroxxc1-2-2 helveticaXerox RGBLinear*p+^K61kxjxeroxxc1-2-2 helveticaXerox RGBLinearLJIʵu2kxjxeroxxc1-2-2 helveticaXerox RGBLinear{?nx#C 3kxjxeroxxc1-2-2 helveticaXerox RGBLinearVp7yC 3kxjxeroxxc1-2-2 helveticaXerox RGBLinearz:1kxjxeroxxc1-2-2 helveticaXerox RGBLinearz#u2kxjxeroxxc1-2-2 helveticaXerox RGBLinear@ѐu3kxjxeroxxc1-2-2 helveticaXerox RGBLinearM8u3kxjxeroxxc1-2-2 helveticaXerox RGBLinear1C:'2kxjrj)Xerox RGBLinearkkxjrjXerox RGBLinearkkxjrj)Xerox RGBLinearkkxjrj Xerox RGBLinearkkxjrj Xerox RGBLinearkkxjrj Xerox RGBLinear/kkxjrje)Xerox RGBLinearkkxjrjeXerox RGBLinearkkxjrje)Xerox RGBLinearkkxjrje Xerox RGBLinearkkxjrje Xerox RGBLinearkkxjrje Xerox RGBLinear/kkkkgArtwork InterpressBounds:0.0 mm xmin 0.0 mm ymin 178.5405 mm xmax 31.43215 mm ymax 34.25437 mm bigger topLeading 34.25437 mm bigger topIndent 1.411111 mm bigger bottomLeading 0.5 0.3 0.95 backgroundColor the topLeading 6 pt .sub backgroundAscent 3 pt backgroundDescent 4 pt outlineBoxThickness 1 pt outlineBoxBearoffGGFile]Gargoyle file for scene: stuffed from Gargoyle at December 23, 1992 4:06:17 pm PST Produced by version 9207.29 ViewTransform: [2.0 0.0 -104.0 0.0 2.0 -646.0] Scripts: Slope: [F 150.0] [F 135.0] [F 120.0] [T 90.0] [F 60.0] [F 45.0] [F 30.0] [T 0.0] Angle: [F 90.0] [F 60.0] [F 45.0] [F 30.0] [F 0.0] [F -30.0] [F -45.0] [F -60.0] [F -90.0] Radius: [F 5.555556e-2 1/18] [F 0.1111111 1/9] [F 0.125 1/8] [F 0.25 1/4] [F 0.3333334 1/3] [F 0.5 1/2] [F 0.6666668 2/3] [F 0.75 3/4] [F 1.0 1] [F 2.0 2] [F 4.0 4] LineDistance: [F 0.0 0] [F 5.555556e-2 1/18] [F 0.1111111 1/9] [F 0.5 1/2] [F 1.0 1] Midpoints: F Heuristics: F ShowAlignments: T ScaleUnit: 72.0 DisplayStyle: print Gravity: T GravityExtent: 8.680556e-2 GravityType: pointsPreferred DefaultFont: xerox/xc1-2-2/helvetica [r1: 0.0 s: [8.278875 8.278875] r2: 0.0] 1.0 1.0 Defaults: [1 0.5] [1 1.0] 2.0 round round Dashed: F Shadows: [1 1.0]F Anchor: F Palette: F Active: F BackgroundColor: [1 0.0] Entities: [60]: Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [3] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [699.0,481.0] (Line ) [654.0,480.0] (Line ) [711.0,443.0] (Line ) [699.0,481.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [711.0,443.0] (Line ) [655.6458,414.991] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [4] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [536.1458,414.991] (Line ) [591.5,443.0] (Line ) [553.5025,456.7748] (Line ) [579.5,481.0] (Line ) [591.5,443.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [309.0,443.0] (Line ) [252.687,436.7361] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [3] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [416.5,481.0] (Line ) [371.5,480.0] (Line ) [428.5,443.0] (Line ) [416.5,481.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [309.0,443.0] (Line ) [297.0,481.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [309.0,443.0] (Line ) [271.0025,456.7748] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [297.0,481.0] (Line ) [271.0025,456.7748] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [3] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [236.7236,453.8692] (Line ) [253.0942,436.7815] (Line ) [271.0025,456.7748] (Line ) [236.7236,453.8692] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [252.0,480.0] (Line ) [214.0,415.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [252.0,480.0] (Line ) [254.0,401.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [252.0,480.0] (Line ) [297.0,425.0] fwd: T pList: ( ) Circle [5.099 0.0 271.0025 0.0 5.099 456.7748] strokeWidth: 2.0 strokeColor: [0 0.8 0.0 0.0] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 236.7236 0.0 5.099 453.8692] strokeWidth: 2.0 strokeColor: [0 0.8 0.0 0.0] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 252.687 0.0 5.099 436.7361] strokeWidth: 2.0 strokeColor: [0 0.8 0.0 0.0] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [371.5,480.0] (Line ) [333.5,415.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [371.5,480.0] (Line ) [373.5,401.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [371.5,480.0] (Line ) [416.5,425.0] fwd: T pList: ( ) Circle [5.099 0.0 371.5 0.0 5.099 480.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.8 0.0 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [3] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [519.2236,453.8692] (Line ) [536.1458,414.991] (Line ) [553.5025,456.7748] (Line ) [519.2236,453.8692] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [534.5,480.0] (Line ) [496.5,415.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [534.5,480.0] (Line ) [536.5,401.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [534.5,480.0] (Line ) [579.5,425.0] fwd: T pList: ( ) Circle [5.099 0.0 553.5025 0.0 5.099 456.7748] strokeWidth: 2.0 strokeColor: [0 0.8 0.0 0.0] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 519.2236 0.0 5.099 453.8692] strokeWidth: 2.0 strokeColor: [0 0.8 0.0 0.0] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 536.1458 0.0 5.099 414.991] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [654.0,480.0] (Line ) [616.0,415.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [654.0,480.0] (Line ) [656.0,401.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [1 1.0] d: T F [654.0,480.0] (Line ) [699.0,425.0] fwd: T pList: ( ) Circle [5.099 0.0 654.0 0.0 5.099 480.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.8 0.0 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 655.6458 0.0 5.099 414.991] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.0 0.8] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 297.0 0.0 5.099 481.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 309.0 0.0 5.099 443.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 591.5 0.0 5.099 443.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 579.5 0.0 5.099 481.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 428.5 0.0 5.099 443.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 416.5 0.0 5.099 481.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 699.0 0.0 5.099 481.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Circle [5.099 0.0 711.0 0.0 5.099 443.0] strokeWidth: 2.0 strokeColor: [] fillColor: [0 0.0 0.8 0.0] dashes: ( F ) props: ( F ) fwd: T pList: ( ) Text T "1" xerox/xc1-2-2/helvetica [9.93465 0.0 255.5184 0.0 9.93465 447.0186][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "2" xerox/xc1-2-2/helvetica [9.93465 0.0 267.5343 0.0 9.93465 443.5299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T " 3" xerox/xc1-2-2/helvetica [9.93465 0.0 286.8274 0.0 9.93465 459.0299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T " 3" xerox/xc1-2-2/helvetica [9.93465 0.0 402.3274 0.0 9.93465 466.0299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "1" xerox/xc1-2-2/helvetica [9.93465 0.0 538.5344 0.0 9.93465 439.5299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "2" xerox/xc1-2-2/helvetica [9.93465 0.0 554.0343 0.0 9.93465 433.5299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "3" xerox/xc1-2-2/helvetica [9.93465 0.0 572.0343 0.0 9.93465 458.5299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "3" xerox/xc1-2-2/helvetica [9.93465 0.0 686.0343 0.0 9.93465 466.5299][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Text T "2" xerox/xc1-2-2/helvetica [9.93465 0.0 663.8774 0.0 9.93465 441.2821][0 0.0 0.0 0.8] F 1.0 props: ( F ) ls: 1.2 pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [599.5,460.0] (Line ) [616.0,460.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [599.5,460.0] (Arc [599.5,457.5] ) [599.5,455.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [599.5,455.0] (Line ) [616.0,455.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [616.0,465.0] (Line ) [616.0,460.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [616.0,455.0] (Line ) [616.0,450.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [2] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [616.0,465.0] (Line ) [631.0,457.5] (Line ) [616.0,450.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [317.0,460.0] (Line ) [333.5,460.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [317.0,460.0] (Arc [317.0,457.5] ) [317.0,455.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [317.0,455.0] (Line ) [333.5,455.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [333.5,465.0] (Line ) [333.5,460.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [1] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [333.5,455.0] (Line ) [333.5,450.0] fwd: T pList: ( ) Outline fillColor: [1 0.5] ow: T fillText: T 0 Children: [1] Traj (open) [2] arrows: 0 j: round e: T round w: 2.0 c: T [0 0.8 0.0 0.0] d: T F [333.5,465.0] (Line ) [348.5,457.5] (Line ) [333.5,450.0] fwd: T pList: ( ) 33L16.0 24 .div 1 1 textColorL16.0 24 .div 1 1 textColorL16.0 24 .div 1 1 textColorL16.0 24 .div 1 1 textColor16.0 24 .div 1 1 textColor M;Interpress/Xerox/3.0 fjkj=xj#{hdxjrj@;{xI {%P.U2)oI+()yLIoIkkxjrj#t #;{oI {%P)oI+()yLIoIkkxjrj#t @;{oI {%P)oI+()yLIoIkkxjrj@'(>)oI+()yLIoIkkxjrj#9늠>)oI+()yLIoIkkxjrj{'(>)oI+()yLIoIkkxjrjߔ{'(>)oI+()yLIoIkkxjrj@+N{kR {%P4{,D{Rkkxjrj#t ';{oI {%PJDJJJ>J( Postfix0.320 0.931 0.362 textColor&0.666 1.0 1.0 textColor &/( Postfix0.320 0.931 0.362 textColor0.666 1.0 1.0 textColor 'J(Postfix0.320 0.931 0.362 textColorS0.0 1.0 1.0 textColor )U0.666 1.0 1.0 textColor   J0.666 1.0 1.0 textColorcs0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColor0.0 1.0 1.0 textColor*Q0.0 1.0 1.0 textColorJ0.0 1.0 1.0 textColor  >J0.666 1.0 1.0 textColor :J0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColorJ0.666 1.0 1.0 textColor (:J0.666 1.0 1.0 textColorJ .YJ#J5J JJcode(Postfix0.320 0.931 0.362 textColor NN J NN!N!N(Postfix0.320 0.931 0.362 textColorJ!AJ5JJ6 FJJ FJJJ&*J 2aJ@K )J  K /J  L J J\J0.0 24 .div 1 1 textColor( Postfix0.320 0.931 0.362 textColor  JJJ J J JJ'Postfix16.0 24 .div 1 1 textColor& ,(Postfix0.320 0.931 0.362 textColorR   VJ  J/DJ/DJ/DJ,J VJJJ JJ*JJ J  VJ>BJJ(Postfix0.320 0.931 0.362 textColor J "LJ JJ!J  8J&  CJ!JJJ(Postfix0.320 0.931 0.362 textColorS  ,YJ JJ99J&J=DJ=DJ=DJJJJJJJ-,k