<> <> <> <> DIRECTORY RealFns, GGModelTypes, GGAngle, GGVector; GGVectorImpl: CEDAR PROGRAM IMPORTS RealFns, GGAngle EXPORTS GGVector = BEGIN Point: TYPE = GGModelTypes.Point; Edge: TYPE = GGModelTypes.Edge; Vector: TYPE = GGModelTypes.Vector; VectorFromPoints: PUBLIC PROC [tail, head: Point] RETURNS [vector: Vector] = CHECKED { vector[1] _ head[1] - tail[1]; vector[2] _ head[2] - tail[2]; }; VectorFromAngle: PUBLIC PROC [angle: REAL] RETURNS [vector: Vector] = CHECKED { <> <> vector[1] _ RealFns.CosDeg[angle]; vector[2] _ RealFns.SinDeg[angle]; }; VectorPlusAngle: PUBLIC PROC [v: Vector, degrees: REAL] RETURNS [rotatedV: Vector] = CHECKED { <> 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: Vector] RETURNS [position: REAL] = CHECKED { <> position _ GGAngle.ArcTan[v[2], v[1]]; }; AngleCCWBetweenVectors: PUBLIC PROC [v1, v2: Vector] RETURNS [difference: REAL] = CHECKED { <> angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ GGAngle.CounterClockwiseAngle[angle1, angle2]; }; AngleCWBetweenVectors: PUBLIC PROC [v1, v2: Vector] RETURNS [difference: REAL] = CHECKED { <> angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ GGAngle.ClockwiseAngle[angle1, angle2]; }; SmallestAngleBetweenVectors: PUBLIC PROC [v1, v2: Vector] RETURNS [difference: REAL] = CHECKED { <> angle1, angle2: REAL; angle1 _ AngleFromVector[v1]; angle2 _ AngleFromVector[v2]; difference _ GGAngle.ShortestDifference[angle1, angle2]; }; Add: PUBLIC PROC [v1, v2: Vector] RETURNS [v1PlusV2: Vector] = CHECKED { v1PlusV2[1] _ v1[1] + v2[1]; v1PlusV2[2] _ v1[2] + v2[2]; }; Sub: PUBLIC PROC [v1, v2: Vector] RETURNS [v1MinusV2: Vector] = CHECKED { v1MinusV2[1] _ v1[1] - v2[1]; v1MinusV2[2] _ v1[2] - v2[2]; }; Scale: PUBLIC PROC[v: Vector, s: REAL] RETURNS [vTimesS: Vector] = CHECKED { vTimesS[1] _ v[1]*s; vTimesS[2] _ v[2]*s; }; Normalize: PUBLIC PROC [v: Vector] RETURNS [normV: Vector] = CHECKED { mag: REAL _ Magnitude[v]; normV[1] _ v[1] / mag; normV[2] _ v[2] /mag; }; Negate: PUBLIC PROC [v: Vector] RETURNS [negV: Vector] = CHECKED { negV[1] _ -v[1]; negV[2] _ -v[2]; }; ElementwiseProduct: PUBLIC PROC [v1, v2: Vector] RETURNS [v1Timesv2: Vector] = CHECKED { v1Timesv2[1] _ v1[1]*v2[1]; v1Timesv2[2] _ v1[2]*v2[2]; }; DotProduct: PUBLIC PROC [v1, v2: Vector] RETURNS [scalar: REAL] = CHECKED { scalar _ v1[1]*v2[1] + v1[2]*v2[2]; }; Magnitude: PUBLIC PROC [v: Vector] RETURNS [mag: REAL] = CHECKED { mag _ RealFns.SqRt[v[1]*v[1] + v[2]*v[2]]; }; Distance: PUBLIC PROC [p1, p2: Point] RETURNS [dist: REAL] = CHECKED { dist _ Magnitude[Sub[p2, p1]]; }; MagnitudeSquared: PUBLIC PROC [v: Vector] RETURNS [magSquared: REAL] = CHECKED { magSquared _ v[1]*v[1] + v[2]*v[2]; }; DistanceSquared: PUBLIC PROC [p1, p2: Point] RETURNS [distSquared: REAL] = CHECKED { distSquared _ MagnitudeSquared[Sub[p2, p1]]; }; RightNormalOfEdge: PUBLIC PROC [edge: Edge] RETURNS [normal: Vector] = CHECKED { <> direction: Vector; IF edge.startIsFirst THEN direction _ VectorFromPoints[tail: edge.start, head: edge.end] ELSE direction _ VectorFromPoints[tail: edge.end, head: edge.start]; normal[1] _ direction[2]; normal[2] _ -direction[1]; }; LeftNormalOfEdge: PUBLIC PROC [edge: Edge] RETURNS [normal: Vector] = CHECKED { <> direction: Vector; IF edge.startIsFirst THEN direction _ VectorFromPoints[tail: edge.start, head: edge.end] ELSE direction _ VectorFromPoints[tail: edge.end, head: edge.start]; normal[1] _ -direction[2]; normal[2] _ direction[1]; }; END.