DIRECTORY Matrix3d, RealFns, Vector3d; Vector3dImpl: CEDAR PROGRAM IMPORTS Matrix3d, RealFns EXPORTS Vector3d ~ BEGIN OPEN Vector3d; Null: PUBLIC PROC [v: Triple] RETURNS [BOOL] ~ { RETURN[v.x = 0.0 AND v.y = 0.0 AND v.z = 0.0]; }; Negate: PUBLIC PROC [v: Triple] RETURNS [Triple] ~ { RETURN[[-v.x, -v.y, -v.z]]; }; Normalize: PUBLIC PROC [v: Triple] RETURNS [Triple] ~ { m: REAL ~ RealFns.SqRt[v.x*v.x+v.y*v.y+v.z*v.z]; RETURN[SELECT m FROM 0.0 => origin, 1.0 => v, ENDCASE => [v.x/m, v.y/m, v.z/m]]; }; Unitize: PUBLIC PROC [v: Triple] RETURNS [Triple] ~ {RETURN[Normalize[v]]}; Mul: PUBLIC PROC [v: Triple, s: REAL] RETURNS [Triple] ~ { RETURN[[v.x*s, v.y*s, v.z*s]]; }; Div: PUBLIC PROC [v: Triple, s: REAL] RETURNS [Triple] ~ { RETURN[IF s # 0.0 THEN [v.x/s, v.y/s, v.z/s] ELSE [v.x, v.y, v.z]]; }; Add: PUBLIC PROC [v1, v2: Triple] RETURNS [Triple] ~ { RETURN[[v2.x+v1.x, v2.y+v1.y, v2.z+v1.z]]; }; Sub: PUBLIC PROC [v1, v2: Triple] RETURNS [Triple] ~ { RETURN[[v1.x-v2.x, v1.y-v2.y, v1.z-v2.z]]; }; Equal: PUBLIC PROC [v1, v2: Triple, epsilon: REAL _ 0.001] RETURNS [BOOL] ~ { RETURN[ABS[v1.x-v2.x] 1.-epsilon]; }; Perpendicular: PUBLIC PROC [v1, v2: Triple, epsilon: REAL _ 0.005] RETURNS [BOOL _ FALSE] ~ { perp: BOOL _ FALSE; temp1: Triple _ Normalize[v1]; temp2: Triple _ Normalize[v2]; RETURN[ABS[Dot[temp1, temp2]] < epsilon]; }; LinePoint: PUBLIC PROC [p: Triple, l: Line] RETURNS [Triple] ~ { lineV: Triple _ Normalize[l.axis]; RETURN[Add[l.base, Mul[lineV, Dot[Sub[p, l.base], lineV]]]]; }; Project: PUBLIC PROC [v1, v2: Triple] RETURNS [Triple] ~ { v2unit: Triple _ Normalize[v2]; RETURN[Mul[v2unit, Dot[v1, v2unit]]]; }; PtOnLine: PUBLIC PROC [p: Triple, l: Line, epsilon: REAL _ 0.005] RETURNS [BOOL] ~ { RETURN[Distance[p, LinePoint[p, l]] < epsilon]; }; V90: PUBLIC PROC [v0, v1: Triple] RETURNS [Triple] ~ { dot: REAL _ Dot[v0, v1]; RETURN [IF ABS[dot] > 0.000001 THEN Normalize[[v1.x-dot*v0.x, v1.y-dot*v0.y, v1.z-dot*v0.z]] ELSE v1]; }; Ortho: PUBLIC PROC [v: Triple, crosser: Triple _ [0.0, 0.0, 0.0]] RETURNS [Triple] ~ { length: REAL _ Length[v]; IF crosser = v THEN crosser _ [crosser.z, crosser.y, crosser.x]; RETURN[IF length = 0.0 THEN [0.0, 0.0, 0.0] ELSE Mul[Normalize[Cross[v, crosser]], length]]; }; RotateAbout: PUBLIC PROC [v, axis: Triple, a: REAL, degrees: BOOL _ TRUE] RETURNS [Triple] ~ { rotate: Matrix3d.Matrix _ Matrix3d.MakePureRotate[axis, a, degrees]; RETURN[Matrix3d.TransformVec[v, rotate]]; }; PolarFromCartesian: PUBLIC PROC [cartesian: Triple] RETURNS [Triple] ~ { xzSum: REAL _ cartesian.x*cartesian.x+cartesian.z*cartesian.z; lng: REAL _ RealFns.ArcTanDeg[cartesian.z, cartesian.x]; lat: REAL _ RealFns.ArcTanDeg[cartesian.y, RealFns.SqRt[xzSum]]; mag: REAL _ RealFns.SqRt[xzSum+cartesian.y*cartesian.y]; IF lat < 0.0 THEN lat _ 360.0+lat; RETURN[[lng, lat, mag]]; }; CartesianFromPolar: PUBLIC PROC [polar: Triple] RETURNS [Triple] ~ { cosmag: REAL _ RealFns.CosDeg[polar.y]*polar.z; RETURN[[ cosmag*RealFns.CosDeg[polar.x], polar.z*RealFns.SinDeg[polar.y], cosmag*RealFns.SinDeg[polar.x]]]; }; CopyRealSequence: PUBLIC PROC [reals: RealSequence] RETURNS [RealSequence] ~ { copy: RealSequence _ NIL; IF reals # NIL THEN { copy _ NEW[RealSequenceRep[reals.length]]; copy.length _ reals.length; FOR n: NAT IN [0..reals.length) DO copy[n] _ reals[n]; ENDLOOP; }; RETURN[copy]; }; CopyPairSequence: PUBLIC PROC [pairs: PairSequence] RETURNS [PairSequence] ~ { copy: PairSequence _ NIL; IF pairs # NIL THEN { copy _ NEW[PairSequenceRep[pairs.length]]; copy.length _ pairs.length; FOR n: NAT IN [0..pairs.length) DO copy[n] _ pairs[n]; ENDLOOP; }; RETURN[copy]; }; CopyTripleSequence: PUBLIC PROC [triples: TripleSequence] RETURNS [TripleSequence] ~ { copy: TripleSequence _ NIL; IF triples # NIL THEN { copy _ NEW[TripleSequenceRep[triples.length]]; copy.length _ triples.length; FOR n: NAT IN [0..triples.length) DO copy[n] _ triples[n]; ENDLOOP; }; RETURN[copy]; }; ArcCos: PUBLIC PROC [cos: REAL, degrees: BOOL _ TRUE] RETURNS [REAL] ~ { x: REAL ~ MIN[1.0, MAX[-1.0, cos]]; y: REAL ~ RealFns.SqRt[1.0-x*x]; RETURN[IF degrees THEN RealFns.ArcTanDeg[y, x] ELSE RealFns.ArcTan[y, x]]; }; CosineBetween: PUBLIC PROC [v0, v1: Triple] RETURNS [REAL] ~ { RETURN[Dot[Normalize[v0], Normalize[v1]]]; }; AngleBetween: PUBLIC PROC [v0, v1: Triple, degrees: BOOL _ TRUE] RETURNS [REAL] ~ { RETURN[ArcCos[CosineBetween[v0, v1], degrees]]; }; MinMaxOfTriples: PUBLIC PROC [triples: TripleSequence] RETURNS [mm: MinMax] ~ { huge: REAL ~ 100000000.0; mm.min _ [huge, huge, huge]; mm.max _ [-huge, -huge, -huge]; FOR n: NAT IN [0..triples.length) DO t: Triple ~ triples[n]; IF t.x < mm.min.x THEN mm.min.x _ t.x; IF t.x > mm.max.x THEN mm.max.x _ t.x; IF t.y < mm.min.y THEN mm.min.y _ t.y; IF t.y > mm.max.y THEN mm.max.y _ t.y; IF t.z < mm.min.z THEN mm.min.z _ t.z; IF t.y > mm.max.y THEN mm.max.y _ t.y; ENDLOOP; }; END. ฎVector3dImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Bloomenthal, February 26, 1987 7:06:22 pm PST Basic Operations on a Single Vector Basic Operations on Two Vectors Length and Distance Operations Parallelness, Coplanarity and Collinearity Tests Compute determinant of matrix of vectors: Nearness Operations Simple Geometric Operations Polar/Cartesian Coordinates Copying Operations Miscellany ส 0˜šœ™Jšœ ฯmœ1™Jšœžœ/˜8Jšœžœ7˜@Jšœžœ/˜8Jšžœ žœ˜"Jšžœ˜J˜J˜—š œžœžœžœ ˜DJšœžœ#˜/šžœ˜Jšœ˜Jšœ ˜ Jšœ!˜!—J˜——šœ™š œž œžœ˜NLšœžœ˜šžœ žœžœ˜Lšœžœ ˜*L˜Lš žœžœžœžœžœ˜?L˜—Lšžœ˜ L˜L˜—š œž œžœ˜NLšœžœ˜šžœ žœžœ˜Lšœžœ ˜*Lšœ˜Lš žœžœžœžœžœ˜?L˜—Lšžœ˜ L˜L˜—š œž œžœ˜VLšœžœ˜šžœ žœžœ˜Lšœžœ$˜.Lšœ˜Lš žœžœžœžœžœ˜CL˜—Lšžœ˜ L˜——™ š œž œžœ žœžœžœžœ˜HJšœžœžœžœ ˜#Jšœžœ˜ Jšžœžœžœžœ˜JJ˜J˜—š  œž œžœžœ˜>Jšžœ$˜*J˜J™—š   œž œžœžœžœžœ˜SJšžœ)˜/J˜J™—š œž œžœ˜OJšœžœ˜J˜J˜šžœžœžœž˜$J˜Jšžœžœ˜&Jšžœžœ˜&Jšžœžœ˜&Jšžœžœ˜&Jšžœžœ˜&Jšžœžœ˜&Jšžœ˜—J˜J˜J˜——Jšžœ˜J˜J˜—…—‚(`