-- File: SVBoundBoxImpl.mesa -- Last edited by Bier on December 18, 1982 1:36 am -- Author: Eric Bier on June 23, 1983 2:24 pm -- Contents: Procedures for creating bounding polyhedra of master objects, and for deriving "3-d" bounding boxes from these polyhedra. Procedures for combining these bounding boxes with union, intersection and difference operators. DIRECTORY CoordSys, CSG, CSGGraphics, Graphics, GraphicsColor, Matrix3d, SV2d, SVBoundBox, SVPolygon3d; SVBoundBoxImpl: PROGRAM IMPORTS CoordSys, CSGGraphics, Graphics, SVPolygon3d EXPORTS SVBoundBox = BEGIN Camera: TYPE = CSGGraphics.Camera; CoordSystem: TYPE = REF CoordSysObj; CoordSysObj: TYPE = CoordSys.CoordSysObj; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = Matrix3d.Point3d; PointSetOp: TYPE = CSG.PointSetOp; Poly3d: TYPE = SVPolygon3d.Poly3d; BoundHedron: TYPE = REF BoundHedronObj; BoundHedronObj: TYPE = SVBoundBox.BoundHedronObj; -- RECORD [ -- len: NAT, -- seq: SEQUENCE numVerts: NAT OF Point3d]; BoundBox: TYPE = REF BoundBoxObj; BoundBoxObj: TYPE = SVBoundBox.BoundBoxObj; -- RECORD [ -- minVert: Point3d, ( min x, y and z makes this lower-left-deep) -- maxVert: Point3d]; ( max x, y and z makes this upper-right-shallow) CreateBoundHedron: PUBLIC PROC [len: NAT] RETURNS [bh: BoundHedron] = { bh _ NEW[BoundHedronObj[len]]; bh.len _ 0; }; AddBoundHedronPoint: PUBLIC PROC [bh: BoundHedron, point: Point3d] = { IF bh.len = bh.maxVerts THEN ERROR ELSE { bh[bh.len] _ point; bh.len _ bh.len + 1; }; }; -- end of AddBoundHedronPoint AddBoundHedronPoly: PUBLIC PROC [bh: BoundHedron, poly: Poly3d] = { FOR i: NAT IN[0..poly.len) DO AddBoundHedronPoint[bh, poly[i]]; ENDLOOP; }; RectangularBoundHedron: PUBLIC PROC [sx, sy, sz: REAL] RETURNS [bh: BoundHedron] = { sx2, sy2, sz2: REAL; sx2 _ sx/2; sy2 _ sy/2; sz2 _ sz/2; bh _ CreateBoundHedron[8]; AddBoundHedronPoint[bh, [-sx2, sy2, sz2]]; AddBoundHedronPoint[bh, [-sx2, sy2, -sz2]]; AddBoundHedronPoint[bh, [sx2, sy2, -sz2]]; AddBoundHedronPoint[bh, [sx2, sy2, sz2]]; AddBoundHedronPoint[bh, [-sx2, -sy2, sz2]]; AddBoundHedronPoint[bh, [-sx2, -sy2, -sz2]]; AddBoundHedronPoint[bh, [sx2, -sy2, -sz2]]; AddBoundHedronPoint[bh, [sx2, -sy2, sz2]]; }; -- end of RectangularBoundHedron RectangularBoundHedron2: PUBLIC PROC [x1, x2, y1, y2, z1, z2: REAL] RETURNS [bh: BoundHedron] = { bh _ CreateBoundHedron[8]; AddBoundHedronPoint[bh, [x1, y2, z2]]; AddBoundHedronPoint[bh, [x1, y2, z1]]; AddBoundHedronPoint[bh, [x2, y2, z1]]; AddBoundHedronPoint[bh, [x2, y2, z2]]; AddBoundHedronPoint[bh, [x1, y1, z2]]; AddBoundHedronPoint[bh, [x1, y1, z1]]; AddBoundHedronPoint[bh, [x2, y1, z1]]; AddBoundHedronPoint[bh, [x2, y1, z2]]; }; -- end of RectangularBoundHedron2 PyramidBoundHedron: PUBLIC PROC [sx, sy, sz: REAL] RETURNS [bh: BoundHedron] = { -- A pyramid with base of size sx by sz on the y=0 plane and tip at [0, sy, 0]. sx2, sz2: REAL; sx2 _ sx/2; sz2 _ sz/2; bh _ CreateBoundHedron[5]; AddBoundHedronPoint[bh, [-sx2, 0, sz2]]; AddBoundHedronPoint[bh, [-sx2, 0, -sz2]]; AddBoundHedronPoint[bh, [sx2, 0, -sz2]]; AddBoundHedronPoint[bh, [sx2, 0, sz2]]; AddBoundHedronPoint[bh, [0, sy, 0]]; }; -- end of PyramidBoundHedron HexagonalBoundHedron: PUBLIC PROC [r, hOver2: REAL] RETURNS [bh: BoundHedron] = { topPoly, bottomPoly: Poly3d; bh _ CreateBoundHedron[12]; topPoly _ SVPolygon3d.CircumHexagon[hOver2, r]; bottomPoly _ SVPolygon3d.CircumHexagon[-hOver2, r]; AddBoundHedronPoly[bh, topPoly]; AddBoundHedronPoly[bh, bottomPoly]; }; HexPyramidBoundHedron: PUBLIC PROC [r, h: REAL] RETURNS [bh: BoundHedron] = { -- A pyramid having base a hexagon around the circle (of radius r centered on [0, 0, 0] on the y=0 plane) and having tip at [0, h, 0]. base: Poly3d; base _ SVPolygon3d.CircumHexagon[0, r]; bh _ CreateBoundHedron[7]; AddBoundHedronPoly[bh, base]; AddBoundHedronPoint[bh, [0, h, 0]]; }; -- end of HexPyramidBoundHedron GeneralConeBoundHedron: PUBLIC PROC [r1, h1, r2, h2: REAL] RETURNS [bh: BoundHedron] = { -- Bounds a cone slice (cone around y axis) with radius r1 at y=h1 and radius r2 at y = h2. Currently uses two hexagons. Octagons may follow. poly: Poly3d; bh _ CreateBoundHedron[12]; poly _ SVPolygon3d.CircumHexagon[h1, r1]; AddBoundHedronPoly[bh, poly]; poly _ SVPolygon3d.CircumHexagon[h2, r2]; AddBoundHedronPoly[bh, poly]; }; -- end of GeneralConeBoundHedron DiskBoundHedron: PUBLIC PROC [r, h: REAL] RETURNS [bh: BoundHedron] = { -- Bounds a disk (centered on y axis) with radius r at y = h; poly: Poly3d; bh _ CreateBoundHedron[6]; poly _ SVPolygon3d.CircumHexagon[h, r]; AddBoundHedronPoly[bh, poly]; }; -- end of DiskBoundHedron ClearBoundHedron: PUBLIC PROC [bh: BoundHedron] = { bh.len _ 0; }; DrawBoundHedron: PUBLIC PROC [dc: Graphics.Context, bh: BoundHedron, localWRTWorld: CoordSystem, camera: Camera, screen: CoordSystem] = { -- a boundHedron is expressed in local coordinates. -- for now, draw a line from each point to every other FOR i: NAT IN[0..bh.len) DO FOR j: NAT IN[0..bh.len) DO IF i#j THEN { CSGGraphics.SetCP[dc, bh[i], camera, localWRTWorld]; CSGGraphics.DrawTo[dc, bh[j], camera, localWRTWorld];}; ENDLOOP; ENDLOOP; }; BoundBoxFromBoundHedron: PUBLIC PROC [bh: BoundHedron, camera: Camera, localCS: CoordSystem] RETURNS [boundBox: BoundBox] = { -- For each point of the bound hedron, find its perspective projection into camera coordinates. Do not project z. Find min x, y, z and max x, y, z as you go. minX, minY, minZ, maxX, maxY, maxZ: REAL; localPt, cameraPt: Point3d; perspecPt: Point2d; boundBox _ NEW[BoundBoxObj]; localPt _ bh[0]; cameraPt _ CSGGraphics.LocalToCamera[localPt, localCS]; perspecPt _ CSGGraphics.GetPerspective[cameraPt, camera]; minX _ maxX _ perspecPt[1]; minY _ maxY _ perspecPt[2]; minZ _ maxZ _ cameraPt[3]; FOR i: NAT IN[1..bh.len) DO localPt _ bh[i]; cameraPt _ CSGGraphics.LocalToCamera[localPt, localCS]; perspecPt _ CSGGraphics.GetPerspective[cameraPt, camera]; IF perspecPt[1] < minX THEN minX _ perspecPt[1] ELSE IF perspecPt[1] > maxX THEN maxX _ perspecPt[1]; IF perspecPt[2] < minY THEN minY _ perspecPt[2] ELSE IF perspecPt[2] > maxY THEN maxY _ perspecPt[2]; IF cameraPt[3] < minZ THEN minZ _ cameraPt[3] ELSE IF cameraPt[3] > maxZ THEN maxZ _ cameraPt[3]; ENDLOOP; boundBox.minVert[1] _ minX; boundBox.minVert[2] _ minY; boundBox.minVert[3] _ minZ; boundBox.maxVert[1] _ maxX; boundBox.maxVert[2] _ maxY; boundBox.maxVert[3] _ maxZ; }; -- end of BoundBoxFromBoundHedron BoundBoxFromValues: PUBLIC PROC [minX, minY, maxX, maxY: REAL] RETURNS [boundBox: BoundBox] = { boundBox _ NEW[BoundBoxObj]; boundBox.minVert[1] _ minX; boundBox.minVert[2] _ minY; boundBox.minVert[3] _ 0; boundBox.maxVert[1] _ maxX; boundBox.maxVert[2] _ maxY; boundBox.maxVert[3] _ 0; }; -- end of BoundBoxFromValues PointInBoundBox: PUBLIC PROC [cameraPoint: Point2d, boundBox: BoundBox] RETURNS [BOOL] = { -- boundbox is in camera coords so this is easy. RETURN[ boundBox.minVert[1] <= cameraPoint[1] AND cameraPoint[1]<=boundBox.maxVert[1] AND boundBox.minVert[2] <= cameraPoint[2] AND cameraPoint[2]<=boundBox.maxVert[2]] }; -- end of PointInBoundBox UnionCombineBoundBoxes: PUBLIC PROC [bb1, bb2: BoundBox] RETURNS [newBB: BoundBox] = { newBB _ NEW[BoundBoxObj]; FOR i: NAT IN[1..3] DO newBB.minVert[i] _ Min[bb1.minVert[i], bb2.minVert[i]]; newBB.maxVert[i] _ Max[bb1.maxVert[i], bb2.maxVert[i]]; ENDLOOP; }; -- end of UnionCombineBoundBoxes IntersectionCombineBoundBoxes: PUBLIC PROC [bb1, bb2: BoundBox] RETURNS [newBB: BoundBox] = { newBB _ NEW[BoundBoxObj]; FOR i: NAT IN[1..3] DO newBB.minVert[i] _ Max[bb1.minVert[i], bb2.minVert[i]]; newBB.maxVert[i] _ Min[bb1.maxVert[i], bb2.maxVert[i]]; ENDLOOP; }; -- end of IntersectionCombineBoundBoxes DifferenceCombineBoundBoxes: PUBLIC PROC [bb1, bb2: BoundBox] RETURNS [newBB: BoundBox] = { newBB _ NEW[BoundBoxObj]; FOR i: NAT IN[1..3] DO newBB.minVert[i] _ bb1.minVert[i]; newBB.maxVert[i] _ bb1.maxVert[i]; ENDLOOP; }; -- end of DifferenceCombineBoundBoxes DrawBoundBox: PUBLIC PROC [dc: Graphics.Context, boundBox: BoundBox, screen: CoordSystem] = { -- bound box is in perspective camera coords. Convert to screen and draw. lowerLeft, upperLeft, upperRight, lowerRight: Point2d; lowerLeft _ CoordSys.CameraToScreen[[boundBox.minVert[1], boundBox.minVert[2]], screen]; upperLeft _ CoordSys.CameraToScreen[[boundBox.minVert[1], boundBox.maxVert[2]], screen]; upperRight _ CoordSys.CameraToScreen[[boundBox.maxVert[1], boundBox.maxVert[2]], screen]; lowerRight _ CoordSys.CameraToScreen[[boundBox.maxVert[1], boundBox.minVert[2]], screen]; Graphics.SetCP[dc, lowerLeft[1], lowerLeft[2]]; Graphics.DrawTo[dc, upperLeft[1], upperLeft[2]]; Graphics.DrawTo[dc, upperRight[1], upperRight[2]]; Graphics.DrawTo[dc, lowerRight[1], lowerRight[2]]; Graphics.DrawTo[dc, lowerLeft[1], lowerLeft[2]]; }; -- end of DrawBoundBox ComplementBoundBox: PUBLIC PROC [dc: Graphics.Context, boundBox: BoundBox, screen: CoordSystem] = { path: Graphics.Path _ Graphics.NewPath[4]; mark: Graphics.Mark; -- bound box is in perspective camera coords. Convert to screen and draw. lowerLeft, upperLeft, upperRight, lowerRight: Point2d; lowerLeft _ CoordSys.CameraToScreen[[boundBox.minVert[1], boundBox.minVert[2]], screen]; upperLeft _ CoordSys.CameraToScreen[[boundBox.minVert[1], boundBox.maxVert[2]], screen]; upperRight _ CoordSys.CameraToScreen[[boundBox.maxVert[1], boundBox.maxVert[2]], screen]; lowerRight _ CoordSys.CameraToScreen[[boundBox.maxVert[1], boundBox.minVert[2]], screen]; Graphics.MoveTo[path, lowerLeft[1], lowerLeft[2]]; Graphics.LineTo[path, upperLeft[1], upperLeft[2]]; Graphics.LineTo[path, upperRight[1], upperRight[2]]; Graphics.LineTo[path, lowerRight[1], lowerRight[2]]; mark _ Graphics.Save[dc]; [] _ Graphics.SetPaintMode[dc, invert]; Graphics.SetColor[dc, GraphicsColor.black]; Graphics.DrawArea[dc, path]; Graphics.Restore[dc, mark]; }; -- end of ComplementBoundBox Min: PROC [a, b: REAL] RETURNS [REAL] = { RETURN[IF a < b THEN a ELSE b]; }; Max: PROC [a, b: REAL] RETURNS [REAL] = { RETURN[IF a > b THEN a ELSE b]; }; END. Κ»– "Mesa" style˜IprocšΊΟcθœΟk œ žœižœžœ/žœžœ žœ$žœžœžœ"žœžœ!žœžœžœ%žœžœ!žœ œ œ,œ žœžœžœ œBœGœΟnœžœžœžœžœžœ*Ÿœžœžœ(žœžœžœžœ9œŸœžœžœ&žœžœžœžœ&žœŸœžœžœžœžœ'žœ­!œŸœžœžœžœžœχ"œŸœžœžœžœžœPœ žœŠœŸœžœžœ žœžœ…Ÿœžœžœžœžœ‡œœ œŸœžœžœžœœΔ!œŸœž œžœžœ>œwœŸœžœžœ*Ÿœžœžœo4œ7œžœžœžœ žœžœžœžœ žœžœžœzžœžœŸœžœžœ9žœ œ$žœ?žœμžœžœžœ žœŒžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ³"œŸœžœžœžœžœ&žœŸœͺŸœžœžœ,žœžœ1œžœ*žœ'žœ)žœ)œŸœžœžœžœ žœžœžœžœžœvžœ!œŸœžœžœžœ žœžœžœžœžœvžœ(œŸœžœžœžœ žœžœžœžœžœLžœ&œŸ œžœžœFKœ£Ÿœž œόœŸœžœžœžœžœžœžœžœžœ Ÿœžœžœžœžœžœžœžœžœ žœ˜ƒP—…—(+Η