/* Poly2Tri * Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Poly2Tri nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; namespace WPM.Poly2Tri { public class Rect2D { private double mMinX; // left private double mMaxX; // right private double mMinY; // bottom // top private double mMaxY; // top // bottom public double MinX { get { return mMinX; } set { mMinX = value; } } public double MaxX { get { return mMaxX; } set { mMaxX = value; } } public double MinY { get { return mMinY; } set { mMinY = value; } } public double MaxY { get { return mMaxY; } set { mMaxY = value; } } public double Left { get { return mMinX; } set { mMinX = value; } } public double Right { get { return mMaxX; } set { mMaxX = value; } } public double Top { get { return mMaxY; } set { mMaxY = value; } } public double Bottom { get { return mMinY; } set { mMinY = value; } } public double Width { get { return (Right - Left); } } public double Height { get { return (Top - Bottom); } } public bool Empty { get { return (Left == Right) || (Top == Bottom); } } public Rect2D () { Clear (); } public override int GetHashCode () { return base.GetHashCode (); } public override bool Equals (Object obj) { Rect2D r = obj as Rect2D; if (r != null) { return Equals (r); } return base.Equals (obj); } public bool Equals (Rect2D r) { return Equals (r, MathUtil.EPSILON); } public bool Equals (Rect2D r, double epsilon) { if (!MathUtil.AreValuesEqual (MinX, r.MinX, epsilon)) { return false; } if (!MathUtil.AreValuesEqual (MaxX, r.MaxX)) { return false; } if (!MathUtil.AreValuesEqual (MinY, r.MinY, epsilon)) { return false; } if (!MathUtil.AreValuesEqual (MaxY, r.MaxY, epsilon)) { return false; } return true; } public void Clear () { MinX = Double.MaxValue; MaxX = Double.MinValue; MinY = Double.MaxValue; MaxY = Double.MinValue; } public void Set (double xmin, double xmax, double ymin, double ymax) { MinX = xmin; MaxX = xmax; MinY = ymin; MaxY = ymax; Normalize (); } public void Set (Rect2D b) { MinX = b.MinX; MaxX = b.MaxX; MinY = b.MinY; MaxY = b.MaxY; } public void SetSize (double w, double h) { Right = Left + w; Top = Bottom + h; } /// /// Returns whether the coordinate is inside the bounding box. Note that this will return /// false if the point is ON the edge of the bounding box. If you want to test for whether /// the point is inside OR on the rect, use ContainsInclusive /// public bool Contains (double x, double y) { return (x > Left) && (y > Bottom) && (x < Right) && (y < Top); } public bool Contains (Point2D p) { return Contains (p.X, p.Y); } public bool Contains (Rect2D r) { return (Left < r.Left) && (Right > r.Right) && (Top < r.Top) && (Bottom > r.Bottom); } /// /// Returns whether the coordinate is inside the bounding box. Note that this will return /// false if the point is ON the edge of the bounding box. If you want to test for whether /// the point is inside OR on the rect, use ContainsInclusive /// public bool ContainsInclusive (double x, double y) { return (x >= Left) && (y >= Top) && (x <= Right) && (y <= Bottom); } public bool ContainsInclusive (double x, double y, double epsilon) { return ((x + epsilon) >= Left) && ((y + epsilon) >= Top) && ((x - epsilon) <= Right) && ((y - epsilon) <= Bottom); } public bool ContainsInclusive (Point2D p) { return ContainsInclusive (p.X, p.Y); } public bool ContainsInclusive (Point2D p, double epsilon) { return ContainsInclusive (p.X, p.Y, epsilon); } public bool ContainsInclusive (Rect2D r) { return (Left <= r.Left) && (Right >= r.Right) && (Top <= r.Top) && (Bottom >= r.Bottom); } public bool ContainsInclusive (Rect2D r, double epsilon) { return ((Left - epsilon) <= r.Left) && ((Right + epsilon) >= r.Right) && ((Top - epsilon) <= r.Top) && ((Bottom + epsilon) >= r.Bottom); } public bool Intersects (Rect2D r) { return (Right > r.Left) && (Left < r.Right) && (Bottom < r.Top) && (Top > r.Bottom); } public Point2D GetCenter () { Point2D p = new Point2D ((Left + Right) / 2, (Bottom + Top) / 2); return p; } public bool IsNormalized () { return (Right >= Left) && (Bottom <= Top); } public void Normalize () { if (Left > Right) { MathUtil.Swap (ref mMinX, ref mMaxX); } if (Bottom < Top) { MathUtil.Swap (ref mMinY, ref mMaxY); } } public void AddPoint (Point2D p) { MinX = Math.Min (MinX, p.X); MaxX = Math.Max (MaxX, p.X); MinY = Math.Min (MinY, p.Y); MaxY = Math.Max (MaxY, p.Y); } public void Inflate (double w, double h) { Left -= w; Top += h; Right += w; Bottom -= h; } public void Inflate (double left, double top, double right, double bottom) { Left -= left; Top += top; Right += right; Bottom -= bottom; } public void Offset (double w, double h) { Left += w; Top += h; Right += w; Bottom += h; } public void SetPosition (double x, double y) { double w = Right - Left; double h = Bottom - Top; Left = x; Bottom = y; Right = x + w; Top = y + h; } /// Intersection /// /// Sets the rectangle to the intersection of two rectangles. /// Returns true if there is any intersection between the two rectangles. /// If there is no intersection, the rectangle is set to 0, 0, 0, 0. /// Either of the input rectangles may be the same as destination rectangle. /// public bool Intersection (Rect2D r1, Rect2D r2) { if (!TriangulationUtil.RectsIntersect (r1, r2)) { Left = Right = Top = Bottom = 0.0; return false; } Left = (r1.Left > r2.Left) ? r1.Left : r2.Left; Top = (r1.Top < r2.Top) ? r1.Top : r2.Top; Right = (r1.Right < r2.Right) ? r1.Right : r2.Right; Bottom = (r1.Bottom > r2.Bottom) ? r1.Bottom : r2.Bottom; return true; } /// Union /// /// Sets the rectangle to the union of two rectangles r1 and r2. /// If either rect is empty, it is ignored. If both are empty, the rectangle /// is set to r1. /// Either of the input rectangle references may refer to the destination rectangle. /// public void Union (Rect2D r1, Rect2D r2) { if ((r2.Right == r2.Left) || (r2.Bottom == r2.Top)) { Set (r1); } else if ((r1.Right == r1.Left) || (r1.Bottom == r1.Top)) { Set (r2); } else { Left = (r1.Left < r2.Left) ? r1.Left : r2.Left; Top = (r1.Top > r2.Top) ? r1.Top : r2.Top; Right = (r1.Right > r2.Right) ? r1.Right : r2.Right; Bottom = (r1.Bottom < r2.Bottom) ? r1.Bottom : r2.Bottom; } } } }