```MODULE W3dGeometry; (** AUTHOR "TF"; PURPOSE "Geometrical primitives (case study)"; *) IMPORT Vectors := W3dVectors; TYPE Plane* = RECORD n* : Vectors.TVector3d; d* : LONGREAL END; Ray* = RECORD p, d : Vectors.TVector3d END; Frustum* = OBJECT VAR nearP*, farP*, bottomP*, rightP*, topP*, leftP* : Plane; PROCEDURE Make*(p, d, u : Vectors.TVector3d; focus, w, h, near, far : LONGREAL); VAR left, z, p0, p1, p2, p3, f0, f1, f2, near0, near1, near2, far0, far1, far2 : Vectors.TVector3d; factor : LONGREAL; BEGIN left := Vectors.Cross(d, u); z := Vectors.VAdd3(p, Vectors.VScaled3(d, - focus)); p0 := Vectors.VAdd3(Vectors.VAdd3(p, Vectors.VScaled3(u, -h/2)), Vectors.VScaled3(left, w/2)); p1 := Vectors.VAdd3(Vectors.VAdd3(p, Vectors.VScaled3(u, -h/2)), Vectors.VScaled3(left, -w/2)); p2 := Vectors.VAdd3(Vectors.VAdd3(p, Vectors.VScaled3(u, h/2)), Vectors.VScaled3(left, -w/2)); p3 := Vectors.VAdd3(Vectors.VAdd3(p, Vectors.VScaled3(u, h/2)), Vectors.VScaled3(left, w/2)); f0 := Vectors.VNormed3(Vectors.VSub3(p0, z)); f1 := Vectors.VNormed3(Vectors.VSub3(p1, z)); f2 := Vectors.VNormed3(Vectors.VSub3(p2, z)); factor := 1 / Vectors.Scalar3(f0, d); (* symmetric situation, all factors are the same *) near0 := Vectors.VAdd3(p0, Vectors.VScaled3(f0, near * factor)); near1 := Vectors.VAdd3(p1, Vectors.VScaled3(f1, near * factor)); near2 := Vectors.VAdd3(p1, Vectors.VScaled3(f2, near * factor)); far0 := Vectors.VAdd3(p0, Vectors.VScaled3(f0, far * factor)); far1 := Vectors.VAdd3(p1, Vectors.VScaled3(f1, far * factor)); far2 := Vectors.VAdd3(p1, Vectors.VScaled3(f2, far * factor)); nearP := MakePlane(near0, near2, near1); farP := MakePlane(far0, far1, far2); leftP := MakePlane(z, p0, p3); bottomP := MakePlane(z, p1, p0); rightP := MakePlane(z, p2, p1); topP := MakePlane(z, p3, p2); END Make; PROCEDURE IsBSOutsideBehind*(center : Vectors.TVector3d; r: LONGREAL): BOOLEAN; BEGIN RETURN (Distance(nearP, center) > r) OR (Distance(leftP, center) > r) OR (Distance(rightP, center) > r) OR (Distance(bottomP, center) > r) OR (Distance(topP, center) > r) END IsBSOutsideBehind; END Frustum; PROCEDURE MakePlane*(p0, p1, p2 : Vectors.TVector3d) : Plane; VAR result : Plane; BEGIN result.n := Vectors.VNormed3(Vectors.Cross(Vectors.VSub3(p1, p0), Vectors.VSub3(p2, p0))); result.d := - Vectors.Scalar3(result.n, p0); RETURN result END MakePlane; PROCEDURE Distance*(e: Plane; p : Vectors.TVector3d) : LONGREAL; BEGIN RETURN Vectors.Scalar3(e.n, p) + e.d END Distance; (** intersection between g and e, g is treated as line *) PROCEDURE Intersection*(VAR g : Ray; VAR e : Plane; VAR p : Vectors.TVector3d) : BOOLEAN; VAR m, d: LONGREAL; BEGIN d := Vectors.Scalar3(e.n, g.d); IF d = 0 THEN RETURN FALSE END; m := -(Vectors.Scalar3(e.n, g.p)+e.d) / d; p := Vectors.VAdd3(g.p, Vectors.VScaled3(g.d, m)); RETURN TRUE END Intersection; END W3dGeometry. ```