<> <> <> DIRECTORY Atom USING [ GetPropFromList ], Real USING [ Round, LargestNumber ], ThreeDBasics USING [ Context, RealSequence, Rectangle, ShapeInstance ], Interactive3D USING [ CloseVertex, CloseVertexSequence, FacingDirection ]; Interactive3DImpl: CEDAR PROGRAM IMPORTS Atom, Real EXPORTS Interactive3D ~ BEGIN <> Context: TYPE ~ ThreeDBasics.Context; Rectangle: TYPE ~ ThreeDBasics.Rectangle; RealSequence: TYPE ~ ThreeDBasics.RealSequence; FacingDirection: TYPE ~ Interactive3D.FacingDirection; CloseVertex: TYPE ~ Interactive3D.CloseVertex; <> CloseVertexSequence: TYPE ~ Interactive3D.CloseVertexSequence; <> <> NearbyVertices: PUBLIC PROC[ context: Context, cursorX, cursorY: REAL, numberToReturn: NAT _ 1, maxDistance: REAL _ Real.LargestNumber ] RETURNS[ closeVtx: REF CloseVertexSequence ] ~ { closeDist: REF RealSequence _ NEW[ RealSequence[numberToReturn] ]; FOR i: NAT IN [0.. closeDist.length) DO closeDist[i] _ Real.LargestNumber; ENDLOOP; closeVtx _ NEW[ CloseVertexSequence[numberToReturn] ]; FOR i: NAT IN [0.. context.shapes.length) DO IF Atom.GetPropFromList[context.shapes[i].props, $Invisible] = NIL AND context.shapes[i].clipState # out AND Inside[context.shapes[i], cursorX, cursorY] THEN { shape: REF ThreeDBasics.ShapeInstance _ context.shapes[i]; FOR i: NAT IN [0.. shape.vertex.length) DO distance: REAL _ ABS[ cursorX - shape.vertex[i].sx ] + ABS[ cursorY - shape.vertex[i].sy ]; IF distance < maxDistance AND distance < closeDist[0] THEN { closeDist[0] _ distance; -- replace most distant close vertex found so far closeVtx[0] _ [i, shape]; FOR j: NAT IN [1 .. closeDist.length) DO -- bubble into sorted position IF closeDist[i] > closeDist[i-1] THEN { tmpVtx: CloseVertex; tmpDst: REAL; tmpDst _ closeDist[i-1]; closeDist[i-1] _ closeDist[i]; closeDist[i] _ tmpDst; tmpVtx _ closeVtx[i-1]; closeVtx[i-1] _ closeVtx[i]; closeVtx[i] _ tmpVtx; } ELSE EXIT; ENDLOOP; -- do for close Vertices }; ENDLOOP; -- do for all vertices }; ENDLOOP; -- do for all shapes }; Inside: PROC[ shape: REF ThreeDBasics.ShapeInstance, x, y: REAL ] RETURNS[ BOOLEAN ] ~ { ix: NAT _ Real.Round[x]; iy: NAT _ Real.Round[y]; IF shape.screenExtent.min.f > ix OR shape.screenExtent.max.f < ix OR shape.screenExtent.min.s > iy OR shape.screenExtent.max.s < iy THEN RETURN[ FALSE ] ELSE RETURN[ TRUE ]; }; BestPolygon: PUBLIC PROC[ closeVtx: REF CloseVertexSequence, facingDir: FacingDirection _ front, closest: BOOLEAN _ TRUE ] ~ { }; <> PasteOn: PUBLIC PROC[context: Context, viewPort: Rectangle, action: PROC[Context]] ~ { <> }; RipOff: PUBLIC PROC[ context: Context ] ~ { <> <> <> <> <> <> <> <> <> }; END.