DIRECTORY CedarProcess, Commander, Controls, Convert, Draw2d, FileNames, G2dContour, G2dVector, G3dBasic, G3dMatrix, G3dSpline, G3dTool, G3dTube, G3dVector, Imager, ImplicitDefs, ImplicitDesign, ImplicitTube, IO, MessageWindow, Rope, ViewerTools; ImplicitScatterCmdImpl: CEDAR PROGRAM IMPORTS CedarProcess, Controls, Convert, Draw2d, FileNames, G2dContour, G2dVector, G3dMatrix, G3dSpline, G3dTool, G3dTube, G3dVector, Imager, ImplicitDesign, ImplicitTube, IO, MessageWindow, Rope, ViewerTools ~ BEGIN Button: TYPE ~ Controls.Button; ClickProc: TYPE ~ Controls.ClickProc; Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; Matrix: TYPE ~ G3dMatrix.Matrix; Tube: TYPE ~ G3dTube.Tube; ROPE: TYPE ~ Rope.ROPE; Point: TYPE ~ REF PointRep; PointRep: TYPE ~ RECORD [ history: LIST OF Triple ¬ NIL, pOld, pNew: Triple ¬ [], vOld, vNew: REAL ¬ 0.0, converged: BOOL ¬ FALSE ]; Points: TYPE ~ REF PointsRep; PointsRep: TYPE ~ RECORD [ length: CARDINAL ¬ 0, element: SEQUENCE maxLength: CARDINAL OF Point ]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ zDir: Triple ¬ [], nDisksB, deltaB, cResB: Button ¬ NIL, delta: REAL ¬ 0.001, nDisks, cRes: INTEGER ¬ 100, tube: Tube ¬ NIL, points: Points ¬ NIL, iterating, history: BOOL ¬ FALSE, tool: ImplicitDesign.Tool ¬ NIL ]; ScatterCommand: Commander.CommandProc ~ { d: Data ~ NEW[DataRep]; d.tool ¬ ImplicitDesign.MakeTool[ name: "Scatter Test", startProc: Start, valueProc: NIL, client: [data: d, draw: Draw], extraButtons: LIST[ Controls.ClickButton["Read Tube", ReadTube, d], Controls.ClickButton["Reset", Setup, d], Controls.ClickButton["Converge", Converge, d], Controls.ClickButton["Step", Step, d], d.nDisksB ¬ Controls.TextButton["NDisks", "10", Setup, d], d.cResB ¬ Controls.TextButton["CRes", "06", Setup, d], d.deltaB ¬ Controls.TextButton["Delta", Convert.RopeFromReal[d.delta], Setup, d], Controls.ClickButton["History On", History, d], Controls.ClickButton["IP Out", IPOut, d]] ]; }; Draw: Controls.DrawProc ~ { Xform: PROC [p: Triple] RETURNS [Pair] ~ {RETURN[G3dMatrix.TransformD[p, view]]}; ScreenSize: PROC [p: Triple] RETURNS [r: REAL] ~ { r ¬ G2dVector.Distance[Xform[p], Xform[G3dVector.ScaleRay[[p, d.zDir], 0.003]]]; r ¬ 0.5*r*r; }; Mark: PROC [t: Triple] ~ {Draw2d.Circle[context, Xform[t], ScreenSize[t], TRUE]}; Segment: PROC [p0, p1: Triple] ~ { Imager.SetStrokeWidth[context, MIN[ScreenSize[p0], ScreenSize[p1]]]; Imager.MaskVector[context, Xform[p0], Xform[p1]]; }; d: Data ¬ NARROW[clientData]; view: Matrix ¬ G3dTool.GetView[viewer].camera.matrix; IF d.points = NIL THEN RETURN; IF whatChanged = NIL THEN { vMat: Matrix ¬ G3dMatrix.Transpose[view, G3dMatrix.ObtainMatrix[]]; d.zDir ¬ G3dVector.Unit[G3dVector.Ortho[G3dMatrix.TransformVec[[0.0, 1.0, 0.0], vMat]]]; G3dMatrix.ReleaseMatrix[vMat]; }; IF d.history THEN FOR n: NAT IN [0..d.points.length) DO FOR l: LIST OF Triple ¬ d.points[n].history, l.rest WHILE l # NIL DO IF l.rest = NIL THEN Mark[l.first] ELSE Segment[l.first, l.rest.first]; ENDLOOP; ENDLOOP ELSE FOR n: NAT IN [0..d.points.length) DO p: Point ¬ d.points[n]; IF d.iterating THEN Segment[p.pOld, p.pNew] ELSE Mark[d.points[n].pNew]; ENDLOOP; }; ReadTube: ClickProc ~ { d: Data ¬ NARROW[clientData]; r: ROPE ¬ FileNames.ResolveRelativePath[Controls.TypescriptReadFileName[d.tool.tool3d.typescript]]; tube: Tube ¬ G3dTube.TubeFromFile[r]; IF tube = NIL THEN {Blink[Rope.Cat["\tCan't open ", r, "\n"]]; RETURN}; G3dTube.SelectAll[d.tube ¬ tube]; DoSetup[d]; }; Setup: ClickProc ~ {d: Data ¬ NARROW[clientData]; IF d.tube # NIL THEN DoSetup[d]}; History: ClickProc ~ { d: Data ¬ NARROW[clientData]; Controls.ButtonToggle[d.tool.tool3d.outerData,d.history¬NOT d.history,"History On","History Off"]; }; DoSetup: PROC [d: Data] ~ { ENABLE Convert.Error => {Blink["\tBad value"]; GOTO Bad}; d.cRes ¬ Convert.IntFromRope[ViewerTools.GetContents[d.cResB.textViewer]]; d.delta ¬ Convert.RealFromRope[ViewerTools.GetContents[d.deltaB.textViewer]]; d.nDisks ¬ Convert.IntFromRope[ViewerTools.GetContents[d.nDisksB.textViewer]]; ImplicitTube.PrepareTube[d.tube, d.tool.distanceMode, d.tool.measureMode]; ScatterPoints[d]; ImplicitDesign.Reset[d.tool]; EXITS Bad => NULL; }; Step: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; IF d.tube = NIL THEN Blink["\tNeed tube!"] ELSE [] ¬ Iterate[d]; }; IPOut: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; r: ROPE ¬ Controls.TypescriptReadFileName[NARROW[clientData, Data].tool.tool3d.typescript]; IF r # NIL THEN Draw2d.IPOut[r, Draw, clientData]; }; Converge: Controls.ClickProc ~ { d: Data ¬ NARROW[clientData]; IF d.tube = NIL THEN {Blink["\tNeed tube!"]; RETURN}; [] ¬ ImplicitDesign.MaybeFork[d.tool, ConvergeFork]; }; ConvergeFork: CedarProcess.ForkableProc ~ { d: Data ¬ NARROW[data]; MessageWindow.Append["\t# remaining:", TRUE]; d.iterating ¬ TRUE; DO CedarProcess.CheckAbort[]; IF Iterate[d] THEN EXIT; ENDLOOP; d.iterating ¬ FALSE; }; Iterate: PROC [d: Data] RETURNS [allConverged: BOOL ¬ TRUE] ~ { Sign: PROC [r: REAL] RETURNS [{pos, neg, zero}] ~ { RETURN[SELECT r FROM > 0.0 => pos, < 0.0 => neg, ENDCASE => zero]; }; nToDo: NAT ¬ 0; FOR n: NAT IN [0..d.points.length) DO p: Point ¬ d.points[n]; IF NOT p.converged THEN { gradient: Triple ¬ Gradient[d, p.pOld ¬ p.pNew, p.vOld ¬ p.vNew]; IF p.vOld < 0.0 THEN gradient ¬ G3dVector.Negate[gradient]; allConverged ¬ FALSE; nToDo ¬ nToDo+1; p.pNew ¬ G3dVector.Add[p.pOld, G3dVector.SetVectorLength[gradient, d.delta]]; p.vNew ¬ Value[d, p.pNew]; p.history ¬ CONS[p.pNew, p.history]; IF ABS[p.vNew] < 0.0001 OR p.vNew = p.vOld OR Sign[p.vNew] # Sign[p.vOld] THEN p.converged ¬ TRUE ELSE { p.pNew ¬ G3dVector.Interp[p.vOld/(p.vOld-p.vNew), p.pOld, p.pNew]; p.vNew ¬ Value[d, p.pNew]; IF Sign[p.vNew] # Sign[p.vOld] THEN p.converged ¬ TRUE; }; }; ENDLOOP; MessageWindow.Append[IO.PutFR[" %g", IO.int[nToDo]]]; ImplicitDesign.Repaint[d.tool, $NoClear]; }; Gradient: PROC [d: Data, p: Triple, v: REAL] RETURNS [Triple] ~ { RETURN[[ v-Value[d, [p.x+d.delta, p.y, p.z]], v-Value[d, [p.x, p.y+d.delta, p.z]], v-Value[d, [p.x, p.y, p.z+d.delta]]]]; }; Value: PROC [d: Data, p: Triple] RETURNS [REAL] ~ { t: ImplicitDesign.Tool ¬ d.tool; RETURN[ImplicitTube.SampleTube[ p, d.tube, t.measureMode, t.distanceMode, t.tolerance, t.spread].value]; }; ValueProc: ImplicitDefs.ValueProc ~ {RETURN[Value[NARROW[clientData], point]]}; ScatterPoints: PROC [d: Data] ~ { Spot: TYPE ~ RECORD [xyz: Triple, t, aLen: REAL]; Spots: TYPE ~ RECORD [element: SEQUENCE maxLength: CARDINAL OF Spot]; MakePoints: G3dTube.TubeProc ~ { Pos: PROC [t: REAL] RETURNS [p: Triple] ~ {p ¬ G3dSpline.Position[tube.spline, t]}; ApplyRefVec: G3dTube.TubeProc ~ {tube.refVec ¬ rv}; MakeDisk: PROC [t: REAL] ~ { v: Triple ¬ G3dVector.Unit[G3dSpline.Velocity[tube.spline, t]]; triad: G3dBasic.Triad ¬ G3dTube.Basis[v, vv, rv]; vv ¬ v; rv ¬ triad.n; refM ¬ G3dTube.RefMatrix[Pos[t], triad, G3dTube.Radius[tube, t], 0, refM]; ApplyCircle[circle]; }; ApplyCircle: PROC [circle: G3dBasic.PairSequence] ~ { FOR i: NAT IN [0..circle.length) DO AddPoint[G3dMatrix.TransformPair[circle[i], refM]]; ENDLOOP; }; AddPoint: PROC [point: Triple] ~ { p: Point ¬ d.points[pIndex]; p.pNew ¬ point; p.vNew ¬ Value[d, p.pNew]; p.history ¬ LIST[p.pNew]; p.converged ¬ FALSE; pIndex ¬ pIndex+1; }; rv: Triple ¬ tube.refVec; vv: Triple ¬ G3dVector.Unit[tube.v0]; totalLen, interDiskLen, accumLen: REAL ¬ 0.0; nDisks: NAT ¬ d.nDisks; IF tube.prev = NIL THEN nDisks ¬ nDisks-1; IF G3dTube.NBranches[tube, TRUE] # 0 THEN nDisks ¬ nDisks-1; IF tube.prev = NIL THEN { v: Triple ¬ G3dVector.Unit[tube.v0]; end: Triple ¬ G3dVector.Sub[tube.p0, G3dVector.SetVectorLength[tube.v0, tube.r0]]; mid: Triple ¬ G3dVector.Midpoint[end, tube.p0]; binormal: Triple ¬ G3dVector.Unit[G3dVector.Cross[v, rv]]; refM ¬ G3dTube.RefMatrix[mid, [v, rv, binormal], 0.5*tube.r0, 0, refM]; AddPoint[end]; ApplyCircle[smallCircle]; MakeDisk[0.0]; }; FOR i: NAT IN [1..nSpots) DO spots[i].xyz ¬ G3dSpline.Position[tube.spline, spots[i].t ¬ REAL[i]/REAL[nSpots-1]]; spots[i].aLen ¬ G3dVector.Distance[spots[i].xyz, spots[i-1].xyz]; totalLen ¬ totalLen+spots[i].aLen; ENDLOOP; interDiskLen ¬ totalLen/(d.nDisks-1); FOR n: NAT IN [1..nSpots-1) DO IF (accumLen ¬ accumLen+spots[n].aLen) > interDiskLen THEN {accumLen ¬ 0.0; MakeDisk[spots[n].t]}; ENDLOOP; IF G3dTube.NBranches[tube] = 0 THEN { v: Triple ¬ G3dVector.Unit[tube.v0]; end: Triple ¬ G3dVector.Add[tube.p1, G3dVector.SetVectorLength[tube.v1, tube.r1]]; mid: Triple ¬ G3dVector.Midpoint[end, tube.p1]; binormal: Triple ¬ G3dVector.Unit[G3dVector.Cross[v, rv]]; refM ¬ G3dTube.RefMatrix[mid, [v, rv, binormal], 0.5*tube.r1, 0, refM]; ApplyCircle[smallCircle]; AddPoint[end]; }; G3dTube.ApplyToBranches[tube, ApplyRefVec]; }; refM: G3dMatrix.Matrix ¬ G3dMatrix.ObtainMatrix[]; circle: G3dBasic.PairSequence ¬ G2dContour.Circle[d.cRes].pairs; smallCircle: G3dBasic.PairSequence ¬ G2dContour.Circle[d.cRes-1].pairs; nSpots: NAT ¬ 100*d.nDisks; spots: REF Spots ¬ NEW[Spots[nSpots]]; pIndex: NAT ¬ 0; nPoints: NAT ¬ (G3dTube.NTubes[d.tube]*d.nDisks)*d.cRes; d.tube.refVec ¬ G3dVector.Unit[G3dVector.Ortho[d.tube.v0]]; IF d.points = NIL OR nPoints > d.points.length THEN { d.points ¬ NEW[PointsRep[nPoints]]; FOR n: NAT IN [0..nPoints) DO d.points[n] ¬ NEW[PointRep]; ENDLOOP; }; d.points.length ¬ nPoints; G3dTube.ApplyToTube[d.tube, MakePoints]; G3dMatrix.ReleaseMatrix[refM]; }; Start: ImplicitDefs.StartProc ~ { ImplicitDesign.StopTool[NARROW[clientData, Data].tool]; Blink["\tThis function disabled when scattering"]; }; Blink: PROC [r: ROPE] ~ {MessageWindow.Append[r, TRUE]; MessageWindow.Blink[]}; ImplicitDesign.Register["Scatter", ScatterCommand, "scatter points and converge."]; END.  ImplicitScatterCmdImpl.mesa Copyright Σ 1989, 1990 by Xerox Corporation. All rights reserved. Bloomenthal, August 11, 1992 4:06 pm PDT Κ •NewlineDelimiter ™™J™BJ™(J˜JšΟk œν˜φJ˜—šΠblœœ˜%JšœΙ˜ΠJ˜—šœ˜J˜Jšœœ˜"Jšœ œ˜'Jšœœ˜Jšœ œ˜"Jšœ œ˜#Jšœœ˜šœœœ˜J˜—Jšœ œœ ˜šœ œœ˜Jšœœœ œ˜#J˜Jšœœ˜Jšœœ˜J˜J˜—Jšœ œœ ˜ šœ œœ˜Jšœ  œ˜Jšœ  œ œœ˜3J˜J˜—Jšœœœ ˜šœœœ˜J˜Jšœ"œ˜&Jšœ œ ˜Jšœ œ˜ Jšœœ˜Jšœœ˜Jšœœœ˜#Jšœ"˜%J˜J˜—šΟbœ˜)Jšœ œ ˜˜!J˜J˜Jšœ œ˜J˜šœœ˜J˜/J˜(J˜.J˜&J˜:J˜6J˜QJ˜/J˜)—J˜—J˜J˜—šΟnœ˜Jš œœ œ œ!˜Qš  œœ œœ˜2J˜PJ˜ J˜—Jš œΟs‘œ‘œ‘œ‘œ‘œ ‘œ‘œ˜Qš  œ‘‘œ‘œ‘œ‘œ˜"Jšœœ"˜DJ˜1J˜—Jšœ œ ˜J˜5Jšœ œœœ˜šœœœ˜J˜CJ˜XJ˜J˜—šœ ˜ š œœœœ˜*š œœœ&œœ˜DJšœ œœ ˜GJšœ˜—Jš˜—š œœœœ˜*J˜Jšœ œœ˜HJšœ˜——J˜J˜—šŸœ˜Jšœ œ ˜Jšœœ\˜cJ˜%Jšœœœ-œ˜GJ˜!J˜ J˜J˜—š  œœ œ œœ ˜SJ˜—š œ˜Jšœ œ ˜Jšœ8œ ‘ œ‘ œ˜bJ˜J˜—š œœ˜Jšœ)œ˜9J˜JJ˜MJ˜NJ˜JJ˜J˜Jšœœ˜J˜J˜—š œ˜Jšœ œ ˜Jšœ œœœ˜@J˜J˜—š œ˜Jšœ œ ˜Jšœœ#œ+˜[Jšœœœ#˜2J˜J˜—š œ˜ Jšœ œ ˜Jšœ œœœ˜5J˜4J˜J˜—š  œ˜+Jšœ œ˜Jšœ'œ˜-Jšœœ˜š˜J˜Jšœ œœ˜Jšœ˜—Jšœœ˜J˜J˜—š  œœ œœœ˜?š œœœœ˜3Jšœœœœ ˜BJ˜—Jšœœ˜šœœœ˜%J˜šœœ œ˜J˜AJšœœ'˜;Jšœœ˜J˜J˜MJ˜Jšœ œ˜$šœœœœ˜IJšœ˜šœ˜J•StartOfExpansion9[t: REAL, v1: G2dBasic.Triple, v2: G2dBasic.Triple]˜BJ˜Jšœœœ˜7J˜——J˜—Jšœ˜—Jšœœœ˜5J˜)J˜J˜—š œœœœ ˜Ašœ˜J˜$J˜$J˜&—J˜J˜—š œœœœ˜3J˜ šœ˜J˜H—J˜J˜—š  œœœ˜OJ˜—š  œœ˜!Jšœœœœ˜1Jš œœœ œ œœ˜Eš  œ˜ Jš œœœœ8˜SJš  œ(˜3š œœœ˜J˜?J˜1J˜J˜ J˜JJ˜J˜—š  œœ$˜5šœœœ˜#J˜3Jšœ˜—J˜—š œœ˜"J˜J˜J˜Jšœ œ ˜Jšœœ˜J˜J˜—J˜J˜%Jšœ"œ˜-Jšœœ ˜Jšœ œœ˜*Jš œ‘œ‘œ‘œ‘‘œ˜<šœ œœ˜J˜$J˜RJ˜/J˜:J˜GJ˜J˜J˜J˜—šœœœ ˜Jšœ<œœ ˜TJ˜AJ˜"Jšœ˜—J˜%šœœœ˜šœ3˜5Jšœ(˜,—Jšœ˜—šœœ˜%J˜$J˜RJ˜/J˜:J˜GJ˜J˜J˜—J˜+J˜—J˜2J˜@J˜GJšœœ˜Jšœœ œ˜&Jšœœ˜Jšœ œ,˜8J˜;šœ œœœ˜5Jšœ œ˜#Jš œœœœœ œ˜CJ˜—J˜J˜(J˜J˜J˜—š œ˜!Jšœœ˜7J˜2J˜J˜—Jš œœœœ˜OJ˜J˜SJ˜—šœ˜J™——…—&60ί