# 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:
DefinitionType
compatible_complex_number_regions FUNCTION
subspace_of FUNCTION

[Top Level Definitions] [Exit]

Generated by STEP Tools® EXPRESS to HTML Converter
2012-03-27T17:13:59-04:00