<<>> <> <> <> DIRECTORY G3dBasic, G3dPlane, G3dSpline, G3dTube, G3dVector, RealFns, ImplicitDefs, ImplicitTube, ImplicitValue, ImplicitWeb; ImplicitWebImpl: CEDAR MONITOR IMPORTS G3dPlane, G3dSpline, G3dTube, G3dVector, RealFns, ImplicitTube, ImplicitValue EXPORTS ImplicitWeb ~ BEGIN Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; Plane: TYPE ~ G3dPlane.Plane; NearSpline: TYPE ~ G3dSpline.NearSpline; SplinePlaneIntersect: TYPE ~ G3dSpline.SplinePlaneIntersect; Tube: TYPE ~ G3dTube.Tube; TubeProc: TYPE ~ G3dTube.TubeProc; DistanceMode: TYPE ~ ImplicitDefs.DistanceMode; Sample: TYPE ~ ImplicitDefs.Sample; Web: TYPE ~ ImplicitWeb.Web; WebRep: TYPE ~ ImplicitWeb.WebRep; WebValue: TYPE ~ ImplicitWeb.WebValue; origin: Triple ~ G3dBasic.origin; <> MakeWeb: PUBLIC PROC [tube0, tube1: Tube] RETURNS [Web] ~ { web: Web ¬ NEW[WebRep ¬ [tube0: tube0, tube1: tube1]]; tip0: Triple ~ TubeTip[tube0]; tip1: Triple ~ TubeTip[tube1]; mid: Triple ~ G3dVector.Mul[G3dVector.Add[tip0, tip1], 0.5]; ave: Triple ~ G3dVector.Unit[G3dVector.Add[tube0.v1,tube1.v1]]; cross: Triple ~ G3dVector.Unit[G3dVector.Sub[tip1, mid]]; tan: Triple ~ G3dVector.V90[cross, ave]; web.helper ¬ G3dSpline.SplineFromHermite[[tube0.p0, mid, tube0.v0, tan]]; web.plane ¬ G3dPlane.FromPointAndNormal[mid, tan]; web.bow ¬ 0.25*G3dVector.Distance[tip0, tip1]; RETURN[web]; }; WebSum: PROC [w: Web, distanceMode: DistanceMode] RETURNS [sum: REAL ¬ 0.0] ~ { R: PROC [r: REAL] RETURNS [REAL] ~ {RETURN[IF distanceMode=inverse THEN r ELSE r*r]}; IF w.tube0 # NIL AND w.tube1 # NIL THEN sum ¬ R[w.tube0.r0]+R[w.tube1.r0]+R[w.taper*0.5*(w.tube0.r0+w.tube1.r0)]; }; TubeTip: PROC [tube: Tube] RETURNS [Triple] ~ { RETURN[G3dVector.Add[tube.p1, G3dVector.Mul[G3dVector.Unit[tube.v1], tube.r1]]]; }; TaperTube: PROC [tube: Tube, distanceMode: DistanceMode, sum: REAL] ~ { f: REAL ~ IF distanceMode = inverse THEN tube.r1/sum ELSE RealFns.SqRt[tube.r1*tube.r1/sum]; tubeProc: TubeProc ~ { taper: REAL ~ IF tube.r0 # 0.0 THEN tube.r1/tube.r0 ELSE 1.0; tube.r0 ¬ f*tube.r0; tube.r1 ¬ tube.r0*taper; }; G3dTube.ApplyToBranches[tube, tubeProc]; }; PrepareWeb: PUBLIC PROC [tube: Tube, measureMode: ATOM, distanceMode: DistanceMode] RETURNS [web: Web] ~ { sum: REAL; ImplicitTube.PrepareTube[tube, distanceMode, measureMode]; web ¬ MakeWeb[tube.next, tube.branches[0]]; sum ¬ WebSum[web, distanceMode]; IF sum # 0.0 THEN TaperTube[tube, distanceMode, sum]; }; PrepareWebs: PUBLIC PROC [tube: Tube, measureMode: ATOM, distanceMode: DistanceMode] RETURNS [web0, web1: Web] ~ { sum: REAL; ImplicitTube.PrepareTube[tube, distanceMode, measureMode]; web0 ¬ MakeWeb[tube.next, tube.branches[0]]; web1 ¬ MakeWeb[tube.next, tube.branches[1]]; sum ¬ WebSum[web0, distanceMode]+WebSum[web1,distanceMode]; IF sum # 0.0 THEN TaperTube[tube, distanceMode, sum]; }; ValueOfWeb: PUBLIC PROC [ q: Triple, tube: Tube, web: Web, distanceMode: DistanceMode, tolerance, spread: REAL ¬ 0.0] RETURNS [s: Sample] ~ { webValue: REAL ¬ WebOnly[q, tube, web, distanceMode, tolerance].value; s ¬ ImplicitTube.SampleTubeBranches[q, tube, $Segment, inverseSqrd, tolerance, spread]; s.value ¬ s.value+webValue; s.refAny ¬ web; }; ValueOfWebs: PUBLIC PROC [ q: Triple, tube: Tube, web0, web1: Web, distanceMode: DistanceMode, tolerance, spread: REAL ¬ 0.0] RETURNS [s: Sample] ~ { webValue: WebValue; IF NearestTube[tube] # tube THEN { webInfo: WebInfo ¬ WhichWeb[q, tolerance, web0, web1]; s.refAny ¬ webInfo.web; webValue ¬ DoWeb[webInfo, q, distanceMode]; }; s ¬ ImplicitTube.SampleTubeBranches[q, tube, $Segment, inverseSqrd, tolerance, spread]; s.value ¬ s.value+webValue.value; }; NearestTube: PROC [in: Tube] RETURNS [out: Tube] ~ { d: REAL ¬ 10000.0; tubeProc: G3dTube.TubeProc ~ { IF tube.nearSpline.distance < d THEN { d ¬ tube.nearSpline.distance; out ¬ tube; } }; <> G3dTube.ApplyToBranches[in, tubeProc]; }; WebInfo: TYPE ~ RECORD [ web: Web, p, p0, p1: Triple ¬ origin, d: REAL ¬ 100000.0, t0, t1: REAL ¬ 0.0 ]; WebOnly: PROC [ q: Triple, tube: Tube, web: Web, distanceMode: DistanceMode, tolerance: REAL ¬ 0.0] RETURNS [webValue: WebValue] ~ { webValue.value ¬ 0.0; IF NearestTube[tube] # tube THEN webValue ¬ DoWeb[CheckWeb[q, tolerance, web], q, distanceMode]; }; WhichWeb: PROC [q: Triple, tolerance: REAL, web0, web1: Web] RETURNS [webInfo: WebInfo] ~ { webInfo0: WebInfo ¬ CheckWeb[q, tolerance, web0]; webInfo1: WebInfo ¬ CheckWeb[q, tolerance, web1]; RETURN[IF webInfo0.d < webInfo1.d THEN webInfo0 ELSE webInfo1]; }; CheckWeb: PROC [q: Triple, tolerance: REAL, web: Web] RETURNS [webInfo: WebInfo] ~ { near3d: NearSpline ~ G3dSpline.NearestPoint[q, web.helper, 0.0, 1.0, tolerance]; plane: Plane ¬ G3dPlane.FromPointAndNormal[near3d.point, G3dSpline.Velocity[web.helper, near3d.t]]; quad: G3dBasic.Quad ¬ [plane.x, plane.y, plane.z, plane.w]; i0: SplinePlaneIntersect ¬ G3dSpline.IntersectSplineAndPlane[web.tube0.spline, quad]; i1: SplinePlaneIntersect ¬ G3dSpline.IntersectSplineAndPlane[web.tube1.spline, quad]; IF i0.nRoots # 1 OR i1.nRoots # 1 THEN RETURN; webInfo.web ¬ web; webInfo.t0 ¬ i0.roots[0]; webInfo.t1 ¬ i1.roots[0]; webInfo.p0 ¬ G3dSpline.Position[web.tube0.spline, webInfo.t0]; webInfo.p1 ¬ G3dSpline.Position[web.tube1.spline, webInfo.t1]; webInfo.p ¬ G3dVector.NearestToSegment[webInfo.p0, webInfo.p1, q].point; webInfo.d ¬ G3dVector.Distance[q, webInfo.p]; }; DoWeb: PROC [wi: WebInfo, q: Triple, distanceMode: DistanceMode] RETURNS [wv: WebValue] ~ { r, r0, r1, aa, d0, d1, dplane: REAL; wv.tube0 ¬ wi.web.tube0; wv.tube1 ¬ wi.web.tube1; dplane ¬ -(wi.p.x*wi.web.plane.x+wi.p.y*wi.web.plane.y+wi.p.z*wi.web.plane.z+wi.web.plane.w); IF dplane < 0.0 THEN RETURN; d0 ¬ G3dVector.Distance[wi.p, wi.p0]; d1 ¬ G3dVector.Distance[wi.p, wi.p1]; wv.a0 ¬ IF d0 = 0.0 AND d1 = 0.0 THEN 0.5 ELSE d1/(d0+d1); wv.a1 ¬ 1.0-wv.a0; aa ¬ ABS[1.0-wv.a0-wv.a0]; IF dplane < (1.0-aa*aa)*wi.web.bow THEN RETURN; r0 ¬ G3dTube.Radius[wi.web.tube0, wi.t0]; r1 ¬ G3dTube.Radius[wi.web.tube1, wi.t1]; r ¬ wi.web.taper*(wv.a0*r0+wv.a1*r1); wv.value ¬ 1.5*ImplicitValue.OfPoint[q, wi.p, r, distanceMode].value; }; TextureOfWeb: PUBLIC PROC [ q: Triple, tube: Tube, web: Web, distanceMode: DistanceMode, tolerance: REAL ¬ 0.0] RETURNS [pair: Pair] ~ { SetTubeLength: PROC [tube: Tube] ~ { IF tube.length0 = 0.0 AND tube.prev # NIL THEN tube.length0 ¬ tube.prev.length1; tube.length ¬ G3dSpline.Length[tube.spline]; tube.length1 ¬ tube.length0+tube.length; }; tubeValue: REAL ¬ ImplicitTube.SampleTube[ q, tube, $Segment, distanceMode, tolerance, 0.75].value; -- set tube.near webValue: WebValue ¬ WebOnly[q, tube, web, distanceMode, tolerance]; pair.x ¬ tubeValue/(webValue.value+tubeValue); IF tube.length = 0.0 THEN SetTubeLength[tube]; IF webValue.value # 0.0 THEN { IF webValue.tube0.length = 0.0 THEN SetTubeLength[webValue.tube0]; IF webValue.tube1.length = 0.0 THEN SetTubeLength[webValue.tube1]; pair.y ¬ tube.length1+ webValue.a0*webValue.tube0.nearSpline.t*webValue.tube0.length+ webValue.a1*webValue.tube1.nearSpline.t*webValue.tube1.length; } ELSE pair.y ¬ tube.length1+tube.nearSpline.t*tube.length; }; TextureOfWebs: PUBLIC PROC [ q: Triple, tube: Tube, web0, web1: Web, distanceMode: DistanceMode, tolerance: REAL ¬ 0.0] RETURNS [pair: Pair] ~ { RETURN[TextureOfWeb[ q, tube, WhichWeb[q, tolerance, web0, web1].web, distanceMode, tolerance]]; }; END.