view dwtx/draw2d/geometry/PrecisionRectangle.d @ 98:95307ad235d9

Added Draw2d code, still work in progress
author Frank Benoit <benoit@tionex.de>
date Sun, 03 Aug 2008 00:52:14 +0200
parents
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2003, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 * Port to the D programming language:
 *     Frank Benoit <benoit@tionex.de>
 *******************************************************************************/
module dwtx.draw2d.geometry.PrecisionRectangle;

import dwt.dwthelper.utils;
import dwtx.draw2d.geometry.Rectangle;
import dwtx.draw2d.geometry.Insets;
import dwtx.draw2d.geometry.Point;
import dwtx.draw2d.geometry.Dimension;
import dwtx.draw2d.geometry.PrecisionPoint;

/**
 * A Rectangle implementation using floating point values which are truncated into the inherited
 * integer fields. The use of floating point prevents rounding errors from accumulating.
 * @author hudsonr
 * Created on Apr 9, 2003
 */
public final class PrecisionRectangle : Rectangle {

/** Double value for height */
public double preciseHeight_;

/** Double value for width */
public double preciseWidth_;

/** Double value for X */
public double preciseX_;

/** Double value for Y */
public double preciseY_;

/**
 * Constructs a new PrecisionRectangle with all values 0.
 */
public this() { }

/**
 * Constructs a new PrecisionRectangle from the given integer Rectangle.
 * @param rect the base rectangle
 */
public this(Rectangle rect) {
    preciseX_ = rect.preciseX();
    preciseY_ = rect.preciseY();
    preciseWidth_ = rect.preciseWidth();
    preciseHeight_ = rect.preciseHeight();
    updateInts();
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#getCopy()
 */
public Rectangle getCopy() {
    return getPreciseCopy();
}

/**
 * Returns a precise copy of this.
 * @return a precise copy
 */
public PrecisionRectangle getPreciseCopy() {
    PrecisionRectangle result = new PrecisionRectangle();
    result.preciseX_ = preciseX_;
    result.preciseY_ = preciseY_;
    result.preciseWidth_ = preciseWidth_;
    result.preciseHeight_ = preciseHeight_;
    result.updateInts();
    return result;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#crop(dwtx.draw2d.geometry.Insets)
 */
public Rectangle crop(Insets insets) {
    if (insets is null)
        return this;
    setX(preciseX_ + insets.left);
    setY(preciseY_ + insets.top);
    setWidth(preciseWidth_ - (insets.getWidth()));
    setHeight(preciseHeight_ - (insets.getHeight()));

    return this;
}

/**
 * @see Rectangle#equals(Object)
 */
public override int opEquals(Object o) {
    if ( auto pr = cast(PrecisionRectangle)o ) {
        return super.opEquals(o)
            && Math.abs(pr.preciseX_ - preciseX_) < 0.000000001
            && Math.abs(pr.preciseY_ - preciseY_) < 0.000000001
            && Math.abs(pr.preciseWidth_ - preciseWidth_) < 0.000000001
            && Math.abs(pr.preciseHeight_ - preciseHeight_) < 0.00000001;
    }

    return super.opEquals(o);
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#performScale(double)
 */
public void performScale(double factor) {
    preciseX_ *= factor;
    preciseY_ *= factor;
    preciseWidth_ *= factor;
    preciseHeight_ *= factor;
    updateInts();
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#performTranslate(int, int)
 */
public void performTranslate(int dx, int dy) {
    preciseX_ += dx;
    preciseY_ += dy;
    x += dx;
    y += dy;
}

/**
 * Returns the bottom coordinte in double precision.
 * @return the precise bottom
 */
public double preciseBottom() {
    return preciseHeight_ + preciseY_;
}

/**
 * Returns the right side in double precision.
 * @return the precise right
 */
public double preciseRight() {
    return preciseWidth_ + preciseX_;
}


/**
 * @see dwtx.draw2d.geometry.Rectangle#resize(dwtx.draw2d.geometry.Dimension)
 */
public Rectangle resize(Dimension sizeDelta) {
    preciseWidth_ += sizeDelta.preciseWidth();
    preciseHeight_ += sizeDelta.preciseHeight();
    updateInts();
    return this;
}

/**
 * Sets the height.
 * @param value the new height
 */
public void setHeight(double value) {
    preciseHeight_ = value;
    height = cast(int)Math.floor(preciseHeight_ + 0.000000001);
}

/**
 * Sets the width.
 * @param value the new width
 */
public void setWidth(double value) {
    preciseWidth_ = value;
    width = cast(int)Math.floor(preciseWidth_ + 0.000000001);
}

/**
 * Sets the x value.
 * @param value the new x value
 */
public void setX(double value) {
    preciseX_ = value;
    x = cast(int)Math.floor(preciseX_ + 0.000000001);
}

/**
 * Sets the y value.
 * @param value the new y value
 */
public void setY(double value) {
    preciseY_ = value;
    y = cast(int)Math.floor(preciseY_ + 0.000000001);
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#translate(dwtx.draw2d.geometry.Point)
 */
public Rectangle translate(Point p) {
    preciseX_ += p.preciseX();
    preciseY_ += p.preciseY();
    updateInts();
    return this;
}

/**
 * Unions the given PrecisionRectangle with this rectangle and returns <code>this</code>
 * for convenience.
 * @since 3.0
 * @param other the rectangle being unioned
 * @return <code>this</code> for convenience
 * @deprecated
 * Use {@link #union(Rectangle)} instead
 */
public PrecisionRectangle union_(PrecisionRectangle other) {
    double newright = Math.max(preciseRight(), other.preciseRight());
    double newbottom = Math.max(preciseBottom(), other.preciseBottom());
    preciseX_ = Math.min(preciseX_, other.preciseX_);
    preciseY_ = Math.min(preciseY_, other.preciseY_);
    preciseWidth_ = newright - preciseX_;
    preciseHeight_ = newbottom - preciseY_;
    updateInts();

    return this;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#union(dwtx.draw2d.geometry.Rectangle)
 */
public Rectangle union_(Rectangle other) {
    double newright = Math.max(preciseRight(), other.preciseX() + other.preciseWidth());
    double newbottom = Math.max(preciseBottom(), other.preciseY() + other.preciseHeight());
    preciseX_ = Math.min(preciseX_, other.preciseX());
    preciseY_ = Math.min(preciseY_, other.preciseY());
    preciseWidth_ = newright - preciseX_;
    preciseHeight_ = newbottom - preciseY_;
    updateInts();

    return this;
}

/**
 * Updates the integer values based on the current precise values.  The integer values ar
 * the floor of the double values.  This is called automatically when calling api which is
 * overridden in this class.
 * @since 3.0
 */
public void updateInts() {
    x = cast(int)Math.floor(preciseX_ + 0.000000001);
    y = cast(int)Math.floor(preciseY_ + 0.000000001);
    width = cast(int)Math.floor(preciseWidth_ + preciseX_ + 0.000000001) - x;
    height = cast(int)Math.floor(preciseHeight_ + preciseY_ + 0.000000001) - y;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#union(dwtx.draw2d.geometry.Point)
 */
public void union_(Point p) {
    if (p.preciseX() < preciseX_) {
        preciseWidth_ += (preciseX_ - p.preciseX());
        preciseX_ = p.preciseX();
    } else {
        double right = preciseX_ + preciseWidth_;
        if (p.preciseX() > right) {
            preciseWidth_ = p.preciseX() - preciseX_;
        }
    }
    if (p.preciseY() < preciseY_) {
        preciseHeight_ += (preciseY - p.preciseY());
        preciseY_ = p.preciseY();
    } else {
        double bottom = preciseY_ + preciseHeight_;
        if (p.preciseY() > bottom) {
            preciseHeight_ = p.preciseY() - preciseY_;
        }
    }
    updateInts();
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#transpose()
 */
public Rectangle transpose() {
    double temp = preciseX_;
    preciseX_ = preciseY_;
    preciseY_ = temp;
    temp = preciseWidth_;
    preciseWidth_ = preciseHeight_;
    preciseHeight_ = temp;
    super.transpose();
    return this;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#setLocation(dwtx.draw2d.geometry.Point)
 */
public Rectangle setLocation(Point loc) {
    preciseX_ = loc.preciseX();
    preciseY_ = loc.preciseY();
    updateInts();
    return this;
}

/**
 * Returns the precise geometric centre of the rectangle
 *
 * @return <code>PrecisionPoint</code> geometric center of the rectangle
 * @since 3.4
 */
public Point getCenter() {
    return new PrecisionPoint(preciseX_ + preciseWidth_ / 2.0, preciseY_ + preciseHeight_ / 2.0);
}

/**
 * Shrinks the sides of this Rectangle by the horizontal and vertical values
 * provided as input, and returns this Rectangle for convenience. The center of
 * this Rectangle is kept constant.
 *
 * @param h  Horizontal reduction amount
 * @param v  Vertical reduction amount
 * @return  <code>this</code> for convenience
 * @since 3.4
 */
public Rectangle shrink(double h, double v) {
    preciseX_ += h;
    preciseWidth_ -= (h + h);
    preciseY_ += v;
    preciseHeight_ -= (v + v);
    updateInts();
    return this;
}

/**
 * Expands the horizontal and vertical sides of this Rectangle with the values
 * provided as input, and returns this for convenience. The location of its
 * center is kept constant.
 *
 * @param h  Horizontal increment
 * @param v  Vertical increment
 * @return  <code>this</code> for convenience
 * @since 3.4
 */
public Rectangle expand(double h, double v) {
    return shrink(-h, -v);
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#shrink(int, int)
 */
public Rectangle shrink(int h, int v) {
    return shrink(cast(double)h, cast(double)v);
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#contains(dwtx.draw2d.geometry.Point)
 */
public bool contains(Point p) {
    return preciseX_ <= p.preciseX() && p.preciseX() <= preciseX_ + preciseWidth_
    && preciseY_ <= p.preciseY() && p.preciseY() <= preciseY_ + preciseHeight_;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#preciseX()
 */
public double preciseX() {
    return preciseX_;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#preciseY()
 */
public double preciseY() {
    return preciseY_;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#preciseWidth()
 */
public double preciseWidth() {
    return preciseWidth_;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#preciseHeight()
 */
public double preciseHeight() {
    return preciseHeight_;
}

/**
 * @see dwtx.draw2d.geometry.Rectangle#setSize(dwtx.draw2d.geometry.Dimension)
 */
public Rectangle setSize(Dimension d) {
    preciseWidth_ = d.preciseWidth();
    preciseHeight_ = d.preciseHeight();
    return super.setSize(d);
}

}