Mercurial > projects > dwt-addons
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/geometry/PrecisionRectangle.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,396 @@ +/******************************************************************************* + * 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); +} + +}