DIRECTORY RealFns, SV2d, SVAngle, SVVector2d; SVVector2dImpl: CEDAR PROGRAM IMPORTS RealFns, SVAngle EXPORTS SVVector2d = BEGIN Point2d: TYPE = SV2d.Point2d; TrigLineSeg: TYPE = SV2d.TrigLineSeg; Vector2d: TYPE = SV2d.Vector2d; VectorFromPoints: PUBLIC PROC [tail, head: Point2d] RETURNS [vector: Vector2d] = { vector[1] _ head[1] - tail[1]; vector[2] _ head[2] - tail[2]; }; VectorFromAngle: PUBLIC PROC [angle: REAL] RETURNS [vector: Vector2d] = { vector[1] _ RealFns.CosDeg[angle]; vector[2] _ RealFns.SinDeg[angle]; }; VectorPlusAngle: PUBLIC PROC [v: Vector2d, degrees: REAL] RETURNS [rotatedV: Vector2d] = { theta: REAL _ RealFns.ArcTanDeg[v[2], v[1]]; angleSum: REAL _ theta + degrees; IF angleSum<= -180 THEN angleSum _ angleSum + 360 ELSE IF angleSum > 180 THEN angleSum _ angleSum - 360; rotatedV _ VectorFromAngle[angleSum]; }; AngleFromVector: PUBLIC PROC [v: Vector2d] RETURNS [position: REAL] = { position _ SVAngle.ArcTan[v[2], v[1]]; }; AngleCCWBetweenVectors: PUBLIC PROC [v1, v2: Vector2d] RETURNS [difference: REAL] = { angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ SVAngle.CounterClockwiseAngle[angle1, angle2]; }; AngleCWBetweenVectors: PUBLIC PROC [v1, v2: Vector2d] RETURNS [difference: REAL] = { angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ SVAngle.ClockwiseAngle[angle1, angle2]; }; SmallestAngleBetweenVectors: PUBLIC PROC [v1, v2: Vector2d] RETURNS [difference: REAL] = { angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ SVAngle.ShortestDifference[angle1, angle2]; }; Add: PUBLIC PROC [v1, v2: Vector2d] RETURNS [v1PlusV2: Vector2d] = { v1PlusV2[1] _ v1[1] + v2[1]; v1PlusV2[2] _ v1[2] + v2[2]; }; Sub: PUBLIC PROC [v1, v2: Vector2d] RETURNS [v1MinusV2: Vector2d] = { v1MinusV2[1] _ v1[1] - v2[1]; v1MinusV2[2] _ v1[2] - v2[2]; }; Scale: PUBLIC PROC[v: Vector2d, s: REAL] RETURNS [vTimesS: Vector2d] = { vTimesS[1] _ v[1]*s; vTimesS[2] _ v[2]*s; }; Normalize: PUBLIC PROC [v: Vector2d] RETURNS [normV: Vector2d] = { mag: REAL _ Magnitude[v]; normV[1] _ v[1] / mag; normV[2] _ v[2] /mag; }; Negate: PUBLIC PROC [v: Vector2d] RETURNS [negV: Vector2d] = { negV[1] _ -v[1]; negV[2] _ -v[2]; }; ElementwiseProduct: PUBLIC PROC [v1, v2: Vector2d] RETURNS [v1Timesv2: Vector2d] = { v1Timesv2[1] _ v1[1]*v2[1]; v1Timesv2[2] _ v1[2]*v2[2]; }; DotProduct: PUBLIC PROC [v1, v2: Vector2d] RETURNS [scalar: REAL] = { scalar _ v1[1]*v2[1] + v1[2]*v2[2]; }; Magnitude: PUBLIC PROC [v: Vector2d] RETURNS [mag: REAL] = { mag _ RealFns.SqRt[v[1]*v[1] + v[2]*v[2]]; }; Distance: PUBLIC PROC [p1, p2: Point2d] RETURNS [dist: REAL] = { dist _ Magnitude[Sub[p2, p1]]; }; MagnitudeSquared: PUBLIC PROC [v: Vector2d] RETURNS [magSquared: REAL] = { magSquared _ v[1]*v[1] + v[2]*v[2]; }; DistanceSquared: PUBLIC PROC [p1, p2: Point2d] RETURNS [distSquared: REAL] = { distSquared _ MagnitudeSquared[Sub[p2, p1]]; }; RightNormalOfTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg] RETURNS [normal: Vector2d] = { direction: Vector2d; IF seg.pLoIsFirst THEN direction _ VectorFromPoints[tail: seg.pLo, head: seg.pHi] ELSE direction _ VectorFromPoints[tail: seg.pHi, head: seg.pLo]; normal[1] _ direction[2]; normal[2] _ -direction[1]; }; LeftNormalOfTrigLineSeg: PUBLIC PROC [seg: TrigLineSeg] RETURNS [normal: Vector2d] = { direction: Vector2d; IF seg.pLoIsFirst THEN direction _ VectorFromPoints[tail: seg.pLo, head: seg.pHi] ELSE direction _ VectorFromPoints[tail: seg.pHi, head: seg.pLo]; normal[1] _ -direction[2]; normal[2] _ direction[1]; }; END. 2File: SVVector2dImpl.mesa Last edited by Bier on June 1, 1984 4:36:10 pm PDT Author: Eric Bier on January 28, 1987 2:26:31 pm PST Contents: Routines for manipulation vectors in two dimensions angle must be in degrees in the range: -180 < angle <= 180. vector is a unit vector. Find angle of v. This should be easy. Normalize v and its components will be cos(theta), sin(theta) respectively. position is a position angle such that -180 < position <= 180 difference will be in: 0 <= difference < 360. A clockwise angle difference will be in: 0 <= difference < 360. A counter-clockwise angle all angles in degrees. RETURNS ClockwiseAngle or CounterClockwiseAngle. Whichever is smaller. -180 < difference <= 180. Given the ordered points of the line segment, we can find the vector from the first to the second. If this vector is [a, b] then the vector 90 degrees to the right is [b, -a]; Given the ordered points of the line segment, we can find the vector from the first to the second. If this vector is [a, b] then the vector 90 degrees to the left is [-b, a]; Κ#– "cedar" style˜Iheadšœ™Iprocšœ2™2Lšœ4™4Lšœ=™=L˜šΟk ˜ Lšœ#˜#—L˜Lšœ ˜Lšœ˜Lšœ ˜L˜Lš˜˜Lšœ œ˜Lšœ œ˜%Lšœ œ˜L˜—šΟnœœœœ˜RLšœ˜Lšœ˜Lšœ˜—š žœœœ œœ˜ILšœ;™;Lšœ™Lšœ"˜"Lšœ"˜"Lšœ˜—š žœœœœœ˜ZLšœs™sLšœœ!˜,Lšœ œ˜!Lšœœ˜1Lšœœœ˜6Lšœ%˜%Lšœ˜—L˜š žœœœœ œ˜GLšœ=™=Lšœ&˜&Lšœ˜—š žœœœœœ˜ULšœ@™@Lšœœ˜Lšœ˜Lšœ˜Lšœ;˜;Lšœ˜—š žœœœœœ˜TLšœH™HLšœœ˜Lšœ˜Lšœ˜Lšœ4˜4Lšœ˜—L˜š žœœœœœ˜ZLšœy™yLšœœ˜Lšœ˜Lšœ˜Lšœ8˜8Lšœ˜—L˜šžœœœœ˜DLšœ˜Lšœ˜Lšœ˜—šžœœœœ˜ELšœ˜Lšœ˜Lšœ˜—L˜š žœœœœœ˜HLšœ˜Lšœ˜Lšœ˜—L˜šž œœœœ˜BLšœœ˜Lšœ˜Lšœ˜Lšœ˜L˜—šžœ œœ˜>Lšœ˜Lšœ˜L˜—L˜šžœœœœ˜TLšœ˜Lšœ˜Lšœ˜—š ž œœœœ œ˜ELšœ#˜#Lšœ˜—L˜š ž œœœœœ˜=Lšœ*˜*Lšœ˜—š žœœœœœ˜@Lšœ˜L˜L˜—š žœœœœœ˜JLšœ#˜#Lšœ˜—š žœœœœœ˜NLšœ,˜,L˜L˜—L˜šžœœœœ˜WLšœ°™°Lšœ˜Lšœœ<˜RLšœ=˜ALšœ˜Lšœ˜Lšœ˜L˜—šžœœœœ˜VLšœ―™―Lšœ˜Lšœœ<˜RLšœ=˜ALšœ˜Lšœ˜Lšœ˜—L˜L˜Lšœ˜—…— u