DIRECTORY Convert, G3dBasic, G3dCurve, G3dMatrix, G3dSpline, IO, Real, Rope; G3dCurveImpl: CEDAR PROGRAM IMPORTS Convert, G3dMatrix, G3dSpline, IO, Real, Rope EXPORTS G3dCurve ~ BEGIN Error: PUBLIC SIGNAL [code: ATOM, reason: ROPE ฌ NIL] = CODE; Triple: TYPE ~ G3dBasic.Triple; -- RECORD [x, y, z: REAL] RealSequence: TYPE ~ G3dBasic.RealSequence; -- sequence of reals Matrix: TYPE ~ G3dMatrix.Matrix; -- a cubic spline Spline: TYPE ~ G3dSpline.Spline; -- a cubic spline SplineSequence: TYPE ~ G3dSpline.SplineSequence; -- a sequence of cubic splines ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Curve: TYPE ~ G3dCurve.Curve; CurveRep: TYPE ~ G3dCurve.CurveRep; Section: TYPE ~ G3dCurve.Section; Fragment: TYPE ~ G3dCurve.Fragment; Fragments: TYPE ~ G3dCurve.Fragments; Spot: TYPE ~ G3dCurve.Spot; CurveSequence: TYPE ~ G3dCurve.CurveSequence; CurveSequenceRep: TYPE ~ G3dCurve.CurveSequenceRep; FSpot: TYPE ~ RECORD [f: Fragment, t: REAL]; CurveFromSplines: PUBLIC PROC [splines: SplineSequence, res: NAT ฌ 100] RETURNS [c: Curve] ~ { IF splines # NIL THEN { tmp: Spline ฌ G3dMatrix.ObtainMatrix[]; nSegs: NAT ฌ MAX[1, res]; lenSegs: NAT ฌ MAX[1, nSegs/2]; c ฌ NEW[CurveRep[splines.length]]; c.length ฌ splines.length; FOR s: NAT IN [0..splines.length) DO t0: REAL ฌ 0.0; spline: Spline ฌ splines[s]; fragments: Fragments ฌ NEW[G3dCurve.FragmentsRep[nSegs]]; c[s] ฌ [spline: spline, accumLength: c.totalLength, fragments: fragments]; FOR n: NAT IN [1..nSegs] DO t1: REAL ฌ REAL[n]/REAL[nSegs]; len: REAL ฌ G3dSpline.Length[G3dSpline.Reparameterize[spline, t0, t1, tmp], lenSegs]; fragments[n-1] ฌ [t0, t1, t1-t0, len, c.totalLength]; c.totalLength ฌ c.totalLength+len; t0 ฌ t1; ENDLOOP; c[s].length ฌ c.totalLength-c[s].accumLength; ENDLOOP; G3dMatrix.ReleaseMatrix[tmp]; }; }; Transform: PUBLIC PROC [curve: Curve, matrix: Matrix] ~ { IF curve # NIL THEN FOR n: NAT IN [0..curve.length) DO curve[n].spline ฌ G3dMatrix.Mul[curve[n].spline, matrix]; ENDLOOP; }; FSpotFromT: PROC [c: Curve, t: REAL] RETURNS [FSpot] ~ { n: NAT ฌ Real.Floor[t]; -- index to curve section tt: REAL ฌ t-n; -- tt = parameter into section fragments: Fragments ฌ c[MIN[n, c.length-1]].fragments; nf: NAT ฌ Real.Round[tt*fragments.length]; -- guess at fragment f: Fragment ฌ fragments[MIN[nf, fragments.length-1]]; WHILE tt NOT IN [f.t0..f.t1] DO -- ensure correct fragment f ฌ fragments[nf ฌ nf+(IF tt < f.t0 THEN -1 ELSE 1)]; ENDLOOP; RETURN[[f, tt]]; }; SpotFromT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [Spot] ~ { n: NAT ฌ Real.Floor[t]; RETURN[[c[n].spline, t-n]]; }; SpotFromArcLength: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [Spot ฌ []] ~ { SectionSpot: PROC [section: Section] RETURNS [spot: Spot] ~ { FragmentSpot: PROC [f: Fragment] RETURNS [Spot] ~ { RETURN[[section.spline, f.t0+f.dt*((arcLength-f.accumLength)/f.length)]]; }; f: Fragments ฌ section.fragments; spot.spline ฌ section.spline; FOR nf: NAT IN [1..f.length) DO IF f[nf].accumLength > arcLength THEN RETURN[FragmentSpot[f[nf-1]]]; ENDLOOP; RETURN[FragmentSpot[f[f.length-1]]]; }; IF arcLength < 0.0 THEN Error[$BadArcLength]; IF arcLength > c.totalLength THEN { s: Section ฌ c[c.length-1]; f: Fragment ฌ s.fragments[s.fragments.length-1]; IF arcLength-c.totalLength > f.length*0.1 -- arbitrary THEN Error[$BadArcLength] ELSE RETURN[[s.spline, f.t1]]; }; FOR n: NAT IN [1..c.length) DO IF c[n].accumLength > arcLength THEN RETURN[SectionSpot[c[n-1]]]; ENDLOOP; RETURN[SectionSpot[c[c.length-1]]]; }; TFromArcLength: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [t: REAL] ~ { RETURN[SpotFromArcLength[c, arcLength].t]; }; ArcLengthFromT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [REAL] ~ { fs: FSpot ฌ FSpotFromT[c, t]; RETURN[fs.f.accumLength+((fs.t-fs.f.t0)/fs.f.dt)*fs.f.length]; }; ArcLengthFromTs: PUBLIC PROC [c: Curve, t0, t1: REAL] RETURNS [REAL] ~ { RETURN[ArcLengthFromT[c, t1]-ArcLengthFromT[c, t0]]; }; PositionT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromT[c, t]; RETURN[G3dSpline.Position[s.spline, s.t]]; }; VelocityT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromT[c, t]; RETURN[G3dSpline.Position[s.spline, s.t]]; }; AccelerationT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromT[c, t]; RETURN[G3dSpline.Acceleration[s.spline, s.t]]; }; CurvatureT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromT[c, t]; RETURN[G3dSpline.Curvature[s.spline, s.t]]; }; CurvatureMagT: PUBLIC PROC [c: Curve, t: REAL] RETURNS [REAL] ~ { s: Spot ฌ SpotFromT[c, t]; RETURN[G3dSpline.CurvatureMag[s.spline, s.t]]; }; PositionA: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromArcLength[c, arcLength]; RETURN[G3dSpline.Position[s.spline, s.t]]; }; VelocityA: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromArcLength[c, arcLength]; RETURN[G3dSpline.Velocity[s.spline, s.t]]; }; AccelerationA: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromArcLength[c, arcLength]; RETURN[G3dSpline.Acceleration[s.spline, s.t]]; }; CurvatureA: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [Triple] ~ { s: Spot ฌ SpotFromArcLength[c, arcLength]; RETURN[G3dSpline.Curvature[s.spline, s.t]]; }; CurvatureMagA: PUBLIC PROC [c: Curve, arcLength: REAL] RETURNS [REAL] ~ { s: Spot ฌ SpotFromArcLength[c, arcLength]; RETURN[G3dSpline.CurvatureMag[s.spline, s.t]]; }; Write: PUBLIC PROC [out: STREAM, c: Curve, name: ROPE ฌ NIL] ~ { IF name # NIL THEN name ฌ Rope.Concat[name, " "]; IO.PutF[out, "Curve%g, %g sections:\n", IO.rope[name], IO.int[c.length]]; FOR n: NAT IN [0..c.length) DO spline: Spline ฌ c[n].spline; IO.PutRope[out, "\t"]; FOR i: NAT IN [0..4) DO r: ARRAY [0..4) OF REAL ฌ spline[i]; IO.PutFL[out, "%g %g %g %g ", LIST[IO.real[r[0]], IO.real[r[1]], IO.real[r[2]], IO.real[r[3]]]]; ENDLOOP; IO.PutRope[out, "\n"]; ENDLOOP; }; Read: PUBLIC PROC [in: STREAM] RETURNS [c: Curve] ~ { ENABLE IO.Error, Convert.Error => GOTO Bad; line: ROPE ฌ IO.GetLineRope[in]; p1: INT ฌ Rope.Find[line, "sections:"]; p0: INT ฌ Rope.FindBackward[line, " ", p1-2]; nSections: INT ฌ Convert.IntFromRope[Rope.Substr[line, p0, p1]]; splines: SplineSequence ฌ NEW[G3dSpline.SplineSequenceRep[nSections]]; FOR n: NAT IN [0..splines.length ฌ nSections) DO splines[n] ฌ NEW[G3dSpline.SplineRep]; FOR i: NAT IN [0..4) DO splines[n][i] ฌ [IO.GetReal[in], IO.GetReal[in], IO.GetReal[in], IO.GetReal[in]]; ENDLOOP; ENDLOOP; RETURN[CurveFromSplines[splines]]; EXITS Bad => Error[$BadInputFormat, IO.PutFR1["file position: %g", IO.int[IO.GetIndex[in]]]]; }; CopyCurveSequence: PUBLIC PROC [curves: CurveSequence] RETURNS [CurveSequence] ~ { copy: CurveSequence ฌ NIL; IF curves # NIL THEN { copy ฌ NEW[CurveSequenceRep[curves.length]]; copy.length ฌ curves.length; FOR n: NAT IN [0..curves.length) DO copy[n] ฌ curves[n]; ENDLOOP; }; RETURN[copy]; }; AddToCurveSequence: PUBLIC PROC [curves: CurveSequence, curve: Curve] RETURNS [CurveSequence] ~ { IF curves = NIL THEN curves ฌ NEW[CurveSequenceRep[1]]; IF curves.length = curves.maxLength THEN curves ฌ LengthenCurveSequence[curves]; curves[curves.length] ฌ curve; curves.length ฌ curves.length+1; RETURN[curves]; }; LengthenCurveSequence: PUBLIC PROC [curves: CurveSequence, amount: REAL ฌ 1.3] RETURNS [new: CurveSequence] ~ { newLength: CARDINAL ฌ Real.Ceiling[amount*curves.maxLength]; newLength ฌ MAX[newLength, 3]; new ฌ NEW[CurveSequenceRep[newLength]]; FOR i: NAT IN [0..curves.length) DO new[i] ฌ curves[i]; ENDLOOP; new.length ฌ curves.length; }; END. ( G3dCurveImpl.mesa Copyright ำ 1984, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, October 21, 1992 5:01 pm PDT Errors Definitions Creation Tranformation Support Conversions Between Arc-length and t Evaluation Given Parameter t Evaluation Given Arc Length IO Sequences ส 2–"cedarcode" style•NewlineDelimiter ™™Jšœ ฯeœ6™BJ™)J˜Jšฯk œC˜LJ˜—šะbl œžœž˜Jšžœ/˜6Jšžœ ˜J˜—Jšœž˜headšฯl™Jšฯnœžœžœžœ žœžœžœ˜@—š  ™ Jšœ žœฯcะcsข ฃข˜?Jšœ žœข˜BJšœ žœข˜8Jšœ žœข˜8Jšœžœข˜PJšžœžœžœ˜šžœžœžœžœ˜J˜—Jšœžœ˜ Jšœ žœ˜%Jšœ žœ˜%Jšœ žœ˜%Jšœ žœ˜'Jšœžœ˜Jšœžœ˜.šœžœ˜3J˜—Jšœ žœžœžœ˜0—š ™šกœžฯsžคœžคœคœคžœ ˜ZJšœ˜šžœ žœžœ˜J˜'Jšœžœžœ ˜Jšœ žœžœ ˜Jšœžœ˜"J˜šžœžœžœž˜$Jšœžœ˜J˜Jšœžœ˜9J˜Jšžœžœžœ ž˜Jšœžœžœžœ˜JšœžœL˜UJ˜5J˜"J˜Jšžœ˜—J˜-Jšžœ˜—J˜J˜—J˜——š  ™ šก œžœžœ#˜9š žœ žœžœžœžœžœž˜6J˜9Jšžœ˜—J˜——š ™šก œžœžœžœ ˜8Jšœžœข˜:Jšœžœข˜9Jšœžœ˜7Jšœžœ'ข˜BJšœžœ˜5š žœžœžœžœข˜BJšœžœ žœžœ˜6Jšžœ˜—Jšžœ ˜J˜——š $™$š ก œžœžœžœžœ ˜=Jšœžœ˜Jšžœ˜J˜J˜—šกœž œžœžœ˜Ršก œžœžœ˜=šก œžœžœ ˜3JšžœC˜IJ˜—J˜!J˜šžœžœžœž˜Jš žคœคœคœ คžคžœ˜DJšžœ˜—Jšžœ˜$Jšœ˜—Jšžœžœ˜-šžœžœ˜#J˜J˜0šžœ)ข ˜7Jšžœ˜Jšžœžœ˜—J˜—šžœžœžœž˜Jšžœžœžœ˜AJšžœ˜—Jšžœ˜#J˜J˜—š กœžœžœžœžœžœ˜MJšžœ$˜*J˜J˜—š กœžœžœžœžœžœ˜BJ˜Jšžœ8˜>J˜J˜—š กœžœžœžœžœžœ˜HJšžœ.˜4J˜——š ™š ก œžœžœžœžœ ˜?J˜Jšžœ$˜*J˜J˜—š ก œžœžœžœžœ ˜?J˜Jšžœ$˜*J˜J˜—š ก œžœžœžœžœ ˜CJ˜Jšžœ(˜.J˜J˜—š ก œžœžœžœžœ ˜@J˜Jšžœ%˜+J˜J™—š ก œžœžœžœžœžœ˜AJ˜Jšžœ(˜.J˜——š ™š ก œžœžœžœžœ ˜GJ˜*Jšžœ$˜*Jšœ˜J˜—š ก œžœžœžœžœ ˜GJ˜*Jšžœ$˜*J˜J˜—š ก œžœžœžœžœ ˜KJ˜*Jšžœ(˜.J˜J˜—š ก œžœžœžœžœ ˜HJ˜*Jšžœ%˜+J˜J™—š ก œžœžœžœžœžœ˜IJ˜*Jšžœ(˜.J˜——š ™š กœžœžœžœžœžœ˜@Jšžœžœžœ˜1Jšžœ&žœ žœ˜Išžœžœžœž˜J˜Jšžœ˜šžœžœžœž˜Jšœžœžœžœ ˜$šžœ˜Jš žœžœ žœ žœ žœ˜B—Jšžœ˜—Jšžœ˜Jšžœ˜—J˜J™—š กœžœžœžœžœ˜5Jšžœžœžœ˜+Jšœžœžœ˜ Jšœžœ ˜'Jšœžœ&˜-Jšœ žœ2˜@Jšœžœ)˜Fšžœžœžœ!ž˜0Jšœ žœ˜&šžœžœžœž˜Jš œžœžœžœžœ˜QJšžœ˜—Jšžœ˜—Jšžœ˜"Jšžœžœžœžœ˜]J˜——š  ™ šกœžœžœ˜6Jšžœ˜Jšœžœ˜šžœ žœžœ˜Jšœžœ"˜,J˜Jš žœžœžœžœžœ˜AJ˜—Jšžœ˜ J˜J˜—šกœžœžœ&˜EJšžœ˜J˜Jšžœ žœžœ žœ˜7Jšžœ"žœ(˜PJ˜J˜ Jšžœ ˜J˜J™—šกœžœžœ!žœ˜NJšžœ˜ Jšœ žœ)˜