#region Written by Tamas Budavari (budavari@jhu.edu)
/**
 * SphericalLib.Region
 * 
 * SphericalLib is a .NET library to deal with geometry on the unit sphere.
 * It is intented to be used for complex survey footprint descriptions in
 * standalone applications as well as in web services and perhaps Yukon.
 * 
 * Written by Tamas Budavari (budavari@jhu.edu)
 * See bottom of file for revision history
 * 
 * Current revision:
 *   ID:          $Id: Region.cs,v 1.1.1.1 2006/11/14 02:56:39 gupchup Exp $
 *   Revision:    $Revision: 1.1.1.1 $
 *   Date:        $Date: 2006/11/14 02:56:39 $
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
using System.Text;
#endregion

namespace Spherical
{
    /// <summary>
	/// Region is the union of convexes
	/// </summary>
    [Serializable, XmlRoot(Namespace = Const.NameSpace)]
    [CLSCompliant(true)]
	public class Region
    {
        #region Private members and keyword definitions

        private string name;
        private List<Convex> convexList;

        private static readonly string keyword = "REGION";
        public static string Keyword { get { return keyword; } }

        #endregion
        #region Public properties

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        [XmlIgnore]
        public ReadOnlyCollection<Convex> ConvexList
        {
            get { return convexList.AsReadOnly(); }
        }

        [XmlArray("ConvexList")]
        public List<Convex> x___DoNotEverTouchMe___
        {
            get { return convexList; }
            set
            {
                throw new ApplicationException
                  ("x__DoNotEverTouchMe__ should not be touched");
            }
        }

        public double? Area
        {
            get
            {
                double? a = 0; 
                foreach (Convex c in convexList)
                    a += c.Area;
                return a;
            }
            set 
            {
                throw new ApplicationException
                    ("Region.Area cannot be set");
            }
        }

        #endregion
		#region Constructors of various kinds

		/// <summary>
		/// Create empty region
		/// </summary>
		public Region() 
		{
			convexList = new List<Convex>();
		}

        /// <summary>
        /// Create empty region of given capacity
        /// </summary>
        /// <param name="capacity"></param>
        public Region(int capacity)
        {
            convexList = new List<Convex>(capacity);
        }

        /// <summary>
        /// Create empty region of given name
        /// </summary>
        /// <param name="name"></param>
        public Region(string name)
        {
            convexList = new List<Convex>();
            this.name = name;
        }

        /// <summary>
        /// Create empty region of given name and capacity
        /// </summary>
        /// <param name="name"></param>
        /// <param name="capacity"></param>
        public Region(string name, int capacity)
        {
            convexList = new List<Convex>(capacity);
            this.name = name;
        }

        /// <summary>
		/// Create region with a single convex in it
		/// </summary>
		/// <param name="convex"></param>
		public Region(Convex convex, bool clone)
		{
            convexList = new List<Convex>(1);
            Convex c;
            if (clone)
                c = new Convex(convex);
            else
                c = convex;
			convexList.Add(c);
		}

		/// <summary>
		/// Copy constructor (clone region)
		/// </summary>
		/// <param name="region"></param>
		public Region(Region region)
		{
            convexList = region.convexList.ConvertAll<Convex>(Convex.Clone);
            name = region.name;
		}

		/// <summary>
		/// Create region with a single halfspace in it
		/// </summary>
		/// <param name="halfspace"></param>
		public Region(Halfspace halfspace)
		{
            convexList = new List<Convex>(1);
            convexList.Add(new Convex(halfspace));
		}

		/// <summary>
		/// Create region with a single halfspace
		/// </summary>
		/// <param name="ra"></param>
		/// <param name="dec"></param>
		/// <param name="arcmin"></param>
		public Region(double ra, double dec, double arcmin)
		{
            convexList = new List<Convex>(1);
            Convex c = new Convex(new Halfspace(ra, dec, arcmin));
			convexList.Add(c);
		}

        #endregion
        #region ConvexList management

        public void Add(Convex c)
        {
            convexList.Add(c);
        }

        public void AddRange(IEnumerable<Convex> collection)
        {
            convexList.AddRange(collection);
        }

        public void AddRange(List<Convex> collection)
        {
            int count = this.convexList.Count + collection.Count;
            if (this.convexList.Capacity < count)
                this.convexList.Capacity = count;
            convexList.AddRange(collection);
        }

        public void RemoveAt(int index)
        {
            this.convexList.RemoveAt(index);
        }

        public void Remove(Convex item)
        {
            this.convexList.Remove(item);
        }

        public void RemoveRange(int index, int count)
        {
            this.convexList.RemoveRange(index, count);
        }

        public void Clear()
        {
            this.convexList.Clear();
        }

        public bool Exists(Predicate<Convex> match)
        {
            return convexList.Exists(match);
        }

        public void Sort(Comparison<Convex> comparison)
        {
            convexList.Sort(comparison);
        }

		#endregion
		#region Morphological operations and geometric relations to others

        /// <summary>
        /// Increase angles of all halfspaces in all convexes by the given amount
        /// </summary>
        /// <param name="arcmin"></param>
        public void Grow(double arcmin)
        {
            foreach (Convex c in convexList)
                c.Grow(arcmin);
        }

        /// <summary>
        /// Chech if point (x,y,z) is inside within given tolerance
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public bool Covers(double x, double y, double z, double tolerance)
        {
            foreach (Convex c in this.convexList)
                if (c.Covers(x, y, z, tolerance))
                    return true;
            return false;
        }

        /// <summary>
        /// Check if region covers a point
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public bool Covers(Cartesian p, double tolerance)
        {
            return Covers(p.X, p.Y, p.Z, tolerance);
        }		
 

        #endregion
        #region Boolean operations

        /// <summary>
        /// Intersect this region with a halfspace in place.
        /// </summary>
        /// <param name="h"></param>
        public void Intersect(Halfspace h)
        {
            foreach (Convex c in this.convexList)
            {
                c.Add(h);
            }
        }

        /// <summary>
        /// Intersect this region with the given convex in place.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="clone"></param>
        public void Intersect(Convex c)
        {
            foreach (Convex k in this.convexList)
            {
                k.AddRange(c.HalfspaceList);
            }
        }

        /// <summary>
        /// Return intersection of this region with another: X=I&R (in I and R)
        /// It leaves both this and the given region in place because uses cloned
        /// halfspaces from them.
        /// </summary>
        /// <param name="region"></param>
        /// <returns></returns>
        public Region Intersect(Region R)
        {
            return this.Intersect(R, -1);
        }

        /// <summary>
        /// Return intersection of this region with another: X=I&R (in I and R)
        /// It leaves both this and the given region in place because uses cloned
        /// halfspaces from them.
        /// </summary>
        /// <param name="region"></param>
        /// <returns></returns>
        public Region Intersect(Region R, double tolerance)
        {
            Region isct = new Region(this.convexList.Count * R.convexList.Count);
            // double loop on convexes to consider all pairs
            foreach (Convex c in this.convexList)
            {
                foreach (Convex k in R.convexList)
                {
                    Convex tmp = new Convex(c.HalfspaceList.Count + k.HalfspaceList.Count);
                    tmp.AddRange(c.HalfspaceList);
                    tmp.AddRange(k.HalfspaceList);
                    if (tolerance < 0 || tmp.SimpleSimplify(tolerance))
                        isct.convexList.Add(tmp);
                }
            }
            return isct;
        }

        /// <summary>
        /// Union of this region with a given convex, in place.
        /// The method simply adds a clone of the convex to the list.
        /// </summary>
        /// <param name="convex"></param>
        public void Union(Convex convex)
        {
            this.convexList.Add(new Convex(convex));
        }

        /// <summary>
        /// Union of this region and another one, in place.
        /// The method adds clones of the other's convexes.
        /// </summary>
        /// <param name="region"></param>
        /// <returns></returns>
        public void Union(Region region)
        {
            List<Convex> cl = region.convexList.ConvertAll<Convex>(Convex.Clone);
            this.convexList.AddRange(cl);
        }

        /// <summary>
        /// Difference of this region and a given halfspace 'h'.
        /// Same as intersecting with 'h' inverse. This is an
        /// in place operation but safe for the halfspace.
        /// </summary>
        /// <param name="h"></param>
        public void Difference(Halfspace h)
        {
            this.Intersect(h.Inverse());
        }

        /// <summary>
        /// Difference of this region and a convex C: X = I\C (in I but not in C)
        /// Algorithm: X = (I&~h1)|(I&h1&~h2)|(I&h1&h2&~h3)|... , where C=h1&h2&...
        /// </summary>
        /// <param name="region"></param>
        /// <returns></returns>
        public Region Difference(Convex C)
        {
            Region diff = new Region();
            // loop on halfspaces of convex 'C'
            for (int i = 0; i < C.HalfspaceList.Count; i++)
            {
                Region tmp = new Region(this); // clone me
                for (int j = 0; j < i; j++)
                {
                    tmp.Intersect(C.HalfspaceList[j]);
                }
                tmp.Intersect(C.HalfspaceList[i].Inverse());
                // diff = diff | tmp
                diff.Union(tmp);
            }
            return diff;
        }

        #endregion
        #region Simplification (simple and full)

        /// <summary>
		/// SimpleSimplify all convexes, remove empty ones and merge
        /// convexes if same halfspaces except one that is inverse
    	/// </summary>
		/// <returns></returns>
		public void SimpleSimplify(double tolerance)
		{
            // convex simplify
			List<Convex> delete = new List<Convex>();
			foreach (Convex c in convexList)
			{
				bool still = c.SimpleSimplify(tolerance);
                if (!still && !delete.Contains(c))
                    delete.Add(c);
			}
            
            // remove empty convexes
			foreach (Convex x in delete)
				convexList.Remove(x);

#if false
            // find mergable convexes
            List<int> jDelete = new List<int>();
            List<int> iList = new List<int>(); // convex i
            List<int> jList = new List<int>(); // convex j
            List<int> uList = new List<int>(); // unmatched halfspace of convex i
            for (int i = 0; i < convexList.Count - 1; i++)
            {
                if (jDelete.Contains(i)) continue;

                for (int j = i + 1; j < convexList.Count; j++)
                {
                    if (jDelete.Contains(j))  continue;

                    // if same (i,j) lengths 
                    if (convexList[i].halfspaceList.Count == convexList[j].halfspaceList.Count)
                    {
                        int unmatched = -1; // means not set yet. -2 means multiple ones
                        for (int k = 0; k < convexList[i].halfspaceList.Count; k++)
                        {
                            Halfspace h = convexList[i].halfspaceList[k];
                            bool found = false;
                            for (int l = 0; l < convexList[j].halfspaceList.Count; l++)
                            {
                                Halfspace g = convexList[j].halfspaceList[l];
                                if (h.Same(g, Const.Tolerance))
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                if (unmatched == -1)
                                {
                                    unmatched = k;
                                }
                                else
                                {
                                    unmatched = -2;
                                    break;
                                }
                            }
                        }

                        // if more than 1 unmatched -> (i,j) rejected
                        if (unmatched == -2)
                        {
                            // do nothing
                        }
                        // if convexes are the same -> mark 'j' for deletion
                        if (unmatched == -1)
                        {
                            if (jList.Contains(j))
                                throw new ApplicationException("need more work here");

                            jDelete.Add(j);
                        }
                        else
                        {
                            // check if inverse is in the other list
                            Halfspace inv = convexList[i].halfspaceList[unmatched].Inverse();
                            bool ifound = false;
                            foreach (Halfspace g in convexList[j].halfspaceList)
                            {
                                if (inv.Same(g, Const.Tolerance))
                                {
                                    ifound = true;
                                    break;
                                }
                            }
                            if (ifound) // 'i,j' to be merged by eliminating 'u'
                            {
                                if (iList.Contains(i))
                                    throw new ApplicationException("need more work here");

                                iList.Add(i); uList.Add(unmatched);
                                jList.Add(j);
                            }
                        }
                    }
                }
            }
            // remove identical convexes
            for (int p = jDelete.Count - 1; p >= 0; p--)
                convexList.RemoveAt(jDelete[p]);
            
            // merge them by removing inverted halfspace and second convex
            for (int p = 0; p < iList.Count; p++)
                convexList[iList[p]].halfspaceList.RemoveAt(uList[p]);
            for (int p = jList.Count - 1; p >= 0; p--)
                convexList.RemoveAt(jList[p]);
#endif
		}

        /// <summary>
        /// Full simplification of region - creates patches
        /// </summary>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public void Simplify(bool simple_simplify, double tolerance, int iteration, bool make_disjoint)
        {
            // simplesimplify convexes, remove empty and duplicate convexes and merge if possible
            if (simple_simplify)
                this.SimpleSimplify(tolerance);

            // full simplifcation of convexes - remove if empty
            List<int> iDelete = new List<int>();
            for (int i=0; i<this.convexList.Count; i++)
            {
                Convex c = this.convexList[i];
                if (c.Simplify(false,tolerance,iteration) == false)
                    iDelete.Add(i);
            }
            for (int p = iDelete.Count-1; p >= 0; p--)
                this.convexList.RemoveAt(iDelete[p]);

            // make convexes disjoint if requested
            if (make_disjoint)
                this.MakeDisjoint(tolerance, iteration);

        }

        /// <summary>
        /// Full simplifcation of region - creates patches
        /// </summary>
        public void Simplify()
        {
            this.Simplify(true, Const.Tolerance, Const.MaximumIteration, true);
        }

        /// <summary>
        /// Full simplification of region - creates patches
        /// </summary>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public void Simplify(double tolerance)
        {
            this.Simplify(true, tolerance, Const.MaximumIteration, true);
        }

        /// <summary>
        /// Full simplification of region - creates patches
        /// </summary>
        /// <param name="tolerance"></param>
        /// <param name="make_disjoint"></param>
        public void Simplify(double tolerance, bool make_disjoint)
        {
            this.Simplify(true, tolerance, Const.MaximumIteration, make_disjoint);
        }

        /// <summary>
        /// Full simplification of region - creates patches
        /// </summary>
        /// <param name="make_disjoint"></param>
        public void Simplify(bool make_disjoint)
        {
            this.Simplify(true, Const.Tolerance, Const.MaximumIteration, make_disjoint);
        }

        /// <summary>
        /// Make sure the region has disjoint convexes
        /// </summary>
        private void MakeDisjoint(double tolerance, int iteration)
        {
            // find colliding convexes
            List<int> i1 = new List<int>();
            List<int> i2 = new List<int>();
            bool done = false;
            while (!done)
            {
                done = this.TwoDisjoint (tolerance, iteration, 
                    i1, i2);
            }
        }

        /// <summary>
        /// Picks 2 colliding convexes c1 and c2, and replace them 
        /// with disjoint combinations: c1, c2-c1
        /// </summary>
        /// <returns></returns>
        private bool TwoDisjoint(double tolerance, int iteration , List<int> i1, List<int> i2)
        {
            if (i1.Count != i2.Count) 
                throw new ArgumentException
                    ("Region.TwoDisjoint(): i1 and i2 lists are different length");

            // sort convexes by area descending
            convexList.Sort(Convex.ComparisonAreaDescending);

            i1.Clear();
            i2.Clear();

            // find colliding pairs if called for the first time
            if (i1.Count == 0)
            {
                for (int i = 0; i < convexList.Count - 1; i++)
                {
                    for (int j = i + 1; j < convexList.Count; j++)
                    {
                        Convex tmp = new Convex(convexList[i]);
                        if (tmp.SmartIntersect(convexList[j], tolerance, iteration))
                        {
                            i1.Add(i);
                            i2.Add(j);
                        }
                    }
                }
            }
            
            // done if no collisions
            if (i1.Count == 0)
                return true;

            // take first 2 and create disjoint convexes 
            Convex c1 = convexList[i1[0]];
            Convex c2 = convexList[i2[0]];

            Region diff = c2.Difference(c1);
            diff.Simplify(true, tolerance, iteration, false);

            // remove old convex
            convexList.RemoveAt(i2[0]);

            // add all new convexes
            this.convexList.AddRange(diff.convexList);
            //this.SimpleSimplify(tolerance);

            return false;
        }

        #endregion
        #region Smart methods exploiting patches

        /// <summary>
        /// (Re)calculate the area using a given pivot/center point
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public double CalcArea(Cartesian c)
        {
            double area = 0;
            foreach (Convex k in this.convexList)
                area += k.CalcArea(c);
            return area;
        }

        /// <summary>
        /// Check if the minimal enclosing circles of the patches
        /// contain the given point (within the given tolerance)
        /// </summary>
        /// <param name="x"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public bool MecCovers(Cartesian x, double tolerance)
        {
            foreach (Convex s in this.convexList)
                foreach (Patch p in s.PatchList)
                    if (p.Mec.Covers(x, tolerance))
                        return true;
            return false;
        }

        /// <summary>
        /// Return the number of all patches
        /// </summary>
        /// <returns></returns>
        public int NumberOfPatches()
        {
            int n = 0;
            foreach (Convex s in this.convexList)
                n += s.PatchList.Count;
            return n;
        }

        /// <summary>
        /// Check if the given point is covered but first test the minimal
        /// enclosing circles of the patches. Uses the given tolerance.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public bool SmartCovers(Cartesian x, double tolerance)
        {
            foreach (Convex s in this.convexList)
                if (s.SmartCovers(x, tolerance))
                    return true;
            return false;
        }

        /// <summary>
        /// Compute intersection
        /// </summary>
        /// <param name="convex"></param>
        public void SmartIntersect(Convex convex, double tolerance, int iteration)
        {
            Region isct = new Region();
            List<Convex> delete = new List<Convex>();
            foreach (Convex c in this.convexList)
            {
                if (!c.SmartIntersect(convex, tolerance, iteration))
                    delete.Add(c);
            }
            foreach (Convex d in delete)
                this.Remove(d);
        }

        /// <summary>
        /// Compute intersection
        /// </summary>
        /// <param name="R"></param>
        public Region SmartIntersect(Region R, double tolerance, int iteration)
        {
            Region isct = new Region();
            // double loop on convexes to consider all pairs
            foreach (Convex c in this.convexList)
            {
                foreach (Convex k in R.convexList)
                {
                    Convex tmp = new Convex(c);
                    if (tmp.SmartIntersect(k,tolerance,iteration))
                        isct.convexList.Add(tmp);
                }
            }
            return isct;
        }

        #endregion
        #region Parse(), ToString(), Revision

        /// <summary>
		/// Parse string "REGION {CONVEX ...}" into a region.
		/// </summary>
		/// <param name="repr"></param>
		/// <returns></returns>
		public static Region Parse(string repr, bool normalize)
		{
			// separators
			char[] spc = new char[] { ' ' };
			char[] cma = new char[] { ',' };

			// only spaces (hopefully)
			string proc = repr.Trim().Replace(',',' ').Replace("\r\n"," ").Replace('\n',' ').Replace('\t',' ');
			
			// replace duplicate spaces with a single one
			string trim = "";
			while (trim != proc) 
			{
				trim = proc;
				proc = trim.Replace("  "," ");
			}

			// get values
			string[] tok = trim.Split(spc,2);
			if (tok[0] != Region.keyword)
				throw new ArgumentException("Region.Parse(): wrong keyword");
			string comma = tok[1].Replace(Convex.Keyword,","+Convex.Keyword);
			tok = comma.Split(cma);
			
			// read all convexes
			Region r = new Region();
			for (int i=1; i<tok.Length; i++)
				r.convexList.Add(Convex.Parse(tok[i],normalize));
			return r;
		}

		/// <summary>
		/// String representation: "REGION CONVEX... CONVEX..."
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			string r = Region.keyword;
            foreach (Convex c in this.convexList)
                r += String.Format(" {0}", c);
			return r;
		}

        /// <summary>
        /// String represntation for George...
        /// </summary>
        /// <returns></returns>
		public String Format() {
			StringBuilder sb = new StringBuilder();
			sb.Append("REGION ");
			foreach (Convex c in this.convexList) {
				sb.AppendFormat("CONVEX CARTESIAN ");
				foreach (Halfspace h in c.HalfspaceList) {
					sb.AppendFormat("{0,20:0.000000000000000} {1,20:0.000000000000000} {2,20:0.000000000000000} {3,20:0.000000000000000} ",
						h.Vector.X, h.Vector.Y, h.Vector.Z, h.Cos0);
				}
			}
			return sb.ToString();
		}


		/// <summary>
		/// Revision from CVS
		/// </summary>
		public static string Revision
		{
			get	{ return "$Revision: 1.1.1.1 $"; }
		}

		#endregion
	}
}

#region Revision History
/* Revision History

        $Log: Region.cs,v $
        Revision 1.1.1.1  2006/11/14 02:56:39  gupchup
        no message

        Revision 1.15  2006/04/24 15:19:30  budavari
        String representations w/o newline

        Revision 1.14  2006/04/24 14:39:30  budavari
        SmartIntersect with Convex

        Revision 1.13  2006/04/19 16:51:01  budavari
        EVerything is now CLS compliant

        Revision 1.12  2006/03/20 16:26:13  budavari
        Get rid of infinitesimal convex, e.g. CONVEX 1 0 0 1

        Revision 1.11  2006/03/11 14:10:48  budavari
        Using AddRange instead of Add

        Revision 1.10  2006/03/08 20:54:03  budavari
        Added sort method, e.g. by area

        Revision 1.9  2006/03/08 19:49:08  gyuri
        Attributes of static fields in safe assemblies must be marked  readonly in Visual C#

        Revision 1.8  2006/03/08 15:10:00  gyuri
        Added Format() for more specific formatted string than ToString()

        Revision 1.7  2006/03/07 21:19:47  budavari
        Fixed bug relevant for making convexes disjoint

        Revision 1.6  2006/02/28 16:26:12  budavari
        Major revision: smart objects w/ properties

        Revision 1.5  2006/02/16 16:54:24  budavari
        Region-simplify is take out for now

        Revision 1.4  2006/02/14 16:24:53  budavari
        Regin simplify issues being worked on

        Revision 1.3  2006/02/03 21:05:47  budavari
        Added Simplify() that returns SuperRegion

        Revision 1.2  2006/01/25 19:06:50  budavari
        No automatic naming in operators

        Revision 1.1  2006/01/24 15:56:05  budavari
        Re-structured directory layout to accommodate more projects

        Revision 1.21  2006/01/19 19:43:12  budavari
        Region.SimpleSimplify() merges convexes

        Revision 1.20  2005/12/20 02:18:13  budavari
        Union() added, Parse() takes bool normalize

        Revision 1.19  2005/12/14 22:39:06  budavari
        Intersect calls SimpleSimplify()

        Revision 1.18  2005/12/05 21:43:55  budavari
        Working Outline implementation :-) Hurray! Except for the fly in the soup:
        I did find an example, Samples.Saw3(), which makes the code throw up as
        it turns the outline into a bowtie. Coming up next...

        Revision 1.17  2005/12/04 16:50:55  budavari
        Small features and fixes. Also added Outline class - not function, yet

        Revision 1.16  2005/12/02 21:32:30  budavari
        member variables do start with small letter ;-) XML still the same

        Revision 1.15  2005/12/01 22:34:57  budavari
        Area struct added and fully functional

        Revision 1.14  2005/11/30 20:50:28  budavari
        Cosmetics... #region specifications etc added

        Revision 1.13  2005/11/30 20:01:53  budavari
        Dilate() renamed to Gro() per Alex's request

        Revision 1.12  2005/11/30 19:50:37  budavari
        Dilate() methods added. Also explicit tolerance required everywhere for clarity

        Revision 1.11  2005/11/30 15:31:58  budavari
        Header changes

        Revision 1.10  2005/11/21 14:26:28  budavari
        Fixed smaller bugs after adding NUnit tests

        Revision 1.9  2005/11/18 22:51:40  budavari
        Boolean operations are done for now: Intersect(), Union() and Difference()

        Revision 1.8  2005/11/18 05:58:09  budavari
        Working on boolean operations on regions...

        Revision 1.7  2005/11/17 01:58:54  budavari
        Done with the convex stuff... Hurray!!! It can even deal with the "orange
        slices" to some extent: the problem is the area - coming up next...

        Revision 1.6  2005/11/15 22:20:20  budavari
        Using Generics - almost there

        Revision 1.5  2005/11/15 15:25:36  budavari
        Everything is a class, things are coming together for area computation, etc. Will moved to C# 2.0

        Revision 1.4  2005/11/05 17:47:44  budavari
        Fixed a bug in Convex caused by renaming things and did some tidying up...

        Revision 1.3  2005/11/04 22:49:36  budavari
        Re-write to have Point and Halfspace as struct again and other tinkerings. XML is still fine...

        Revision 1.2  2005/11/03 15:22:01  budavari
        Fairly major revision to make sure the objects serialize to XML nicely:
          - Added separate containers of halfspaces and convexes
          - Customized XML output for compactness and friendly proxy interface
          - Implemented simple .Parse() methods taking cartesion representation

        Revision 1.1.1.1  2005/10/28 14:13:43  budavari
        Initial import of the SphericalLib library. It is pretty complete in terms
        of the classes but lacking the simplication and other advanced methods.

*/
#endregion