DIRECTORY Real, RealFns, SVAngle; SVAngleImpl: PROGRAM IMPORTS Real, RealFns EXPORTS SVAngle = BEGIN Normalize: PUBLIC PROC [anyRange: REAL] RETURNS [range180: REAL] = { IF anyRange > 180 THEN { realNumberOf360s: REAL _ anyRange/360; fixNumberOf360s: NAT _ Real.FixC[realNumberOf360s];-- FixC truncates numberToSubtract: REAL _ fixNumberOf360s*360.0; RETURN[anyRange-numberToSubtract]; }; IF anyRange <= -180 THEN { 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] = { 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] = { increment _ 0; IF fromPosition < 0 THEN {-- start in lower semi-circle. 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. 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] = { increment _ 360 + ClockwiseAngle[fromPosition, toPostion]; IF increment = 360 THEN increment _ 0; }; ShortestDifference: PUBLIC PROC [position1, position2: REAL] RETURNS [pos1MinusPos2: REAL] = { clockwise: REAL _ ClockwiseAngle[position1, position2]; pos1MinusPos2 _ IF clockwise <= -180 THEN clockwise + 360 ELSE clockwise; }; Scale: PUBLIC PROC [angle: REAL, scalar: REAL] RETURNS [angleTimesScalar: REAL] = { angleTimesScalar _ angle*scalar; angleTimesScalar _ Normalize[angleTimesScalar]; }; ArcTan: PUBLIC PROC [numerator, denominator: REAL] RETURNS [degrees: REAL] = { degrees _ RealFns.ArcTanDeg[numerator, denominator]; degrees _ Normalize[degrees]; -- Normalize may not be needed. RealFns seems to do the right thing }; END. File: SVAngleImpl.mesa Last edited by Bier on June 1, 1984 4:30:45 pm PDT Author: Eric Bier on June 26, 1984 11:19:59 am PDT 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. Takes an angle in degrees and puts it in 180 < theta <= 180 form. Find the integer number of times 360 goes into it and subtract that many 360's. Find the integer number of times 360 goes into its negative and add (that many + 1) 360's. All angles in degrees All angles in degrees. -360 < increment <= 0 Proceed clockwise until you encounter theta = 180 or "toPostion". Proceed clockwise until you encounter "toPostion" or theta = 180 All angles in degrees. 0 <= increment < 360. For example, if the clockwise angle is -90, the counter-clockwise angle will be 270. All angles in degrees. RETURNS ClockwiseAngle or CounterClockwiseAngle. Whichever is smaller. -180< pos1MinusPos2 <= 180. All angles in degrees. Think of angle as the increment from 0 degrees to angle degrees. Scale this and normalize. Has the effect of calling RealFns.ArcTanDegrees and normalizing the result. Κ‰˜Iheadšœ™Jšœ2™2Jšœ2™2Jšœ’™’J˜šΟk ˜ Jšœ˜Jšœ˜Jšœ˜—J˜Jšœ ˜Jšœ˜Jšœ ˜Jš˜J˜š Οn œœœ œœ œ˜DJšœA™Ašœœ˜JšœO™OJšœœ˜&Jšœœ0˜DJšœœ˜/Jšœ˜"Jšœ˜—šœœ˜JšœZ™ZJšœœ˜'Jšœœ0˜DJšœ œ˜0Jšœ˜Jšœ˜—Jšœ˜Jšœ˜—J˜š žœœœœœœ˜NJšœ™JšœC˜CJšœœ$˜?Jšœœœ%˜GJšœ˜—J˜š žœœœœœ œ˜YJšœ,™,Jšœ˜šœœ ˜8JšœA™AJšœœœœ˜WJšœ/˜3Jšœœœœ˜OJšœ˜!Jšœ˜Jšœ˜—šœ!˜%Jšœ@™@Jšœœœœ!˜]Jšœœ˜&Jšœ˜—Jšœ˜—š žœœœœœ œ˜`Jšœ,™,JšœT™TJšœ:˜:Jšœœ˜&Jšœ˜—J˜š žœœœœœœ˜_Jšœ{™{Jšœ œ(˜7Jšœœœœ ˜IJšœ˜—J˜šžœœœ œ œœœ˜SJšœr™rJšœ ˜ Jšœ/˜/Jšœ˜—J˜š žœœœœœ œ˜NšœK™KJšœ4˜4Jšœb˜bJšœ˜——J˜Jšœ˜—…— Ž-