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; BoundBox: TYPE = REF BoundBoxObj; BoundBoxObj: TYPE = SVBoundBox.BoundBoxObj; 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] = { 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] = { 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] = { 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] = { 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] = { 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] = { minX, minY, minZ, maxX, maxY, maxZ: REAL; localPt, cameraPt: Point3d; perspecPt: Point2d; IF bh = NIL THEN {boundBox _ NIL; RETURN}; 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] = { IF boundBox = NIL THEN RETURN[TRUE] -- NIL is used to represent an infinite bounding box ELSE 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] = { IF bb1 = NIL OR bb2 = NIL THEN {newBB _ NIL; RETURN}; newBB _ NEW[BoundBoxObj]; FOR i: NAT IN[1..3] DO newBB.minVert[i] _ bb2.minVert[i]; 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] = { IF bb1 = NIL AND bb2 = NIL THEN {newBB _ NIL; RETURN}; newBB _ NEW[BoundBoxObj]; FOR i: NAT IN[1..3] DO SELECT TRUE FROM bb1 = NIL => { newBB.minVert[i] _ bb2.minVert[i]; newBB.maxVert[i] _ bb2.maxVert[i]; }; bb2 = NIL => { newBB.minVert[i] _ bb1.minVert[i]; newBB.maxVert[i] _ bb1.maxVert[i]; }; ENDCASE => { 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] = { IF bb1 = NIL THEN {newBB _ NIL; RETURN}; 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] = { 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; 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. ŽFile: SVBoundBoxImpl.mesa Last edited by Bier on August 19, 1983 1:02 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. A pyramid with base of size sx by sz on the y=0 plane and tip at [0, sy, 0]. 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]. 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. Bounds a disk (centered on y axis) with radius r at y = h; A boundHedron is expressed in local coordinates. for now, draw a line from each point to every other 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. Boundbox is in camera coords so this is easy. Bound box is in perspective camera coords. Convert to screen and draw. bound box is in perspective camera coords. Convert to screen and draw. Κ λ– "cedar" style˜Iheadšœ™Iprocšœ.™.Lšœε™εL˜šΟk ˜ Lšœ ˜ Lšœ˜Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ ˜ Lšœ˜Lšœ ˜ Lšœ ˜ —L˜šœ˜Lšœ-˜4Lšœ ˜—Lš˜˜Lšœœ˜"Lšœ œœ ˜$Lšœ œ˜)Lšœ œ˜Lšœ œ˜!Lšœ œœ ˜"Lšœœ˜"L˜Lšœ œœ˜'Lšœœ˜1L˜Lšœ œœ ˜!Lšœ œ˜+Lšœ˜š Οnœœœœœ˜GLšœœ˜Lšœ ˜ Lšœ˜—Lšœ˜šžœœœ&˜FLšœœ˜"šœ˜Lšœ˜Lšœ˜Lšœ˜—LšœΟc˜ —L˜šžœœœ$˜Cšœœœ˜Lšœ!˜!—Lšœ˜Lšœ˜—Lšœ˜š žœœœœœ˜TLšœœ˜Lšœ ˜ Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ*˜*Lšœ+˜+Lšœ*˜*Lšœ)˜)Lšœ+˜+Lšœ,˜,Lšœ+˜+Lšœ*˜*LšœŸ ˜#—Lšœ˜š žœœœœœ˜aLšœ˜Lšœ&˜&Lšœ&˜&Lšœ&˜&Lšœ&˜&Lšœ&˜&Lšœ&˜&Lšœ&˜&Lšœ&˜&LšœŸ!˜$—Lšœ˜š žœœœœœ˜PLšœL™LLšœ œ˜Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ(˜(Lšœ)˜)Lšœ(˜(Lšœ'˜'Lšœ$˜$LšœŸ˜—L˜š žœœœ œœ˜QLšœ˜Lšœ˜Lšœ/˜/Lšœ3˜3Lšœ ˜ Lšœ#˜#Lšœ˜—Lšœ˜š žœœœœœ˜MLšœƒ™ƒLšœ ˜ Lšœ'˜'Lšœ˜Lšœ˜Lšœ#˜#LšœŸ˜"—L˜š žœœœœœ˜XLšœŒ™ŒLšœ ˜ Lšœ˜Lšœ)˜)Lšœ˜Lšœ)˜)Lšœ˜LšœŸ ˜#—L˜š žœœœœœ˜GLšœ:™:Lšœ ˜ Lšœ˜Lšœ'˜'Lšœ˜LšœŸ˜—Lšœ˜šžœœœ˜3Lšœ ˜ Lšœ˜—Lšœ˜šžœœœm˜‰Lšœ0™0Lšœ3™3šœœœ ˜šœœœ ˜šœœ˜ Lšœ4˜4Lšœ7˜7——Lšœ˜—Lšœ˜Lšœ˜—Lšœ˜šžœœœ9œ˜}Lšœœ™œLšœ$œ˜)Lšœ˜Lšœ˜L˜Lš œœœ œœ˜*Lšœ œ˜Lšœ˜Lšœ7˜7Lšœ9˜9Lšœ˜Lšœ˜Lšœ˜šœœœ ˜Lšœ˜Lšœ7˜7Lšœ9˜9Lšœœ˜/Lšœœœ˜5Lšœœ˜/Lšœœœ˜5Lšœœ˜-Lšœœœ˜3—Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜LšœŸ!˜$—Lšœ˜š žœœœœœ˜_Lšœ œ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜LšœŸ˜—L˜š žœœœ,œœ˜ZLšœ-™-Lš œ œœœœŸ4˜Xšœœ˜ Lšœ&œ$˜MLš˜Lšœ&œ%˜N—LšœŸ˜—L˜šžœœœœ˜VLšœœœœœ œœ˜5Lšœœ˜šœœœ˜Lšœ"˜"Lšœ7˜7Lšœ7˜7—Lšœ˜LšœŸ ˜#—Lšœ˜šžœœœœ˜]Lšœœœœœ œœ˜6Lšœœ˜šœœœ˜šœœ˜šœœ˜Lšœ"˜"Lšœ"˜"L˜—šœœ˜Lšœ"˜"Lšœ"˜"L˜—šœ˜ Lšœ7˜7Lšœ7˜7L˜———Lšœ˜LšœŸ'˜*—Lšœ˜šžœœœœ˜[Lš œœœ œœ˜(Lšœœ˜šœœœ˜Lšœ"˜"Lšœ"˜"—Lšœ˜LšœŸ%˜(—Lšœ˜L˜šž œœœD˜]LšœG™GLšœ6˜6LšœX˜XLšœX˜XLšœY˜YLšœY˜YLšœ/˜/Lšœ0˜0Lšœ2˜2Lšœ2˜2Lšœ0˜0LšœŸ˜—Lšœ˜šžœœœD˜cLšœ*˜*Lšœ˜LšœG™GLšœ6˜6LšœX˜XLšœX˜XLšœY˜YLšœY˜YLšœ2˜2Lšœ2˜2Lšœ4˜4Lšœ4˜4Lšœ˜Lšœ'˜'Lšœ+˜+Lšœ˜Lšœ˜LšœŸ˜—Lšœ˜š žœœœœœ˜)Lšœœœœ˜Lšœ˜—L˜š žœœœœœ˜)Lšœœœœ˜Lšœ˜——L˜Lšœ˜—…—#€2ω