~
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;
Webs
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.ApplyToTube[in, tubeProc];
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]];
};