<> <> <> DIRECTORY Commander, Controls, Controls3d, Draw2d, Draw3d, Imager, IO, Matrix3d, Print3d, Real, RealFns, Random, Spline3d, SplineStructure, Vector3d, ViewerOps; ContoursRandomImpl: CEDAR PROGRAM IMPORTS Commander, Controls, Controls3d, Draw2d, Draw3d, Print3d, Random, Real, RealFns, Spline3d, SplineStructure, Vector3d, ViewerOps ~ BEGIN gaussArray: Spline3d.RealSequence _ InitGaussSequence[1024]; Triple: TYPE ~ Vector3d.Triple; Coeffs: TYPE ~ Spline3d.Coeffs; Bezier: TYPE ~ Spline3d.Bezier; Box: TYPE ~ RECORD [a, b, c, d: Triple]; BoxSequence: TYPE ~ REF BoxSequenceRec; BoxSequenceRec: TYPE ~ RECORD [element: SEQUENCE maxLength: NAT OF Box]; SplineData: TYPE ~ SplineStructure.SplineData; SplineDataRec: TYPE ~ SplineStructure.SplineDataRec; ProgramData: TYPE ~ REF ProgramDataRec; ProgramDataRec: TYPE ~ RECORD [ out: IO.STREAM _ NIL, outer, graphics: Controls.Viewer _ NIL, entries: LIST OF Controls.Entry _ NIL, mouse: SplineStructure.Mouse _ [0, 0, none, left], cam: Controls3d.Camera, -- camera hold: Controls3d.Hold, -- handle on a point and its tangent nSpl: Controls.ControlData _ NIL, -- number of new splines from old one nRec: Controls.ControlData _ NIL, -- number of recursive levels graphicsData: Controls.GraphicsData _ NIL, view: Matrix3d.Matrix _ NIL, recurse: BOOL _ FALSE, noPick: BOOL _ TRUE, s: SplineData _ NIL, -- all the contour splines pd: SplineStructure.PickData _ NIL ]; Contour: Commander.CommandProc ~ { d: ProgramData _ NEW[ProgramDataRec]; d.out _ cmd.err; d.pd _ NEW[SplineStructure.PickDataRec]; d.view _ NEW[Matrix3d.MatrixRep]; d.s _ NEW[SplineDataRec]; d.cam _ Controls3d.InitCamera[dz: 0.5, zoom: 3., fov: 0., proc: Controller, data: d]; d.hold _ Controls3d.InitHold[Controller, d]; d.pd.s _ SplineStructure.contour _ d.s; d.s.c _ Spline3d.CoeffsFromHermite[[[-0.5, 0., 0.], [0.5, 0., 0.], [1., 1., 0.], [1., -1., 0.]]]; d.nSpl _ Controls.NewControl["nSpl", vert, , 2.0, 15.0, 4.0, TRUE, , , Controller, d]; d.nRec _ Controls.NewControl["nRec", vert, , 1.0, 15.0, 1.0, TRUE, , , Controller, d]; SplineStructure.PointPick[d.pd]; Controls3d.FocusHold[d.pd.tan, d.hold]; Controls.ControlRow[d.cam.pan, 2]; d.outer _ Controls.OuterViewer[ name: "Contour", column: left, entries: LIST[ ["Recurse", Recurse], ["Randomize", Randomize], ["PickToggle", PickToggle], ["Reset", Reset], ["PrintC", PrintC]], controls: LIST[ d.hold.x, d.hold.y, d.hold.z, d.hold.lng, d.hold.lat, d.hold.mag, d.nSpl, d.nRec, d.cam.xRot, d.cam.yRot, d.cam.zRot, d.cam.scale, d.cam.x, d.cam.y, d.cam.z, d.cam.fov], graphicsHeight: 300, graphicsProc: ScreenPick, graphicsShow: Display, data: d]; d.entries _ NARROW[d.outer.data, Controls.OuterData].entries; d.graphics _ NARROW[d.outer.data, Controls.OuterData].graphics; d.graphicsData _ NARROW[d.graphics.data]; }; Controller: PUBLIC Controls.ControlProc ~ { d: ProgramData _ NARROW[control.data]; IF d.pd.dividePending THEN { SplineStructure.DivideSpline[d.pd]; Controls.ControlVal[d.hold.mag, Vector3d.Mag[d.pd.sPt0.v1]]; }; SELECT control FROM d.hold.x, d.hold.y, d.hold.z => SplineStructure.ChangePosition[d.s, d.pd, [d.hold.x.val, d.hold.y.val, d.hold.z.val]]; d.hold.lng, d.hold.lat, d.hold.mag => IF NOT d.noPick THEN SplineStructure.ChangeTangent[ d.s, d.pd, Vector3d.CartesianFromPolar[[d.hold.lng.val, d.hold.lat.val, d.hold.mag.val]]]; d.cam.xRot, d.cam.yRot, d.cam.zRot, d.cam.scale, d.cam.x, d.cam.y, d.cam.z, d.cam.fov => Controls3d.UpDateCamera[d.cam]; ENDCASE => NULL; ViewerOps.PaintViewer[control.graphics, client, FALSE, control]; }; ScreenPick: Controls.GraphicsProc ~ { d: ProgramData _ NARROW[graphics.data]; IF graphics.mouse.state = up THEN RETURN; IF graphics.mouse.button = left THEN { SplineStructure.ScreenPick[d.s, graphics.mouse, d.view, d.pd]; Controls3d.FocusHold[d.pd.tan, d.hold]; }; }; PickToggle: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; d.noPick _ NOT d.noPick; ViewerOps.PaintViewer[d.graphics, client, FALSE, d]; }; PrintC: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; FOR s: SplineData _ d.s, s.next WHILE s # NIL DO Print3d.Matrix[d.out, s.c]; ENDLOOP; }; Reset: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; SplineStructure.contour _ d.s _ NEW[SplineDataRec]; (d.pd.s _ d.s).c _ Spline3d.CoeffsFromHermite[[[-0.5,0.,0.], [0.5,0.,0.], [1.,1.,0.], [1.,-1.,0.]]]; ViewerOps.PaintViewer[d.graphics, client, FALSE, d]; }; Recurse: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; d.recurse _ TRUE; ViewerOps.PaintViewer[d.graphics, client, FALSE, d]; d.recurse _ FALSE; }; Randomize: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; s: SplineData _ d.s; WHILE s # NIL DO r: SplineData _ RandomizeSpline[s.c, Real.RoundI[d.nSpl.val]]; r.prev _ s.prev; IF s.prev # NIL THEN s.prev.next _ r ELSE SplineStructure.contour _ d.s _ r; WHILE r.next # NIL DO r _ r.next; ENDLOOP; IF s.next # NIL THEN s.next.prev _ r; s _ r.next _ s.next; ENDLOOP; ViewerOps.PaintViewer[d.graphics, client, FALSE, d]; }; InsertSpline: PROC [insert, splines: SplineData] RETURNS [SplineData] ~ { <> s: SplineData _ splines; IF splines = NIL THEN RETURN[insert]; WHILE s.next # NIL DO s _ s.next; ENDLOOP; insert.prev _ s; insert.next _ s.next; s.next _ insert; IF insert.next # NIL THEN insert.next.prev _ insert; RETURN[splines]; }; RandomizeSpline: PROC [c: Coeffs, nSplines: INTEGER _ 2] RETURNS [SplineData] ~ { splines: SplineData _ NIL; coeffs: Spline3d.CoeffsSequence; bez: Bezier _ Spline3d.BezierFromCoeffs[c]; boxes: BoxSequence _ BoxesFromBezier[bez, nSplines]; knots: Spline3d.KnotSequence _ NEW[Spline3d.KnotSequenceRep[nSplines+1]]; scale: REAL _ 3.0/REAL[MAX[1, nSplines]]; tan0: Triple _ Vector3d.Mul[Vector3d.Sub[bez.b1, bez.b0], scale]; tan1: Triple _ Vector3d.Mul[Vector3d.Sub[bez.b3, bez.b2], scale]; IF nSplines = 0 THEN RETURN[splines]; knots[0] _ bez.b0; FOR n: NAT IN [1..nSplines) DO knots[n] _ RandomPtInBox[boxes[n-1]]; ENDLOOP; knots[nSplines] _ bez.b3; knots.length _ nSplines+1; coeffs _ Spline3d.Interpolate[knots, tan0, tan1]; FOR n: NAT IN [0..nSplines) DO insert: SplineData _ NEW[SplineDataRec]; insert.c _ coeffs[n]; splines _ InsertSpline[insert, splines]; ENDLOOP; RETURN[splines]; }; BoxesFromBezier: PROC [bez: Bezier, nBoxes: NAT] RETURNS [BoxSequence] ~ { boxes: BoxSequence _ NEW[BoxSequenceRec[nBoxes]]; p0: Triple _ bez.b0; p1: Triple _ bez.b1; dp0: Triple _ Vector3d.Div[Vector3d.Sub[bez.b3, bez.b0], REAL[nBoxes]]; dp1: Triple _ Vector3d.Div[Vector3d.Sub[bez.b2, bez.b1], REAL[nBoxes]]; FOR n: NAT IN [0..nBoxes) DO pp0: Triple _ Vector3d.Add[p0, dp0]; pp1: Triple _ Vector3d.Add[p1, dp1]; boxes[n] _ [p0, p1, pp1, pp0]; p0 _ pp0; p1 _ pp1; ENDLOOP; RETURN[boxes]; }; RanR: PROC RETURNS [REAL] ~ {RETURN[gaussArray[Random.ChooseInt[min: 0, max: 1023]]]}; RandomPtInSegment: PROC [p0, p1: Triple] RETURNS[Triple] ~ { w: REAL _ RanR[]; RETURN[Vector3d.Add[Vector3d.Mul[p0, w], Vector3d.Mul[p1, 1.0-w]]]; }; RandomPtInBox: PROC [box: Box] RETURNS[t: Triple] ~ { w0: REAL _ RanR[]; w1: REAL _ RanR[]; w2: REAL _ RanR[]; w3: REAL _ RanR[]; n: REAL _ 1.0/(w0+w1+w2+w3); w0 _ w0*n; w1 _ w1*n; w2 _ w2*n; w3 _ w3*n; t.x _ box.a.x*w0+box.b.x*w1+box.c.x*w2+box.d.x*w3; t.y _ box.a.y*w0+box.b.y*w1+box.c.y*w2+box.d.y*w3; t.z _ box.a.z*w0+box.b.z*w1+box.c.z*w2+box.d.z*w3; }; Function: PROC [x: REAL] RETURNS [REAL] ~ { <> x _ 2.0*3.1415926535*(x-0.5); RETURN[0.5*(1.0+RealFns.Sin[x]+RealFns.Cos[x])]; }; Display: Controls.GraphicsShow ~ { d: ProgramData _ NARROW[data]; Action: PROC ~ { d.view _ Controls3d.InitPix[context, w, h]; IF d.recurse THEN { p, q: Triple _ [0.0, 0.0, 0.0]; FOR i: NAT IN [0..100) DO q.x _ REAL[i-50]/100.0; q.y _ 0.5+q.x; FOR n: NAT IN[1..Real.RoundI[d.nRec.val]] DO q.y _ Function[q.y]; ENDLOOP; q.y _ 0.5*q.y; IF i > 0 THEN Draw3d.PP[p, q, context, d.view]; p _ q; ENDLOOP; } ELSE FOR s: SplineData _ d.s, s.next WHILE s # NIL DO Draw3d.DrawBezierPolygon[Spline3d.BezierFromCoeffs[s.c], context, d.view, dot]; Draw3d.DrawCurve[s.c, context, d.view]; ENDLOOP; IF NOT d.noPick THEN Draw3d.PV[d.pd.pos, d.pd.tan,, context, d.view, IF d.pd.t IN(0.0..1.0) THEN cross ELSE none]; }; Draw2d.DoWithBuffer[context, Action, w, h] }; InitGaussSequence: PROC [nEntries: NAT] RETURNS [Spline3d.RealSequence] ~ { x: REAL _ 0.0; sigma: REAL ~ 0.16; dx: REAL _ 1.0/REAL[nEntries]; ret: Spline3d.RealSequence _ NEW[Spline3d.RealSequenceRec[nEntries]]; FOR i: NAT IN [0..1024) DO xx: REAL _ x-0.5; ret[i] _ RealFns.Exp[-xx*xx/(2.0*sigma*sigma)]; x _ x+dx; ENDLOOP; RETURN[ret]; }; Commander.Register["Contour", Contour, "\nTest some contour ideas."]; END. .. <> <> <> <> <> <> <> <<>> <> <> <<>> <> <<>> <> <> <<>> <> <> <> <<>> <> <> <> <> <> <<>> <> <<};>> <> <> <> <> <> <> <<};>> <> <> <> < 0 AND roots.r1 IN [0.0..1.0] THEN CheckI[roots.r1];>> < 1 AND roots.r2 IN [0.0..1.0] THEN CheckI[roots.r2];>> <<};>> <> <> <<};>> <<>>