/** * Return the complement of the interior of the interval. An interval and its * complement have the same boundary but do not share any interior values. The * complement operator is not a bijection, since the complement of a singleton * interval (containing a single value) is the same as the complement of an * empty interval. *#/ * public S1Interval complement() { * if (lo() == hi()) { * return full(); // Singleton. * } * return new S1Interval(hi(), lo(), true); // Handles * // empty and * // full. * } * * /** Return true if the interval (which is closed) contains the point 'p'. *#/ * public boolean contains(double p) { * // Works for empty, full, and singleton intervals. * // assert (Math.abs(p) <= S2.M_PI); * if (p == -S2.M_PI) { * p = S2.M_PI; * } * return fastContains(p); * } * * /** * Return true if the interval (which is closed) contains the point 'p'. Skips * the normalization of 'p' from -Pi to Pi. * *#/ * public boolean fastContains(double p) { * if (isInverted()) { * return (p >= lo() || p <= hi()) && !isEmpty(); * } else { * return p >= lo() && p <= hi(); * } * } * * /** Return true if the interior of the interval contains the point 'p'. *#/ * public boolean interiorContains(double p) { * // Works for empty, full, and singleton intervals. * // assert (Math.abs(p) <= S2.M_PI); * if (p == -S2.M_PI) { * p = S2.M_PI; * } * * if (isInverted()) { * return p > lo() || p < hi(); * } else { * return (p > lo() && p < hi()) || isFull(); * } * } * * /** * Return true if the interval contains the given interval 'y'. Works for * empty, full, and singleton intervals. *#/ * public boolean contains(final S1Interval y) { * // It might be helpful to compare the structure of these tests to * // the simpler Contains(double) method above. * * if (isInverted()) { * if (y.isInverted()) { * return y.lo() >= lo() && y.hi() <= hi(); * } * return (y.lo() >= lo() || y.hi() <= hi()) && !isEmpty(); * } else { * if (y.isInverted()) { * return isFull() || y.isEmpty(); * } * return y.lo() >= lo() && y.hi() <= hi(); * } * } * * /** * Returns true if the interior of this interval contains the entire interval * 'y'. Note that x.InteriorContains(x) is true only when x is the empty or * full interval, and x.InteriorContains(S1Interval(p,p)) is equivalent to * x.InteriorContains(p). *#/ * public boolean interiorContains(final S1Interval y) { * if (isInverted()) { * if (!y.isInverted()) { * return y.lo() > lo() || y.hi() < hi(); * } * return (y.lo() > lo() && y.hi() < hi()) || y.isEmpty(); * } else { * if (y.isInverted()) { * return isFull() || y.isEmpty(); * } * return (y.lo() > lo() && y.hi() < hi()) || isFull(); * } * } * * /** * Return true if the two intervals contain any points in common. Note that * the point +/-Pi has two representations, so the intervals [-Pi,-3] and * [2,Pi] intersect, for example. */ public function intersects(S1Interval $y) { if ($this->isEmpty() || $y->isEmpty()) { return false; } if ($this->isInverted()) { // Every non-empty inverted interval contains Pi. return $y->isInverted() || $y->lo() <= $this->hi() || $y->hi() >= $this->lo(); } else { if ($y->isInverted()) { return $y->lo() <= $this->hi() || $y->hi() >= $this->lo(); } return $y->lo() <= $this->hi() && $y->hi() >= $this->lo(); } }