/*
 * Copyright 2010-2015 Institut Pasteur.
 * 
 * This file is part of Icy.
 * 
 * Icy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Icy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
 */
package icy.type.rectangle;

import icy.type.dimension.Dimension5D;
import icy.type.point.Point5D;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

/**
 * Rectangle5D class.<br>
 * Incomplete implementation (work in progress...)
 * 
 * @author Stephane
 */
public abstract class Rectangle5D implements Cloneable
{
    /**
     * Intersects the pair of specified source <code>Rectangle5D</code> objects and puts the result
     * into the specified destination <code>Rectangle5D</code> object. One of the source rectangles
     * can also be the destination to avoid creating a third Rectangle5D object, but in this case
     * the original points of this source rectangle will be overwritten by this method.
     * 
     * @param src1
     *        the first of a pair of <code>Rectangle5D</code> objects to be intersected with each
     *        other
     * @param src2
     *        the second of a pair of <code>Rectangle5D</code> objects to be intersected with each
     *        other
     * @param dest
     *        the <code>Rectangle5D</code> that holds the
     *        results of the intersection of <code>src1</code> and <code>src2</code>.<br>
     *        If set to <code>null</code> then a new Rectangle5D is created.
     * @return resulting <code>Rectangle5D</code> from the intersect process.
     */
    public static Rectangle5D intersect(Rectangle5D src1, Rectangle5D src2, Rectangle5D dest)
    {
        final Rectangle5D result;

        if (dest == null)
            result = new Rectangle5D.Double();
        else
            result = dest;

        final double x1 = Math.max(src1.getMinX(), src2.getMinX());
        final double y1 = Math.max(src1.getMinY(), src2.getMinY());
        final double z1 = Math.max(src1.getMinZ(), src2.getMinZ());
        final double t1 = Math.max(src1.getMinT(), src2.getMinT());
        final double c1 = Math.max(src1.getMinC(), src2.getMinC());
        final double x2 = Math.min(src1.getMaxX(), src2.getMaxX());
        final double y2 = Math.min(src1.getMaxY(), src2.getMaxY());
        final double z2 = Math.min(src1.getMaxZ(), src2.getMaxZ());
        final double t2 = Math.min(src1.getMaxT(), src2.getMaxT());
        final double c2 = Math.min(src1.getMaxC(), src2.getMaxC());

        double dx;
        double dy;
        double dz;
        double dt;
        double dc;

        // special infinite case
        if (x2 == java.lang.Double.POSITIVE_INFINITY)
            dx = java.lang.Double.POSITIVE_INFINITY;
        else
            dx = x2 - x1;
        // special infinite case
        if (y2 == java.lang.Double.POSITIVE_INFINITY)
            dy = java.lang.Double.POSITIVE_INFINITY;
        else
            dy = y2 - y1;
        // special infinite case
        if (z2 == java.lang.Double.POSITIVE_INFINITY)
            dz = java.lang.Double.POSITIVE_INFINITY;
        else
            dz = z2 - z1;
        // special infinite case
        if (t2 == java.lang.Double.POSITIVE_INFINITY)
            dt = java.lang.Double.POSITIVE_INFINITY;
        else
            dt = t2 - t1;
        // special infinite case
        if (c2 == java.lang.Double.POSITIVE_INFINITY)
            dc = java.lang.Double.POSITIVE_INFINITY;
        else
            dc = c2 - c1;

        result.setRect(x1, y1, z1, t1, c1, dx, dy, dz, dt, dc);

        return result;
    }

    /**
     * Returns a new <code>Rectangle5D</code> object representing the intersection of this
     * <code>Rectangle5D</code> with the specified <code>Rectangle5D</code>.
     * 
     * @param r
     *        the <code>Rectangle5D</code> to be intersected with this <code>Rectangle5D</code>
     * @return the largest <code>Rectangle5D</code> contained in both the specified
     *         <code>Rectangle5D</code> and in this <code>Rectangle5D</code>.
     */
    public abstract Rectangle5D createIntersection(Rectangle5D r);

    /**
     * Unions the pair of source <code>Rectangle5D</code> objects and puts the result into the
     * specified destination <code>Rectangle5D</code> object. One of the source rectangles can also
     * be the destination to avoid creating a third Rectangle5D object, but in this case the
     * original points of this source rectangle will be overwritten by this method.
     * 
     * @param src1
     *        the first of a pair of <code>Rectangle5D</code> objects to be combined with each other
     * @param src2
     *        the second of a pair of <code>Rectangle5D</code> objects to be combined with each
     *        other
     * @param dest
     *        the <code>Rectangle5D</code> that holds the
     *        results of the union of <code>src1</code> and <code>src2</code>.<br>
     *        If set to <code>null</code> then a new Rectangle5D is created.
     * @return resulting <code>Rectangle5D</code> from the intersect process.
     */
    public static Rectangle5D union(Rectangle5D src1, Rectangle5D src2, Rectangle5D dest)
    {
        final Rectangle5D result;

        if (dest == null)
            result = new Rectangle5D.Double();
        else
            result = dest;

        double x1 = Math.min(src1.getMinX(), src2.getMinX());
        double y1 = Math.min(src1.getMinY(), src2.getMinY());
        double z1 = Math.min(src1.getMinZ(), src2.getMinZ());
        double t1 = Math.min(src1.getMinT(), src2.getMinT());
        double c1 = Math.min(src1.getMinC(), src2.getMinC());
        double x2 = Math.max(src1.getMaxX(), src2.getMaxX());
        double y2 = Math.max(src1.getMaxY(), src2.getMaxY());
        double z2 = Math.max(src1.getMaxZ(), src2.getMaxZ());
        double t2 = Math.max(src1.getMaxT(), src2.getMaxT());
        double c2 = Math.max(src1.getMaxC(), src2.getMaxC());

        double dx;
        double dy;
        double dz;
        double dt;
        double dc;

        // special infinite case
        if (x2 == java.lang.Double.POSITIVE_INFINITY)
            dx = java.lang.Double.POSITIVE_INFINITY;
        else
            dx = x2 - x1;
        // special infinite case
        if (y2 == java.lang.Double.POSITIVE_INFINITY)
            dy = java.lang.Double.POSITIVE_INFINITY;
        else
            dy = y2 - y1;
        // special infinite case
        if (z2 == java.lang.Double.POSITIVE_INFINITY)
            dz = java.lang.Double.POSITIVE_INFINITY;
        else
            dz = z2 - z1;
        // special infinite case
        if (t2 == java.lang.Double.POSITIVE_INFINITY)
            dt = java.lang.Double.POSITIVE_INFINITY;
        else
            dt = t2 - t1;
        // special infinite case
        if (c2 == java.lang.Double.POSITIVE_INFINITY)
            dc = java.lang.Double.POSITIVE_INFINITY;
        else
            dc = c2 - c1;

        result.setRect(x1, y1, z1, t1, c1, dx, dy, dz, dt, dc);

        return result;
    }

    /**
     * Returns a new <code>Rectangle5D</code> object representing the union of this
     * <code>Rectangle5D</code> with the specified <code>Rectangle5D</code>.
     * 
     * @param r
     *        the <code>Rectangle5D</code> to be combined with this <code>Rectangle5D</code>
     * @return the smallest <code>Rectangle5D</code> containing both the specified
     *         <code>Rectangle5D</code> and this <code>Rectangle5D</code>.
     */
    public abstract Rectangle5D createUnion(Rectangle5D r);

    /**
     * Sets the position and size of this <code>Rectangle5D</code> to the specified
     * <code>double</code> values.
     * 
     * @param x
     *        the X coordinate of the minimum corner position of this <code>Rectangle5D</code>
     * @param y
     *        the Y coordinate of the minimum corner position of this <code>Rectangle5D</code>
     * @param z
     *        the Z coordinate of the minimum corner position of this <code>Rectangle5D</code>
     * @param t
     *        the T coordinate of the minimum corner position of this <code>Rectangle5D</code>
     * @param c
     *        the C coordinate of the minimum corner position of this <code>Rectangle5D</code>
     * @param sizeX
     *        size for X dimension of this <code>Rectangle5D</code>
     * @param sizeY
     *        size for Y dimension of this <code>Rectangle5D</code>
     * @param sizeZ
     *        size for Z dimension of this <code>Rectangle5D</code>
     * @param sizeT
     *        size for T dimension of this <code>Rectangle5D</code>
     * @param sizeC
     *        size for C dimension of this <code>Rectangle5D</code>
     */
    public abstract void setRect(double x, double y, double z, double t, double c, double sizeX, double sizeY,
            double sizeZ, double sizeT, double sizeC);

    /**
     * Returns the minimum X coordinate.
     */
    public abstract double getX();

    /**
     * Returns the minimum Y coordinate.
     */
    public abstract double getY();

    /**
     * Returns the minimum Z coordinate.
     */
    public abstract double getZ();

    /**
     * Returns the minimum T coordinate.
     */
    public abstract double getT();

    /**
     * Returns the minimum C coordinate.
     */
    public abstract double getC();

    /**
     * Returns the size of X dimension.
     */
    public abstract double getSizeX();

    /**
     * Returns the size of Y dimension.
     */
    public abstract double getSizeY();

    /**
     * Returns the size of Z dimension.
     */
    public abstract double getSizeZ();

    /**
     * Returns the size of T dimension.
     */
    public abstract double getSizeT();

    /**
     * Returns the size of C dimension.
     */
    public abstract double getSizeC();

    /**
     * Returns the point coordinate.
     */
    public abstract Point5D getPosition();

    /**
     * Returns the dimension.
     */
    public abstract Dimension5D getDimension();

    /**
     * Returns an integer {@link Rectangle5D} that completely encloses the
     * double <code>Rectangle</code>. The returned <code>Rectangle</code> might also fail to
     * completely enclose the original double <code>Rectangle</code> if it overflows
     * the limited range of the integer data type.
     * 
     * @return an integer <code>Rectangle</code> that completely encloses
     *         the actual double <code>Rectangle</code>.
     */
    public Rectangle5D.Integer toInteger()
    {
        double sx = getSizeX();
        double sy = getSizeY();
        double sz = getSizeZ();
        double st = getSizeT();
        double sc = getSizeC();
        double x = getX();
        double y = getY();
        double z = getZ();
        double t = getT();
        double c = getC();
        int ix = (int) Math.floor(x);
        int iy = (int) Math.floor(y);
        int iz = (int) Math.floor(z);
        int it = (int) Math.floor(t);
        int ic = (int) Math.floor(c);
        int isx;
        int isy;
        int isz;
        int ist;
        int isc;

        if (sx < 0d)
            isx = 0;
        else if (sx >= java.lang.Integer.MAX_VALUE)
            isx = java.lang.Integer.MAX_VALUE;
        else
            isx = ((int) Math.ceil(x + sx)) - ix;
        if (sy < 0d)
            isy = 0;
        else if (sy >= java.lang.Integer.MAX_VALUE)
            isy = java.lang.Integer.MAX_VALUE;
        else
            isy = ((int) Math.ceil(y + sy)) - iy;
        if (sz < 0d)
            isz = 0;
        else if (sz >= java.lang.Integer.MAX_VALUE)
            isz = java.lang.Integer.MAX_VALUE;
        else
            isz = ((int) Math.ceil(z + sz)) - iz;
        if (st < 0d)
            ist = 0;
        else if (st >= java.lang.Integer.MAX_VALUE)
            ist = java.lang.Integer.MAX_VALUE;
        else
            ist = ((int) Math.ceil(t + st)) - it;
        if (sc < 0d)
            isc = 0;
        else if (sc >= java.lang.Integer.MAX_VALUE)
            isc = java.lang.Integer.MAX_VALUE;
        else
            isc = ((int) Math.ceil(c + sc)) - ic;

        return new Rectangle5D.Integer(ix, iy, iz, it, ic, isx, isy, isz, ist, isc);
    }

    /**
     * Sets the minimum X coordinate.
     */
    public abstract void setX(double x);

    /**
     * Sets the minimum Y coordinate.
     */
    public abstract void setY(double y);

    /**
     * Sets the minimum Z coordinate.
     */
    public abstract void setZ(double z);

    /**
     * Sets the minimum T coordinate.
     */
    public abstract void setT(double t);

    /**
     * Sets the minimum C coordinate.
     */
    public abstract void setC(double c);

    /**
     * Sets the size of X dimension.
     */
    public abstract void setSizeX(double value);

    /**
     * Sets the size of Y dimension.
     */
    public abstract void setSizeY(double value);

    /**
     * Sets the size of Z dimension.
     */
    public abstract void setSizeZ(double value);

    /**
     * Sets the size of T dimension.
     */
    public abstract void setSizeT(double value);

    /**
     * Sets the size of C dimension.
     */
    public abstract void setSizeC(double value);

    /**
     * Returns the smallest X coordinate of the rectangle.
     */
    public double getMinX()
    {
        return getX();
    }

    /**
     * Returns the smallest Y coordinate of the rectangle.
     */
    public double getMinY()
    {
        return getY();
    }

    /**
     * Returns the smallest Z coordinate of the rectangle.
     */
    public double getMinZ()
    {
        return getZ();
    }

    /**
     * Returns the smallest T coordinate of the rectangle.
     */
    public double getMinT()
    {
        return getT();
    }

    /**
     * Returns the smallest C coordinate of the rectangle.
     */
    public double getMinC()
    {
        return getC();
    }

    /**
     * Returns the largest X coordinate of the rectangle.
     */
    public double getMaxX()
    {
        // handle this special case
        if (getSizeX() == java.lang.Double.POSITIVE_INFINITY)
            return java.lang.Double.POSITIVE_INFINITY;

        return getX() + getSizeX();
    }

    /**
     * Returns the largest Y coordinate of the rectangle.
     */
    public double getMaxY()
    {
        // handle this special case
        if (getSizeY() == java.lang.Double.POSITIVE_INFINITY)
            return java.lang.Double.POSITIVE_INFINITY;

        return getY() + getSizeY();
    }

    /**
     * Returns the largest Z coordinate of the rectangle.
     */
    public double getMaxZ()
    {
        // handle this special case
        if (getSizeZ() == java.lang.Double.POSITIVE_INFINITY)
            return java.lang.Double.POSITIVE_INFINITY;

        return getZ() + getSizeZ();
    }

    /**
     * Returns the largest T coordinate of the rectangle.
     */
    public double getMaxT()
    {
        // handle this special case
        if (getSizeT() == java.lang.Double.POSITIVE_INFINITY)
            return java.lang.Double.POSITIVE_INFINITY;

        return getT() + getSizeT();
    }

    /**
     * Returns the largest C coordinate of the rectangle.
     */
    public double getMaxC()
    {
        // handle this special case
        if (getSizeC() == java.lang.Double.POSITIVE_INFINITY)
            return java.lang.Double.POSITIVE_INFINITY;

        return getC() + getSizeC();
    }

    /**
     * Returns the X coordinate of the center of the rectangle.
     */
    public double getCenterX()
    {
        // handle this special case
        if (isInfiniteX())
            return 0d;

        return getX() + (getSizeX() / 2d);
    }

    /**
     * Returns the Y coordinate of the center of the rectangle.
     */
    public double getCenterY()
    {
        // handle this special case
        if (isInfiniteY())
            return 0d;

        return getY() + (getSizeY() / 2d);
    }

    /**
     * Returns the Z coordinate of the center of the rectangle.
     */
    public double getCenterZ()
    {
        // handle this special case
        if (isInfiniteZ())
            return 0d;

        return getZ() + (getSizeZ() / 2d);
    }

    /**
     * Returns the T coordinate of the center of the rectangle.
     */
    public double getCenterT()
    {
        // handle this special case
        if (isInfiniteT())
            return 0d;

        return getT() + (getSizeT() / 2d);
    }

    /**
     * Returns the C coordinate of the center of the rectangle.
     */
    public double getCenterC()
    {
        // handle this special case
        if (isInfiniteC())
            return 0d;

        return getC() + (getSizeC() / 2d);
    }

    /**
     * Determines whether the <code>Rectangle5D</code> is empty.
     * 
     * @return <code>true</code> if the <code>Rectangle5D</code> is empty; <code>false</code>
     *         otherwise.
     */
    public boolean isEmpty()
    {
        return (getSizeX() <= 0d) || (getSizeY() <= 0d) || (getSizeZ() <= 0d) || (getSizeT() <= 0d)
                || (getSizeC() <= 0d);
    }

    /**
     * Returns <code>true</code> if the X dimension should be considered as infinite.
     */
    public boolean isInfiniteX()
    {
        return (getX() == java.lang.Double.NEGATIVE_INFINITY) && (getSizeX() == java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Returns <code>true</code> if the Y dimension should be considered as infinite.
     */
    public boolean isInfiniteY()
    {
        return (getY() == java.lang.Double.NEGATIVE_INFINITY) && (getSizeY() == java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Returns <code>true</code> if the Z dimension should be considered as infinite.
     */
    public boolean isInfiniteZ()
    {
        return (getZ() == java.lang.Double.NEGATIVE_INFINITY) && (getSizeZ() == java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Returns <code>true</code> if the T dimension should be considered as infinite.
     */
    public boolean isInfiniteT()
    {
        return (getT() == java.lang.Double.NEGATIVE_INFINITY) && (getSizeT() == java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Returns <code>true</code> if the C dimension should be considered as infinite.
     */
    public boolean isInfiniteC()
    {
        return (getC() == java.lang.Double.NEGATIVE_INFINITY) && (getSizeC() == java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Sets the X dimension to infinite.
     */
    public void setInfiniteX()
    {
        setX(java.lang.Double.NEGATIVE_INFINITY);
        setSizeX(java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Sets the Y dimension to infinite.
     */
    public void setInfiniteY()
    {
        setY(java.lang.Double.NEGATIVE_INFINITY);
        setSizeY(java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Sets the Z dimension to infinite.
     */
    public void setInfiniteZ()
    {
        setZ(java.lang.Double.NEGATIVE_INFINITY);
        setSizeZ(java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Sets the T dimension to infinite.
     */
    public void setInfiniteT()
    {
        setT(java.lang.Double.NEGATIVE_INFINITY);
        setSizeT(java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Sets the C dimension to infinite.
     */
    public void setInfiniteC()
    {
        setC(java.lang.Double.NEGATIVE_INFINITY);
        setSizeC(java.lang.Double.POSITIVE_INFINITY);
    }

    /**
     * Tests if the specified coordinates are inside the boundary of the <code>Rectangle5D</code>.
     * 
     * @param x
     *        the specified X coordinate to be tested
     * @param y
     *        the specified Y coordinate to be tested
     * @param z
     *        the specified Z coordinate to be tested
     * @param t
     *        the specified T coordinate to be tested
     * @param c
     *        the specified C coordinate to be tested
     * @return <code>true</code> if the specified coordinates are inside
     *         the <code>Rectangle5D</code> boundary; <code>false</code> otherwise.
     */
    public boolean contains(double x, double y, double z, double t, double c)
    {
        return (x >= getMinX()) && (y >= getMinY()) && (z >= getMinZ()) && (t >= getMinT()) && (c >= getMinC())
                && (x < getMaxX()) && (y < getMaxY()) && (z < getMaxZ()) && (t < getMaxT()) && (c < getMaxC());
    }

    /**
     * Tests if the <code>Rectangle5D</code> entirely contains the specified 5D rectangular area.<br>
     * All coordinates that lie inside the 5D rectangular area must lie within the
     * <code>Rectangle5D</code>.
     * 
     * @param x
     *        the X coordinate of the minimum corner position of the specified rectangular area
     * @param y
     *        the Y coordinate of the minimum corner position of the specified rectangular area
     * @param z
     *        the Z coordinate of the minimum corner position of the specified rectangular area
     * @param t
     *        the T coordinate of the minimum corner position of the specified rectangular area
     * @param c
     *        the C coordinate of the minimum corner position of the specified rectangular area
     * @param sizeX
     *        size for X dimension of the specified rectangular area
     * @param sizeY
     *        size for Y dimension of the specified rectangular area
     * @param sizeZ
     *        size for Z dimension of the specified rectangular area
     * @param sizeT
     *        size for T dimension of the specified rectangular area
     * @param sizeC
     *        size for C dimension of the specified rectangular area
     * @return <code>true</code> if the <code>Rectangle5D</code> entirely contains the
     *         specified 5D rectangular area; <code>false</code> otherwise
     * @see #intersects
     */
    public boolean contains(double x, double y, double z, double t, double c, double sizeX, double sizeY, double sizeZ,
            double sizeT, double sizeC)
    {
        final double maxX;
        final double maxY;
        final double maxZ;
        final double maxT;
        final double maxC;

        // special infinite case
        if (sizeX == java.lang.Double.POSITIVE_INFINITY)
            maxX = java.lang.Double.POSITIVE_INFINITY;
        else
            maxX = x + sizeX;
        // special infinite case
        if (sizeY == java.lang.Double.POSITIVE_INFINITY)
            maxY = java.lang.Double.POSITIVE_INFINITY;
        else
            maxY = y + sizeY;
        // special infinite case
        if (sizeZ == java.lang.Double.POSITIVE_INFINITY)
            maxZ = java.lang.Double.POSITIVE_INFINITY;
        else
            maxZ = z + sizeZ;
        // special infinite case
        if (sizeT == java.lang.Double.POSITIVE_INFINITY)
            maxT = java.lang.Double.POSITIVE_INFINITY;
        else
            maxT = t + sizeT;
        // special infinite case
        if (sizeC == java.lang.Double.POSITIVE_INFINITY)
            maxC = java.lang.Double.POSITIVE_INFINITY;
        else
            maxC = c + sizeC;

        return (x >= getMinX()) && (y >= getMinY()) && (z >= getMinZ()) && (t >= getMinT()) && (c >= getMinC())
                && (maxX <= getMaxX()) && (maxY <= getMaxY()) && (maxZ <= getMaxZ()) && (maxT <= getMaxT())
                && (maxC <= getMaxC());
    }

    /**
     * Tests if the <code>Rectangle5D</code> entirely contains the specified
     * <code>Rectangle5D</code>.
     * 
     * @see #contains(double, double, double, double, double, double, double, double, double,
     *      double)
     */
    public boolean contains(Rectangle5D rect)
    {
        return contains(rect.getX(), rect.getY(), rect.getZ(), rect.getT(), rect.getC(), rect.getSizeX(),
                rect.getSizeY(), rect.getSizeZ(), rect.getSizeT(), rect.getSizeC());
    }

    /**
     * Tests if the interior of the <code>Rectangle5D</code> intersects the interior of a specified
     * 5D rectangular area.<br>
     * The 5D rectangular area is considered to intersect the <code>Rectangle5D</code> if any point
     * is contained in both the interior of the <code>Rectangle5D</code> and the specified
     * rectangular area.
     * 
     * @param x
     *        the X coordinate of the minimum corner position of the specified rectangular area
     * @param y
     *        the Y coordinate of the minimum corner position of the specified rectangular area
     * @param z
     *        the Z coordinate of the minimum corner position of the specified rectangular area
     * @param t
     *        the T coordinate of the minimum corner position of the specified rectangular area
     * @param c
     *        the C coordinate of the minimum corner position of the specified rectangular area
     * @param sizeX
     *        size for X dimension of the specified rectangular area
     * @param sizeY
     *        size for Y dimension of the specified rectangular area
     * @param sizeZ
     *        size for Z dimension of the specified rectangular area
     * @param sizeT
     *        size for T dimension of the specified rectangular area
     * @param sizeC
     *        size for C dimension of the specified rectangular area
     * @return <code>true</code> if the interior of the <code>Rectangle5D</code> and
     *         the interior of the 5D rectangular area intersect.
     */
    public boolean intersects(double x, double y, double z, double t, double c, double sizeX, double sizeY,
            double sizeZ, double sizeT, double sizeC)
    {
        final double maxX;
        final double maxY;
        final double maxZ;
        final double maxT;
        final double maxC;

        // special infinite case
        if (sizeX == java.lang.Double.POSITIVE_INFINITY)
            maxX = java.lang.Double.POSITIVE_INFINITY;
        else
            maxX = x + sizeX;
        // special infinite case
        if (sizeY == java.lang.Double.POSITIVE_INFINITY)
            maxY = java.lang.Double.POSITIVE_INFINITY;
        else
            maxY = y + sizeY;
        // special infinite case
        if (sizeZ == java.lang.Double.POSITIVE_INFINITY)
            maxZ = java.lang.Double.POSITIVE_INFINITY;
        else
            maxZ = z + sizeZ;
        // special infinite case
        if (sizeT == java.lang.Double.POSITIVE_INFINITY)
            maxT = java.lang.Double.POSITIVE_INFINITY;
        else
            maxT = t + sizeT;
        // special infinite case
        if (sizeC == java.lang.Double.POSITIVE_INFINITY)
            maxC = java.lang.Double.POSITIVE_INFINITY;
        else
            maxC = c + sizeC;

        return (maxX > getMinX()) && (maxY > getMinY()) && (maxZ > getMinZ()) && (maxT > getMinT())
                && (maxC > getMinC()) && (x < getMaxX()) && (y < getMaxY()) && (z < getMaxZ()) && (t < getMaxT())
                && (c < getMaxC());
    }

    /**
     * Tests if the interior of the <code>Rectangle5D</code> intersects the interior of a specified
     * <code>Rectangle5D</code>.<br>
     * 
     * @see #intersects(double, double, double, double, double, double, double, double, double,
     *      double)
     */
    public boolean intersects(Rectangle5D rect)
    {
        return intersects(rect.getX(), rect.getY(), rect.getZ(), rect.getT(), rect.getC(), rect.getSizeX(),
                rect.getSizeY(), rect.getSizeZ(), rect.getSizeT(), rect.getSizeC());
    }

    /**
     * Adds a 5D point, specified by the double precision coordinates arguments, to this
     * <code>Rectangle5D</code>. The resulting <code>Rectangle5D</code> is the smallest
     * <code>Rectangle5D</code> that contains both the original <code>Rectangle5D</code> and the
     * specified 5D point.
     * <p>
     * After adding a 5D point, a call to <code>contains</code> with the added point as an argument
     * does not necessarily return <code>true</code>. The <code>contains</code> method does not
     * return <code>true</code> for points on the edges of a rectangle. Therefore, if the added 5D
     * point falls on edge of the enlarged rectangle, <code>contains</code> returns
     * <code>false</code> for that point.
     * 
     * @param newx
     *        the X coordinate of the new point
     * @param newy
     *        the Y coordinate of the new point
     * @param newz
     *        the Z coordinate of the new point
     * @param newt
     *        the T coordinate of the new point
     * @param newc
     *        the C coordinate of the new point
     */
    public void add(double newx, double newy, double newz, double newt, double newc)
    {
        double x1 = Math.min(getMinX(), newx);
        double x2 = Math.max(getMaxX(), newx);
        double y1 = Math.min(getMinY(), newy);
        double y2 = Math.max(getMaxY(), newy);
        double z1 = Math.min(getMinZ(), newz);
        double z2 = Math.max(getMaxZ(), newz);
        double t1 = Math.min(getMinT(), newt);
        double t2 = Math.max(getMaxT(), newt);
        double c1 = Math.min(getMinC(), newc);
        double c2 = Math.max(getMaxC(), newc);

        double dx;
        double dy;
        double dz;
        double dt;
        double dc;

        // special infinite case
        if (x2 == java.lang.Double.POSITIVE_INFINITY)
            dx = java.lang.Double.POSITIVE_INFINITY;
        else
            dx = x2 - x1;
        // special infinite case
        if (y2 == java.lang.Double.POSITIVE_INFINITY)
            dy = java.lang.Double.POSITIVE_INFINITY;
        else
            dy = y2 - y1;
        // special infinite case
        if (z2 == java.lang.Double.POSITIVE_INFINITY)
            dz = java.lang.Double.POSITIVE_INFINITY;
        else
            dz = z2 - z1;
        // special infinite case
        if (t2 == java.lang.Double.POSITIVE_INFINITY)
            dt = java.lang.Double.POSITIVE_INFINITY;
        else
            dt = t2 - t1;
        // special infinite case
        if (c2 == java.lang.Double.POSITIVE_INFINITY)
            dc = java.lang.Double.POSITIVE_INFINITY;
        else
            dc = c2 - c1;

        setRect(x1, y1, z1, t1, c1, dx, dy, dz, dt, dc);
    }

    /**
     * Adds the <code>Point5D</code> object <code>pt</code> to this <code>Rectangle5D</code>.
     * The resulting <code>Rectangle5D</code> is the smallest <code>Rectangle5D</code> that contains
     * both the original <code>Rectangle5D</code> and the specified <code>Point5D</code>.
     * <p>
     * After adding a point, a call to <code>contains</code> with the added point as an argument
     * does not necessarily return <code>true</code>. The <code>contains</code> method does not
     * return <code>true</code> for points on the edges of a rectangle. Therefore, if the added
     * point falls on edge of the enlarged rectangle, <code>contains</code> returns
     * <code>false</code> for that point.
     * 
     * @param pt
     *        the new <code>Point5D</code> to add to this <code>Rectangle5D</code>.
     */
    public void add(Point5D pt)
    {
        add(pt.getX(), pt.getY(), pt.getZ(), pt.getT(), pt.getC());
    }

    /**
     * Adds a <code>Rectangle5D</code> object to this <code>Rectangle5D</code>. The resulting
     * <code>Rectangle5D</code> is the union of the two <code>Rectangle5D</code> objects.
     * 
     * @param r
     *        the <code>Rectangle5D</code> to add to this <code>Rectangle5D</code>.
     */
    public void add(Rectangle5D r)
    {
        union(this, r, this);
    }

    /**
     * Convert to 2D rectangle
     */
    public abstract Rectangle2D toRectangle2D();

    /**
     * Convert to 3D rectangle
     */
    public abstract Rectangle3D toRectangle3D();

    /**
     * Convert to 4D rectangle
     */
    public abstract Rectangle4D toRectangle4D();

    @Override
    public boolean equals(Object obj)
    {
        if (obj == this)
            return true;
        if (obj instanceof Rectangle5D)
        {
            final Rectangle5D rect = (Rectangle5D) obj;
            return (getX() == rect.getX()) && (getY() == rect.getY()) && (getC() == rect.getC())
                    && (getZ() == rect.getZ()) && (getT() == rect.getT()) && (getSizeX() == rect.getSizeX())
                    && (getSizeY() == rect.getSizeY()) && (getSizeC() == rect.getSizeC())
                    && (getSizeZ() == rect.getSizeZ()) && (getSizeT() == rect.getSizeT());
        }

        return super.equals(obj);
    }

    @Override
    public int hashCode()
    {
        long bits = java.lang.Double.doubleToLongBits(getX());
        bits ^= java.lang.Double.doubleToLongBits(getY());
        bits ^= java.lang.Double.doubleToLongBits(getC());
        bits ^= java.lang.Double.doubleToLongBits(getZ());
        bits ^= java.lang.Double.doubleToLongBits(getT());
        bits ^= java.lang.Double.doubleToLongBits(getSizeX());
        bits ^= java.lang.Double.doubleToLongBits(getSizeY());
        bits ^= java.lang.Double.doubleToLongBits(getSizeC());
        bits ^= java.lang.Double.doubleToLongBits(getSizeZ());
        bits ^= java.lang.Double.doubleToLongBits(getSizeT());
        return (((int) bits) ^ ((int) (bits >> 32)));
    }

    /**
     * Creates a new object of the same class as this object.
     * 
     * @return a clone of this instance.
     * @exception OutOfMemoryError
     *            if there is not enough memory.
     * @see java.lang.Cloneable
     */
    @Override
    public Object clone()
    {
        try
        {
            return super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }

    @Override
    public String toString()
    {
        return getClass().getName() + "[" + getX() + "," + getY() + "," + getZ() + "," + getT() + "," + getC() + " - "
                + getSizeX() + "," + getSizeY() + "," + getSizeZ() + "," + getSizeT() + "," + getSizeC() + "]";
    }

    public static class Double extends Rectangle5D
    {
        public double x;
        public double y;
        public double z;
        public double t;
        public double c;

        public double sizeX;
        public double sizeY;
        public double sizeZ;
        public double sizeT;
        public double sizeC;

        public Double(double x, double y, double z, double t, double c, double sizeX, double sizeY, double sizeZ,
                double sizeT, double sizeC)
        {
            super();

            this.x = x;
            this.y = y;
            this.z = z;
            this.t = t;
            this.c = c;
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            this.sizeZ = sizeZ;
            this.sizeT = sizeT;
            this.sizeC = sizeC;
        }

        public Double(Rectangle5D r)
        {
            this(r.getX(), r.getY(), r.getZ(), r.getT(), r.getC(), r.getSizeX(), r.getSizeY(), r.getSizeZ(), r
                    .getSizeT(), r.getSizeC());
        }

        public Double()
        {
            this(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }

        @Override
        public void setRect(double x, double y, double z, double t, double c, double sizeX, double sizeY, double sizeZ,
                double sizeT, double sizeC)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            this.t = t;
            this.c = c;
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            this.sizeZ = sizeZ;
            this.sizeT = sizeT;
            this.sizeC = sizeC;
        }

        @Override
        public double getX()
        {
            return x;
        }

        @Override
        public void setX(double value)
        {
            x = value;
        }

        @Override
        public double getY()
        {
            return y;
        }

        @Override
        public void setY(double value)
        {
            y = value;
        }

        @Override
        public double getZ()
        {
            return z;
        }

        @Override
        public void setZ(double value)
        {
            z = value;
        }

        @Override
        public double getT()
        {
            return t;
        }

        @Override
        public void setT(double value)
        {
            t = value;
        }

        @Override
        public double getC()
        {
            return c;
        }

        @Override
        public void setC(double value)
        {
            c = value;
        }

        @Override
        public double getSizeX()
        {
            return sizeX;
        }

        @Override
        public void setSizeX(double value)
        {
            sizeX = value;
        }

        @Override
        public double getSizeY()
        {
            return sizeY;
        }

        @Override
        public void setSizeY(double value)
        {
            sizeY = value;
        }

        @Override
        public double getSizeZ()
        {
            return sizeZ;
        }

        @Override
        public void setSizeZ(double value)
        {
            sizeZ = value;
        }

        @Override
        public double getSizeT()
        {
            return sizeT;
        }

        @Override
        public void setSizeT(double value)
        {
            sizeT = value;
        }

        @Override
        public double getSizeC()
        {
            return sizeC;
        }

        @Override
        public void setSizeC(double value)
        {
            sizeC = value;
        }

        @Override
        public Point5D.Double getPosition()
        {
            return new Point5D.Double(x, y, z, t, c);
        }

        @Override
        public Dimension5D.Double getDimension()
        {
            return new Dimension5D.Double(sizeX, sizeY, sizeZ, sizeT, sizeC);
        }

        @Override
        public Rectangle5D createIntersection(Rectangle5D r)
        {
            final Rectangle5D.Double result = new Rectangle5D.Double();

            intersect(this, r, result);

            return result;
        }

        @Override
        public Rectangle5D createUnion(Rectangle5D r)
        {
            final Rectangle5D.Double result = new Rectangle5D.Double();

            union(this, r, result);

            return result;
        }

        @Override
        public Rectangle2D toRectangle2D()
        {
            return new Rectangle2D.Double(x, y, sizeX, sizeY);
        }

        @Override
        public Rectangle3D toRectangle3D()
        {
            return new Rectangle3D.Double(x, y, z, sizeX, sizeY, sizeZ);
        }

        @Override
        public Rectangle4D toRectangle4D()
        {
            return new Rectangle4D.Double(x, y, z, t, sizeX, sizeY, sizeZ, sizeT);
        }
    }

    public static class Float extends Rectangle5D
    {
        public float x;
        public float y;
        public float z;
        public float t;
        public float c;

        public float sizeX;
        public float sizeY;
        public float sizeZ;
        public float sizeT;
        public float sizeC;

        public Float(float x, float y, float z, float t, float c, float sizeX, float sizeY, float sizeZ, float sizeT,
                float sizeC)
        {
            super();

            this.x = x;
            this.y = y;
            this.z = z;
            this.t = t;
            this.c = c;
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            this.sizeZ = sizeZ;
            this.sizeT = sizeT;
            this.sizeC = sizeC;
        }

        public Float(Rectangle5D r)
        {
            this((float) r.getX(), (float) r.getY(), (float) r.getZ(), (float) r.getT(), (float) r.getC(), (float) r
                    .getSizeX(), (float) r.getSizeY(), (float) r.getSizeZ(), (float) r.getSizeT(), (float) r.getSizeC());
        }

        public Float()
        {
            this(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }

        @Override
        public void setRect(double x, double y, double z, double t, double c, double sizeX, double sizeY, double sizeZ,
                double sizeT, double sizeC)
        {
            this.x = (float) x;
            this.y = (float) y;
            this.z = (float) z;
            this.t = (float) t;
            this.c = (float) c;
            this.sizeX = (float) sizeX;
            this.sizeY = (float) sizeY;
            this.sizeZ = (float) sizeZ;
            this.sizeT = (float) sizeT;
            this.sizeC = (float) sizeC;
        }

        @Override
        public double getX()
        {
            // special infinite case
            if (x == java.lang.Float.NEGATIVE_INFINITY)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (x == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return x;
        }

        @Override
        public void setX(double value)
        {
            x = (float) value;
        }

        @Override
        public double getY()
        {
            // special infinite case
            if (y == java.lang.Float.NEGATIVE_INFINITY)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (y == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return y;
        }

        @Override
        public void setY(double value)
        {
            y = (float) value;
        }

        @Override
        public double getZ()
        {
            // special infinite case
            if (z == java.lang.Float.NEGATIVE_INFINITY)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (z == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return z;
        }

        @Override
        public void setZ(double value)
        {
            z = (float) value;
        }

        @Override
        public double getT()
        {
            // special infinite case
            if (t == java.lang.Float.NEGATIVE_INFINITY)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (t == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return t;
        }

        @Override
        public void setT(double value)
        {
            t = (float) value;
        }

        @Override
        public double getC()
        {
            // special infinite case
            if (c == java.lang.Float.NEGATIVE_INFINITY)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (c == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return c;
        }

        @Override
        public void setC(double value)
        {
            c = (float) value;
        }

        @Override
        public double getSizeX()
        {
            // special infinite case
            if (sizeX == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeX;
        }

        @Override
        public void setSizeX(double value)
        {
            sizeX = (float) value;
        }

        @Override
        public double getSizeY()
        {
            // special infinite case
            if (sizeY == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeY;
        }

        @Override
        public void setSizeY(double value)
        {
            sizeY = (float) value;
        }

        @Override
        public double getSizeZ()
        {
            // special infinite case
            if (sizeZ == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeZ;
        }

        @Override
        public void setSizeZ(double value)
        {
            sizeZ = (float) value;
        }

        @Override
        public double getSizeT()
        {
            // special infinite case
            if (sizeT == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeT;
        }

        @Override
        public void setSizeT(double value)
        {
            sizeT = (float) value;
        }

        @Override
        public double getSizeC()
        {
            // special infinite case
            if (sizeC == java.lang.Float.POSITIVE_INFINITY)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeC;
        }

        @Override
        public void setSizeC(double value)
        {
            sizeC = (float) value;
        }

        @Override
        public Point5D.Float getPosition()
        {
            return new Point5D.Float(x, y, z, t, c);
        }

        @Override
        public Dimension5D.Float getDimension()
        {
            return new Dimension5D.Float(sizeX, sizeY, sizeZ, sizeT, sizeC);
        }

        @Override
        public Rectangle5D createIntersection(Rectangle5D r)
        {
            final Rectangle5D.Float result = new Rectangle5D.Float();

            intersect(this, r, result);

            return result;
        }

        @Override
        public Rectangle5D createUnion(Rectangle5D r)
        {
            final Rectangle5D.Float result = new Rectangle5D.Float();

            union(this, r, result);

            return result;
        }

        @Override
        public Rectangle2D toRectangle2D()
        {
            return new Rectangle2D.Float(x, y, sizeX, sizeY);
        }

        @Override
        public Rectangle3D toRectangle3D()
        {
            return new Rectangle3D.Float(x, y, z, sizeX, sizeY, sizeZ);
        }

        @Override
        public Rectangle4D toRectangle4D()
        {
            return new Rectangle4D.Float(x, y, z, t, sizeX, sizeY, sizeZ, sizeT);
        }
    }

    public static class Integer extends Rectangle5D
    {
        public int x;
        public int y;
        public int z;
        public int t;
        public int c;
        public int sizeX;
        public int sizeY;
        public int sizeZ;
        public int sizeT;
        public int sizeC;

        public Integer(int x, int y, int z, int t, int c, int sizeX, int sizeY, int sizeZ, int sizeT, int sizeC)
        {
            super();

            this.x = x;
            this.y = y;
            this.z = z;
            this.t = t;
            this.c = c;
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            this.sizeZ = sizeZ;
            this.sizeT = sizeT;
            this.sizeC = sizeC;
        }

        public Integer(Rectangle5D.Integer r)
        {
            this(r.x, r.y, r.z, r.t, r.c, r.sizeX, r.sizeY, r.sizeZ, r.sizeT, r.sizeC);
        }

        public Integer(Rectangle5D r)
        {
            this(r.toInteger());
        }

        public Integer()
        {
            this(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }

        /**
         * Sets the bounds of this {@code Rectangle5D} to the integer bounds
         * which encompass the specified double bounds.
         * 
         * @param x
         *        the X coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param y
         *        the Y coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param z
         *        the Z coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param t
         *        the T coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param c
         *        the C coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param sizeX
         *        size for X dimension of this <code>Rectangle5D</code>
         * @param sizeY
         *        size for Y dimension of this <code>Rectangle5D</code>
         * @param sizeZ
         *        size for Z dimension of this <code>Rectangle5D</code>
         * @param sizeT
         *        size for T dimension of this <code>Rectangle5D</code>
         * @param sizeC
         *        size for C dimension of this <code>Rectangle5D</code>
         */
        @Override
        public void setRect(double x, double y, double z, double t, double c, double sizeX, double sizeY, double sizeZ,
                double sizeT, double sizeC)
        {
            final Rectangle5D.Integer r = new Rectangle5D.Double(x, y, z, t, c, sizeX, sizeY, sizeZ, sizeT, sizeC)
                    .toInteger();
            setRect(r.x, r.y, r.z, r.t, r.c, r.sizeX, r.sizeY, r.sizeZ, r.sizeT, r.sizeC);
        }

        /**
         * Sets the position and size of this <code>Rectangle5D</code> to the specified
         * <code>integer</code> values.
         * 
         * @param x
         *        the X coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param y
         *        the Y coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param z
         *        the Z coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param t
         *        the T coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param c
         *        the C coordinate of the minimum corner position of this <code>Rectangle5D</code>
         * @param sizeX
         *        size for X dimension of this <code>Rectangle5D</code>
         * @param sizeY
         *        size for Y dimension of this <code>Rectangle5D</code>
         * @param sizeZ
         *        size for Z dimension of this <code>Rectangle5D</code>
         * @param sizeT
         *        size for T dimension of this <code>Rectangle5D</code>
         * @param sizeC
         *        size for C dimension of this <code>Rectangle5D</code>
         */
        public void setRect(int x, int y, int z, int t, int c, int sizeX, int sizeY, int sizeZ, int sizeT, int sizeC)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            this.t = t;
            this.c = c;
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            this.sizeZ = sizeZ;
            this.sizeT = sizeT;
            this.sizeC = sizeC;
        }

        @Override
        public double getX()
        {
            // special infinite case
            if (x == java.lang.Integer.MIN_VALUE)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (x == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return x;
        }

        @Override
        public void setX(double value)
        {
            x = (int) value;
        }

        @Override
        public double getY()
        {
            // special infinite case
            if (y == java.lang.Integer.MIN_VALUE)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (y == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return y;
        }

        @Override
        public void setY(double value)
        {
            y = (int) value;
        }

        @Override
        public double getZ()
        {
            // special infinite case
            if (z == java.lang.Integer.MIN_VALUE)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (z == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return z;
        }

        @Override
        public void setZ(double value)
        {
            z = (int) value;
        }

        @Override
        public double getT()
        {
            // special infinite case
            if (t == java.lang.Integer.MIN_VALUE)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (t == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return t;
        }

        @Override
        public void setT(double value)
        {
            t = (int) value;
        }

        @Override
        public double getC()
        {
            // special infinite case
            if (c == java.lang.Integer.MIN_VALUE)
                return java.lang.Double.NEGATIVE_INFINITY;
            if (c == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return c;
        }

        @Override
        public void setC(double value)
        {
            c = (int) value;
        }

        @Override
        public double getSizeX()
        {
            // special infinite case
            if (sizeX == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeX;
        }

        @Override
        public void setSizeX(double value)
        {
            sizeX = (int) value;
        }

        @Override
        public double getSizeY()
        {
            // special infinite case
            if (sizeY == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeY;
        }

        @Override
        public void setSizeY(double value)
        {
            sizeY = (int) value;
        }

        @Override
        public double getSizeZ()
        {
            // special infinite case
            if (sizeZ == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeZ;
        }

        @Override
        public void setSizeZ(double value)
        {
            sizeZ = (int) value;
        }

        @Override
        public double getSizeT()
        {
            // special infinite case
            if (sizeT == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeT;
        }

        @Override
        public void setSizeT(double value)
        {
            sizeT = (int) value;
        }

        @Override
        public double getSizeC()
        {
            // special infinite case
            if (sizeC == java.lang.Integer.MAX_VALUE)
                return java.lang.Double.POSITIVE_INFINITY;

            return sizeC;
        }

        @Override
        public void setSizeC(double value)
        {
            sizeC = (int) value;
        }

        @Override
        public Point5D.Integer getPosition()
        {
            return new Point5D.Integer(x, y, z, t, c);
        }

        @Override
        public Dimension5D.Integer getDimension()
        {
            return new Dimension5D.Integer(sizeX, sizeY, sizeZ, sizeT, sizeC);
        }

        @Override
        public Rectangle5D.Integer toInteger()
        {
            return (Integer) clone();
        }

        @Override
        public Rectangle5D createIntersection(Rectangle5D r)
        {
            final Rectangle5D.Integer result = new Rectangle5D.Integer();

            intersect(this, r, result);

            return result;
        }

        @Override
        public Rectangle5D createUnion(Rectangle5D r)
        {
            final Rectangle5D.Integer result = new Rectangle5D.Integer();

            union(this, r, result);

            return result;
        }

        @Override
        public Rectangle2D toRectangle2D()
        {
            return new Rectangle(x, y, sizeX, sizeY);
        }

        @Override
        public Rectangle3D toRectangle3D()
        {
            return new Rectangle3D.Integer(x, y, z, sizeX, sizeY, sizeZ);
        }

        @Override
        public Rectangle4D toRectangle4D()
        {
            return new Rectangle4D.Integer(x, y, z, t, sizeX, sizeY, sizeZ, sizeT);
        }
    }
}