Click here to Skip to main content
15,892,480 members
Articles / Programming Languages / C# 4.0

The List Trifecta, Part 2

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
7 Sep 2013LGPL310 min read 28.7K   317   12  
The BDictionary is like a Dictionary mashed up with List<T>. BList and BMultiMap also say hello.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Loyc.Math
{
	/// <summary>Holds a mutable 2D bounding rectangle.</summary>
	/// <typeparam name="T">Data type of each coordinate.</typeparam>
	/// <remarks>Several extension methods are provided in <see cref="BoundingBoxExt"/>.</remarks>
	public class BoundingBox<T> : IRectangle<T>, INewRectangle<BoundingBox<T>,T>
		where T : IConvertible, IComparable<T>, IEquatable<T>
	{
		static IAdditionGroup<T> m = Maths<T>.IAdditionGroup;
		static IInrementer<T> inc = Maths<T>.IInrementer;
		static INumTraits<T> traits = Maths<T>.Traits;

		public BoundingBox(T minX, T minY, T maxX, T maxY) 
			{ _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY; }
		public BoundingBox(Point<T> p) 
			{ _minX = p.X; _minY = p.Y; _maxX = p.X; _maxY = p.Y; }
		public BoundingBox(Point<T> p1, Point<T> p2)
			{ _minX = p1.X; _minY = p1.Y; _maxX = p2.X; _maxY = p2.Y; Normalize(); }
		public BoundingBox(IEnumerable<Point<T>> pts)
		{
			var e = pts.GetEnumerator();
			if (!e.MoveNext())
			{
				_minX = _minY = _maxX = _maxY = traits.NaN;
				return;
			}
			var p = e.Current;
			_minX = p.X; _minY = p.Y; _maxX = p.X; _maxY = p.Y;

			while (e.MoveNext())
				RectangleExt.ExpandToInclude<BoundingBox<T>,Point<T>,T>(this, e.Current);
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)] // reduce clutter
		private T _minX, _minY, _maxX, _maxY;

		public T X1 { get { return _minX; } set { _minX = value; } }
		public T Y1 { get { return _minY; } set { _minY = value; } }
		public T X2 { get { return _maxX; } set { _maxX = value; } }
		public T Y2 { get { return _maxY; } set { _maxY = value; } }

		public T Width
		{
			get { return inc.NextHigher(m.Subtract(_maxX, _minX)); }
			set { X2 = inc.NextLower(m.Add(X1, value)); }
		}
		public T Height 
		{
			get { return inc.NextHigher(m.Subtract(_maxY, _minY)); }
			set { Y2 = inc.NextLower(m.Add(Y1, value)); }
		}
		
		[DebuggerBrowsable(DebuggerBrowsableState.Never)] // reduce clutter
		public Point<T> MinPoint
		{
			get { return new Point<T>(_minX, _minY); }
			set { _minX = value.X; _minY = value.Y; }
		}
		[DebuggerBrowsable(DebuggerBrowsableState.Never)] // reduce clutter
		public Point<T> MaxPoint
		{
			get { return new Point<T>(_maxX, _maxY); }
			set { _maxX = value.X; _maxY = value.Y; }
		}

		public BoundingBox<T> NewRect(T x, T y, T width, T height)
		{
			return new BoundingBox<T>(x, y, inc.NextLower(m.Add(x, width)), inc.NextLower(m.Add(y, height)));
		}
		public BoundingBox<T> NewRange(T x1, T y1, T x2, T y2)
		{
			return new BoundingBox<T>(x1, y1, x2, y2);
		}
		IRectangle<T> INewRectangle<IRectangle<T>, T>.NewRect(T x, T y, T width, T height)
		{
			return new BoundingBox<T>(x, y, inc.NextLower(m.Add(x, width)), inc.NextLower(m.Add(y, height)));
		}
		IRectangle<T> INewRectangle<IRectangle<T>, T>.NewRange(T x1, T y1, T x2, T y2)
		{
			return new BoundingBox<T>(x1, y1, x2, y2);
		}

		public void SetXAndWidth(T x, T width)
		{
			SetXRange(x, inc.NextLower(m.Add(x, width)));
		}
		public void SetYAndHeight(T y, T height)
		{
			SetYRange(y, inc.NextLower(m.Add(y, height)));
		}
		public void SetXRange(T x1, T x2)
		{
			_minX = x1;
			_maxX = x2;
		}
		public void SetYRange(T y1, T y2)
		{
			_minY = y1;
			_maxY = y2;
		}
		public bool IsNormal()
		{
			return _maxX.CompareTo(_minX) >= 0 && _maxY.CompareTo(_minY) >= 0;
		}
		public void Normalize()
		{
			RectangleExt.Normalize<BoundingBox<T>, T>(this);
		}
		public BoundingBox<T> Union(BoundingBox<T> b)
		{
			return RectangleExt.Union<BoundingBox<T>, T>(this, b);
		}
		public BoundingBox<T> Intersect(BoundingBox<T> b)
		{
			return RectangleExt.Intersect<BoundingBox<T>, T>(this, b);
		}
		public bool ExpandToInclude(Point<T> point)
		{
			return RectangleExt.ExpandToInclude<BoundingBox<T>, Point<T>, T>(this, point);
		}
		public bool ExpandToInclude(IEnumerable<Point<T>> points)
		{
			return RectangleExt.ExpandToInclude<BoundingBox<T>, Point<T>, T>(this, points);
		}
		public bool Contains(Point<T> point)
		{
			return RectangleExt.Contains<BoundingBox<T>, Point<T>, T>(this, point);
		}
		public bool Contains(BoundingBox<T> other)
		{
			return RectangleExt.Contains<BoundingBox<T>, T>(this, other);
		}
		public bool Overlaps(BoundingBox<T> other)
		{
			return RectangleExt.Overlaps<BoundingBox<T>, T>(this, other);
		}

		public void SetRect(T x, T y, T width, T height)
		{
			SetXAndWidth(x, width);
			SetYAndHeight(y, height);
		}
		public void SetRange(T x1, T y1, T x2, T y2)
		{
			SetXRange(x1, x2);
			SetYRange(y1, y2);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer None
Canada Canada
Since I started programming when I was 11, I wrote the SNES emulator "SNEqr", the FastNav mapping component, the Enhanced C# programming language (in progress), the parser generator LLLPG, and LES, a syntax to help you start building programming languages, DSLs or build systems.

My overall focus is on the Language of your choice (Loyc) initiative, which is about investigating ways to improve interoperability between programming languages and putting more power in the hands of developers. I'm also seeking employment.

Comments and Discussions