-- File: SVAngleImpl.mesa -- Last edited by Bier on December 18, 1982 1:08 am -- Author: Eric Bier on October 19, 1982 1:35 pm -- Contents: Solidviews requires a precise set of angle operations defined with angle "theta" in the range -180 < theta <= 180. "theta" is an absolute angle (ie a position around the circle). Given two positions angles T1 and T2 we can find the incremental clockwise angle CT between them or the incremental counter-clockwise angle CCT where -360 < CT <= 0 and 0 <= CCT < 360. When we add two angles, we are adding an incremental angle to a position angle to get a new position angle. We subtract two position angles to get an incremental angle. DIRECTORY Real, RealFns, SVAngle; SVAngleImpl: PROGRAM IMPORTS Real, RealFns EXPORTS SVAngle = BEGIN Normalize: PUBLIC PROC [anyRange: REAL] RETURNS [range180: REAL] = { -- takes an angle in degrees and puts it in 180 < theta <= 180 form. IF anyRange > 180 THEN { -- find the integer number of times 360 goes into it and subtract that many 360's. realNumberOf360s: REAL _ anyRange/360; fixNumberOf360s: NAT _ Real.FixC[realNumberOf360s]; -- FixC truncates numberToSubtract: REAL _ fixNumberOf360s*360.0; RETURN[anyRange-numberToSubtract]; }; IF anyRange <= -180 THEN { -- find the integer number of times 360 goes into its negative and add (that many + 1) 360's. realNumberOf360s: REAL _ -anyRange/360; fixNumberOf360s: NAT _ Real.FixC[realNumberOf360s]; -- FixC truncates numberToAdd: REAL _ (fixNumberOf360s + 1)*360.0; RETURN[anyRange+numberToAdd]; }; range180 _ anyRange }; -- end of Normalize Add: PUBLIC PROC [position, increment: REAL] RETURNS [finalPosition: REAL] = { -- all angles in degrees finalPosition _ position + increment; -- -540 < finalPosition < 540 IF finalPosition > 180 THEN finalPosition _ finalPosition - 360 ELSE IF finalPosition <= -180 THEN finalPosition _ finalPosition + 360; }; -- end of Add ClockwiseAngle: PUBLIC PROC [fromPosition, toPostion: REAL] RETURNS [increment: REAL] = { -- all angles in degrees. -360 < increment <= 0 increment _ 0; IF fromPosition < 0 THEN {-- start in lower semi-circle. -- proceed clockwise until you encounter theta = 180 or "toPostion". IF -180 < toPostion AND toPostion <= fromPosition THEN RETURN[toPostion - fromPosition] ELSE increment _ increment + (-180 - fromPosition); IF 0 <= toPostion AND toPostion <= 180 THEN RETURN[increment + (toPostion-180)] ELSE increment _ increment + 180; RETURN[increment + toPostion]; } ELSE { -- start in upper semi-circle. -- proceed clockwise until you encounter "toPostion" or theta = 180 IF fromPosition < toPostion AND toPostion <= 180 THEN RETURN [toPostion - fromPosition - 360] ELSE RETURN[toPostion - fromPosition]; }; }; -- end of ClockwiseAngle CounterClockwiseAngle: PUBLIC PROC [fromPosition, toPostion: REAL] RETURNS [increment: REAL] = { -- all angles in degrees. 0 <= increment < 360. -- For example, if the clockwise angle is -90, the counter-clockwise angle will be 270. increment _ 360 + ClockwiseAngle[fromPosition, toPostion]; IF increment = 360 THEN increment _ 0; }; ShortestDifference: PUBLIC PROC [position1, position2: REAL] RETURNS [pos1MinusPos2: REAL] = { -- all angles in degrees. RETURNS ClockwiseAngle or CounterClockwiseAngle. Whichever is smaller. -180< pos1MinusPos2 <= 180. clockwise: REAL _ ClockwiseAngle[position1, position2]; pos1MinusPos2 _ IF clockwise <= -180 THEN clockwise + 360 ELSE clockwise; }; Scale: PUBLIC PROC [angle: REAL, scalar: REAL] RETURNS [angleTimesScalar: REAL] = { -- all angles in degrees. Think of angle as the increment from 0 degrees to angle degrees. Scale this and normalize. angleTimesScalar _ angle*scalar; angleTimesScalar _ Normalize[angleTimesScalar]; }; ArcTan: PUBLIC PROC [numerator, denominator: REAL] RETURNS [degrees: REAL] = { -- has the effect of calling RealFns.ArcTanDegrees and normalizing the result. degrees _ RealFns.ArcTanDeg[numerator, denominator]; degrees _ Normalize[degrees]; -- Normalize may not be needed. RealFns seems to do the right thing }; END. Źķ˜JšäĻcūœ«Ļk œ*žœžœžœ žœĻn œžœžœ žœžœ žœEœžœžœSœžœ$žœ œžœžœ#žœžœ^œžœ%žœ œžœ"žœ6œŸœžœžœžœžœžœœ'œžœžœ'žœžœžœ*œŸœžœžœžœžœ žœ0œžœžœœEœžœžœžœžœžœ2žœžœžœžœ!žœ žœžœœDœžœžœžœžœ&žœžœ%œŸœžœžœžœžœ žœ0œXœ=žœžœŸœžœžœžœžœžœœ žœ:žœžœžœŸœžœžœ žœ žœžœžœvœYŸœžœžœžœžœ žœOœUEœžœ˜Ø —…—*