FUNCTION enclose_pregion_in_pregion

(* SCHEMA Ap242_managed_model_based_3d_engineering_mim_LF; *)
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:20:10-04:00