FUNCTION enclose_pregion_in_pregion
(* SCHEMA mathematical_functions_schema; *)
FUNCTION enclose_pregion_in_pregion(prgn : polar_complex_number_region;
centre : complex_number_literal)
: polar_complex_number_region;
-- Find equivalent direction in range -PI < a <= PI.
FUNCTION angle(a : REAL) : REAL;
REPEAT WHILE a > PI; a := a - 2.0*PI; END_REPEAT;
REPEAT WHILE a <= -PI; a := a + 2.0*PI; END_REPEAT;
RETURN (a);
END_FUNCTION;
-- Find proper limits for direction interval
PROCEDURE angle_range(VAR amin, amax : REAL);
amin := angle(amin);
IF amin = PI THEN amin := -PI; END_IF;
amax := angle(amax);
IF amax <= amin THEN amax := amax + 2.0*PI; END_IF;
END_PROCEDURE;
-- Determine whether a direction is strictly within a direction interval
FUNCTION strictly_in(a : REAL;
aitv : finite_real_interval) : LOGICAL;
a := angle(a);
RETURN ({aitv.min < a < aitv.max} OR {aitv.min < a+2.0*PI < aitv.max});
END_FUNCTION;
-- Find min and max and related inclusion booleans among four candidates,
-- using a base direction chosen to ensure the algebraic comparisons are valid.
PROCEDURE find_aminmax( ab,a0,a1,a2,a3 : REAL;
in0,in1,in2,in3 : BOOLEAN;
VAR amin,amax : REAL;
VAR amin_in,amax_in : BOOLEAN);
LOCAL
a : REAL;
END_LOCAL;
amin := angle(a0-ab); amin_in := in0;
amax := amin; amax_in := in0;
a := angle(a1-ab);
IF a = amin THEN amin_in := amin_in OR in1; END_IF;
IF a < amin THEN amin := a; amin_in := in1; END_IF;
IF a = amax THEN amax_in := amax_in OR in1; END_IF;
IF a > amax THEN amax := a; amax_in := in1; END_IF;
a := angle(a2-ab);
IF a = amin THEN amin_in := amin_in OR in2; END_IF;
IF a < amin THEN amin := a; amin_in := in2; END_IF;
IF a = amax THEN amax_in := amax_in OR in2; END_IF;
IF a > amax THEN amax := a; amax_in := in2; END_IF;
a := angle(a3-ab);
IF a = amin THEN amin_in := amin_in OR in3; END_IF;
IF a < amin THEN amin := a; amin_in := in3; END_IF;
IF a = amax THEN amax_in := amax_in OR in3; END_IF;
IF a > amax THEN amax := a; amax_in := in3; END_IF;
amin := amin+ab;
amax := amax+ab;
angle_range(amin,amax);
END_PROCEDURE;
LOCAL
ritp, ritv : real_interval;
aitp, aitv : finite_real_interval;
xp, yp, xc, yc, rmax, rmin, amin, amax, rc, acp, apc : REAL := 0.0;
rmax_in, rmin_in, amin_in, amax_in : BOOLEAN := FALSE;
rmxp, rmnp, x, y, r, a, ab, r0, a0, r1, a1, r2, a2, r3, a3 : REAL := 0.0;
in0, in1, in2, in3, inn : BOOLEAN := FALSE;
minclo, maxclo : open_closed := open;
END_LOCAL;
-- Extract elementary input information
IF NOT EXISTS (prgn) OR NOT EXISTS (centre) THEN RETURN (?); END_IF;
xp := prgn.centre.real_part;
yp := prgn.centre.imag_part;
ritp := prgn.distance_constraint;
aitp := prgn.direction_constraint;
xc := centre.real_part;
yc := centre.imag_part;
IF (xc = xp) AND (yc = yp) THEN RETURN (prgn); END_IF;
rc := SQRT((xp-xc)**2 + (yp-yc)**2);
acp := atan2(yp-yc,xp-xc);
apc := atan2(yc-yp,xc-xp);
rmnp := real_min(ritp);
-- Analyse cases by existence of max distance and direction limits
IF max_exists(ritp) THEN
rmxp := real_max(ritp);
IF aitp.max - aitp.min = 2.0*PI THEN
-- annulus or disk, with or without slot or puncture
inn := NOT max_included(aitp); -- slot exists;
a := angle(aitp.min); -- slot direction
rmax := rc+rmxp; rmax_in := max_included(ritp);
IF inn AND (acp = a) THEN rmax_in := FALSE; END_IF;
IF rc > rmxp THEN
a0 := ASIN(rmxp/rc);
amin := angle(acp-a0); amin_in := max_included(ritp);
IF amin = PI THEN amin := -PI; END_IF;
amax := angle(acp+a0); amax_in := amin_in;
IF amax < amin THEN amax := amax + 2.0*PI; END_IF;
rmin := rc-rmxp; rmin_in := amin_in;
IF inn THEN
-- slotted case
IF apc = a THEN rmin_in := FALSE; END_IF;
IF angle(amin+0.5*PI) = a THEN amin_in := FALSE; END_IF;
IF angle(amax-0.5*PI) = a THEN amax_in := FALSE; END_IF;
END_IF;
ELSE IF rc = rmxp THEN
amin := angle(acp-0.5*PI); amin_in := FALSE;
IF amin = PI THEN amin := -PI; END_IF;
amax := angle(acp+0.5*PI); amax_in := FALSE;
IF amax < amin THEN amax := amax + 2.0*PI; END_IF;
rmin := 0.0; rmin_in := max_included(ritp);
IF inn AND (apc = a) THEN rmin_in := FALSE; END_IF;
ELSE IF rc > rmnp THEN
IF inn AND (apc = a) THEN -- in the slot
rmin := 0.0; rmin_in := FALSE;
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
ELSE
rmin := 0.0; rmin_in := TRUE;
amin := -PI; amin_in := FALSE;
amax := PI; amax_in := TRUE;
END_IF;
ELSE
rmin := rmnp-rc; rmin_in := min_included(ritp);
amin := -PI; amin_in := FALSE;
amax := PI; amax_in := TRUE;
IF inn THEN -- Special cases when aligned with slot
IF apc = a THEN
rmin_in := FALSE;
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
ELSE IF acp = a THEN
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
END_IF; END_IF;
END_IF;
END_IF; END_IF; END_IF;
ELSE -- direction range < 2*PI
-- Compute data for corners with respect to xc,yc
x := xp + rmxp*cos(aitp.min) - xc;
y := yp + rmxp*sin(aitp.min) - yc;
r0 := SQRT(x**2 + y**2);
in0 := max_included(ritp) AND min_included(aitp);
IF r0 <> 0.0 THEN a0 := atan2(y,x); END_IF;
x := xp + rmxp*cos(aitp.max) - xc;
y := yp + rmxp*sin(aitp.max) - yc;
r1 := SQRT(x**2 + y**2);
in1 := max_included(ritp) AND max_included(aitp);
IF r1 <> 0.0 THEN a1 := atan2(y,x); END_IF;
x := xp + rmnp*cos(aitp.max) - xc;
y := yp + rmnp*sin(aitp.max) - yc;
r2 := SQRT(x**2 + y**2);
in2 := min_included(ritp) AND max_included(aitp);
IF r2 <> 0.0 THEN a2 := atan2(y,x); ELSE a2 := a1; in2 := in1; END_IF;
IF r1 = 0.0 THEN a1 := a2; in1 := in2; END_IF;
x := xp + rmnp*cos(aitp.min) - xc;
y := yp + rmnp*sin(aitp.min) - yc;
r3 := SQRT(x**2 + y**2);
in3 := min_included(ritp) AND min_included(aitp);
IF r3 <> 0.0 THEN a3 := atan2(y,x); ELSE a3 := a0; in3 := in0; END_IF;
IF r0 = 0.0 THEN a0 := a3; in0 := in3; END_IF;
IF rmnp = 0.0 THEN in2 := min_included(ritp); in3 := in2; END_IF;
IF (apc = angle(aitp.min)) OR (acp = angle(aitp.min)) THEN
in0 := min_included(aitp);
in3 := in0;
ELSE IF (apc = angle(aitp.max)) OR (acp = angle(aitp.max)) THEN
in1 := max_included(aitp);
in2 := in1;
END_IF; END_IF;
-- Find rmax
IF strictly_in(acp,aitp) THEN
rmax := rc+rmxp; rmax_in := max_included(ritp);
ELSE
rmax := r0; rmax_in := in0;
IF rmax = r1 THEN rmax_in := rmax_in OR in1; END_IF;
IF rmax < r1 THEN rmax := r1; rmax_in := in1; END_IF;
IF rmax = r2 THEN rmax_in := rmax_in OR in2; END_IF;
IF rmax < r2 THEN rmax := r2; rmax_in := in2; END_IF;
IF rmax = r3 THEN rmax_in := rmax_in OR in3; END_IF;
IF rmax < r3 THEN rmax := r3; rmax_in := in3; END_IF;
END_IF;
-- Find rmin
IF strictly_in(apc,aitp) THEN
IF rc >= rmxp THEN
rmin := rc-rmxp; rmin_in := max_included(ritp);
ELSE IF rc <= rmnp THEN
rmin := rmnp-rc; rmin_in := min_included(ritp);
ELSE
rmin := 0.0; rmin_in := TRUE;
END_IF; END_IF;
ELSE
rmin := r0; rmin_in := in0;
a := apc-aitp.min;
r := rc*COS(a);
IF {rmnp < r < rmxp} THEN -- use nearest point on line segment
rmin := rc*SIN(ABS(a)); rmin_in := min_included(aitp);
END_IF;
a := apc-aitp.max;
r := rc*COS(a);
IF {rmnp < r < rmxp} THEN -- try nearest point on line segment
r := rc*SIN(ABS(a)); inn := max_included(aitp);
IF r = rmin THEN rmin_in := rmin_in OR inn; END_IF;
IF r < rmin THEN rmin := r; rmin_in := inn; END_IF;
END_IF;
IF r1 = rmin THEN rmin_in := rmin_in OR in1; END_IF;
IF r1 < rmin THEN rmin := r1; rmin_in := in1; END_IF;
IF r2 = rmin THEN rmin_in := rmin_in OR in2; END_IF;
IF r2 < rmin THEN rmin := r2; rmin_in := in2; END_IF;
IF r3 = rmin THEN rmin_in := rmin_in OR in3; END_IF;
IF r3 < rmin THEN rmin := r3; rmin_in := in3; END_IF;
END_IF;
-- Find amin and amax, initially with respect to base direction ab.
IF rc >= rmxp THEN -- outside outer circle
ab := acp;
find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
a := ACOS(rmxp/rc);
IF strictly_in(apc-a,aitp) THEN
amin := ab-ASIN(rmxp/rc); amin_in := max_included(ritp);
END_IF;
IF strictly_in(apc+a,aitp) THEN
amax := ab+ASIN(rmxp/rc); amax_in := max_included(ritp);
END_IF;
angle_range(amin,amax);
ELSE IF rc > rmnp THEN
ab := angle(0.5*(aitp.min+aitp.max)); -- reference direction
find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
ELSE
-- Using base direction midway in prgn, compute all directions using
-- values which ensure a3 < a2 and a0 < a1 algebraically.
ab := angle(0.5*(aitp.min+aitp.max)); -- reference direction
a0 := angle(a0-ab);
a1 := angle(a1-ab);
a2 := angle(a2-ab);
a3 := angle(a3-ab);
IF a3 > a2 THEN a2 := a2 + 2.0*PI; END_IF;
IF a0 > a1 THEN a0 := a0 + 2.0*PI; END_IF;
IF a3 < a0 THEN amin := a3; amin_in := in3;
ELSE amin := a0; amin_in := in0; END_IF;
IF a2 > a1 THEN amax := a2; amax_in := in2;
ELSE amax := a1; amax_in := in1; END_IF;
IF (amax - amin > 2.0*PI) OR
((amax - amin = 2.0*PI) AND (amin_in OR amax_in)) THEN
-- Cannot see out
amin := -PI; amin_in := FALSE;
amax := PI; amax_in := TRUE;
ELSE
amin := amin + ab;
amax := amax + ab;
angle_range(amin,amax);
END_IF;
END_IF; END_IF;
END_IF;
IF rmin_in THEN minclo := closed; END_IF;
IF rmax_in THEN maxclo := closed; END_IF;
ritv := make_finite_real_interval(rmin,minclo,rmax,maxclo);
ELSE -- Not max_exists(ritp)
IF (rc > rmnp) AND strictly_in(apc,aitp) THEN
RETURN (?); -- No pregion exists. (Would require whole plane.)
END_IF;
IF aitp.max - aitp.min = 2.0*PI THEN
-- complement of disk, with or without slot
a := angle(aitp.min); -- slot direction
IF rc > rmnp THEN -- already excluded if not aligned with slot
IF max_included(aitp) THEN
RETURN (?); -- No pregion exists. (Would require whole plane.)
END_IF;
rmin := 0.0; rmin_in := FALSE;
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
ELSE
rmin := rmnp-rc; rmin_in := min_included(ritp);
amin := -PI; amin_in := FALSE;
amax := PI; amax_in := TRUE;
IF NOT max_included(aitp) THEN -- Special cases when aligned with slot
IF apc = a THEN
rmin_in := FALSE;
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
ELSE IF acp = a THEN
amin := aitp.min; amin_in := FALSE;
amax := aitp.max; amax_in := FALSE;
END_IF; END_IF;
END_IF;
END_IF;
ELSE -- direction range < 2*PI
-- Compute data for corners with respect to xc,yc (two at infinity)
a0 := angle(aitp.min);
in0 := FALSE;
a1 := angle(aitp.max);
in1 := FALSE;
x := xp + rmnp*cos(aitp.max) - xc;
y := yp + rmnp*sin(aitp.max) - yc;
r2 := SQRT(x**2 + y**2);
in2 := min_included(ritp) AND max_included(aitp);
IF r2 <> 0.0 THEN a2 := atan2(y,x); ELSE a2 := a1; in2 := in1; END_IF;
x := xp + rmnp*cos(aitp.min) - xc;
y := yp + rmnp*sin(aitp.min) - yc;
r3 := SQRT(x**2 + y**2);
in3 := min_included(ritp) AND min_included(aitp);
IF r3 <> 0.0 THEN a3 := atan2(y,x); ELSE a3 := a0; in3 := in0; END_IF;
IF rmnp = 0.0 THEN in2 := min_included(ritp); in3 := in2; END_IF;
IF (apc = angle(aitp.min)) OR (acp = angle(aitp.min)) THEN
in0 := min_included(aitp);
in3 := in0;
ELSE IF (apc = angle(aitp.max)) OR (acp = angle(aitp.max)) THEN
in1 := max_included(aitp);
in2 := in1;
END_IF; END_IF;
-- Find rmin
IF strictly_in(apc,aitp) THEN
rmin := rmnp-rc; rmin_in := min_included(ritp);
ELSE
rmin := r2; rmin_in := in2;
a := apc-aitp.min;
r := rc*COS(a);
IF rmnp < r THEN -- use nearest point on aitp.min ray
rmin := rc*SIN(ABS(a)); rmin_in := min_included(aitp);
END_IF;
a := apc-aitp.max;
r := rc*COS(a);
IF rmnp < r THEN -- try nearest point on aitp.max ray
r := rc*SIN(ABS(a)); inn := max_included(aitp);
IF r = rmin THEN rmin_in := rmin_in OR inn; END_IF;
IF r < rmin THEN rmin := r; rmin_in := inn; END_IF;
END_IF;
IF r3 = rmin THEN rmin_in := rmin_in OR in3; END_IF;
IF r3 < rmin THEN rmin := r3; rmin_in := in3; END_IF;
END_IF;
-- Find amin and amax
ab := angle(0.5*(aitp.min+aitp.max)); -- reference direction
IF rc > rmnp THEN
find_aminmax(ab,a0,a1,a2,a3,in0,in1,in2,in3,amin,amax,amin_in,amax_in);
ELSE
-- Using base direction midway in prgn, compute all directions using
-- values which ensure a3 < a2 and a0 < a1 algebraically.
a0 := angle(a0-ab);
a1 := angle(a1-ab);
a2 := angle(a2-ab);
a3 := angle(a3-ab);
IF a3 > a2 THEN a2 := a2 + 2.0*PI; END_IF;
IF a0 > a1 THEN a0 := a0 + 2.0*PI; END_IF;
IF a3 < a0 THEN amin := a3; amin_in := in3;
ELSE amin := a0; amin_in := in0; END_IF;
IF a2 > a1 THEN amax := a2; amax_in := in2;
ELSE amax := a1; amax_in := in1; END_IF;
IF (amax - amin > 2.0*PI) OR
((amax - amin = 2.0*PI) AND (amin_in OR amax_in)) THEN
-- Cannot see out
amin := -PI; amin_in := FALSE;
amax := PI; amax_in := TRUE;
IF (rmin = 0.0) AND rmin_in THEN
RETURN (?); -- No pregion exists. (Would require whole plane.)
END_IF;
ELSE
amin := amin + ab;
amax := amax + ab;
angle_range(amin,amax);
END_IF;
END_IF;
END_IF;
IF rmin_in THEN minclo := closed; END_IF;
ritv := make_real_interval_from_min(rmin,minclo);
END_IF;
minclo := open; maxclo := open;
IF amin_in THEN minclo := closed; END_IF;
IF amax_in THEN maxclo := closed; END_IF;
aitv := make_finite_real_interval(amin,minclo,amax,maxclo);
-- Construct polar region
RETURN (make_polar_complex_number_region(centre,ritv,aitv));
END_FUNCTION; -- enclose_pregion_in_pregion
Referenced By
Defintion enclose_pregion_in_pregion is references by the following definitions:
[Top Level Definitions] [Exit]Generated by STEP Tools® EXPRESS to HTML Converter
2012-03-27T17:13:59-04:00