using System;
using System.Collections.Generic;
//Author:Domenico Ciavarella
//http://www.studioat.it
namespace Geometry
{
public interface IGeometry
{
int Dimension { get;}
}
public interface IPoint : IGeometry
{
bool IsEmpty();
double X { get; set; }
double Y { get; set; }
void SetEmpty();
double Distance(IPoint pt);
}
public class Point : IPoint, ICloneable
{
double m_x = double.NaN;
double m_y = double.NaN;
public Point(IPoint point)
: this(point.X, point.Y)
{
}
public Point(double x, double y)
{
m_x = x;
m_y = y;
}
public Point()
{ }
#region IPoint Members
public bool IsEmpty()
{
IPoint p = this as IPoint;
return (double.IsNaN(p.X) || double.IsNaN(p.Y));
}
public void SetEmpty()
{
IPoint p = this as IPoint;
p.X = double.NaN;
p.Y = double.NaN;
}
public double X
{
get { return m_x; }
set { m_x = value; }
}
public double Y
{
get { return m_y; }
set { m_y = value; }
}
public double Distance(IPoint pt)
{
IPoint p = this as IPoint;
if ((pt.IsEmpty()) || (p.IsEmpty()))
return double.NaN;
else
return Math.Sqrt(Math.Pow(pt.X - p.X, 2) + Math.Pow(pt.Y - p.Y, 2));
}
public static Point operator +(Point p1, Point p2)
{
return new Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
public static Point operator /(Point p1, double d)
{
return new Point(p1.m_x / d, p1.m_y / d);
}
#endregion
#region ICloneable Members
object ICloneable.Clone()
{
return this.MemberwiseClone();
}
#endregion
public override string ToString()
{
IPoint p = this as IPoint;
if (p.IsEmpty())
return "Point is Null";
else
return string.Format("X: {0} Y:{1}", p.X.ToString(), p.Y.ToString());
}
public override bool Equals(object obj)
{
bool bResult = false;
IPoint pt = obj as IPoint;
if (pt != null)
{
IPoint ptClass = this as IPoint;
if ((ptClass.IsEmpty()) && (pt.IsEmpty())) return true;
if ((!ptClass.IsEmpty()) || (pt.IsEmpty())) return false;
if ((ptClass.IsEmpty()) || (!pt.IsEmpty())) return false;
return ((pt.X == ptClass.X) && (pt.Y == ptClass.Y));
}
return bResult;
}
public override int GetHashCode()
{
IPoint pt = this as IPoint;
if (pt.IsEmpty()) return -1;
return (int)(Math.Pow(pt.X, 2) + Math.Pow(pt.Y, 2));
}
public static explicit operator Point(Envelope envelope)
{
return (envelope as IArea).Centroid as Point;
}
#region IGeometry Members
int IGeometry.Dimension
{
get { return 0; }
}
#endregion
}
public interface IArea
{
double Area { get;}
IPoint Centroid { get;}
}
public interface IEnvelope : IGeometry
{
double Height { get; }
double Width { get; }
Point Origin { get;}
Point Size { get;}
}
public interface ICircle : IGeometry
{
double Radious { get;set; }
IPoint Center { get;set;}
}
public class Envelope : IArea, IEnvelope
{
private Point m_size;
private Point m_origin;
public Envelope(Point origin, Point size)
{
m_origin = origin;
m_size = size;
}
public Point Origin
{
get { return m_origin; }
}
public Point Size
{
get { return m_size; }
}
public double Height
{
get { return Size.Y; }
}
public double Width
{
get { return Size.X; }
}
#region IArea Members
public double Area
{
get { return Height * Width; }
}
public IPoint Centroid
{
get
{
return Origin + (Size / 2.0);
}
}
#endregion
#region IGeometry Members
public int Dimension
{
get { return 2; }
}
#endregion
}
public class Circle : IArea, ICircle
{
double m_radious = double.NaN;
IPoint m_center = null;
public Circle(double radious, IPoint center)
{
Center = center;
Radious = radious;
}
#region ICircle Members
public double Radious
{
get { return m_radious; }
set { m_radious = value; }
}
public IPoint Center
{
get { return m_center; }
set { m_center = value; }
}
#endregion
#region IGeometry Members
public int Dimension
{
get { return 2; }
}
#endregion
#region IArea Members
public double Area
{
get { return Math.Pow(Radious,2) * Math.PI; }
}
public IPoint Centroid
{
get { return Center; }
}
#endregion
}
public delegate R Operation<T, R>(T geo1, T geo2)
where R : struct
where T : IArea;
public class GeometryBag<T>where T:IArea
{
private List<T> geometries = new List<T>();
public void AddGeometry(T geometry)
{
geometries.Add(geometry);
}
public double Area
{
get
{
double totalArea = 0;
foreach (T geometry in geometries)
{
totalArea += geometry.Area;
}
return totalArea;
}
}
public static double Sum(T geometry1,T geometry2)
{
return geometry1.Area + geometry2.Area;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Geometry;
//Author:Domenico Ciavarella
//http://www.studioat.it
namespace Generics
{
class Program
{
static void Main(string[] args)
{
IPoint pPoint = new Point(10d, 2d);
IPoint pPoint2 = new Point(pPoint);
Console.WriteLine("Point2 x:{0} y:{1}", pPoint2.X.ToString(), pPoint2.Y.ToString());
IPoint pPoint3 = new Point();
Console.WriteLine("Point3 is null: {0}", pPoint3.IsEmpty().ToString());
ICloneable pPoint4 = pPoint2 as ICloneable;
IPoint pPoint5 = pPoint4.Clone() as IPoint;
Console.WriteLine("Point5 x:{0} y:{1} HashCode Point5:{2}", pPoint5.X.ToString(), pPoint5.Y.ToString(), pPoint5.GetHashCode());
IPoint pPoint6 = new Point();
Console.WriteLine("Point6 is equal Point3: {0} HashCode Point6:{1} HashCode Point3:{2}", pPoint6.Equals(pPoint3), pPoint6.GetHashCode(), pPoint3.GetHashCode());
Envelope pEnvelope = new Envelope(new Point(2d, 2d), new Point(5d, 6d));
Point pPoint7 = (Point)pEnvelope;
Console.WriteLine("Point7 x:{0} y:{1}", pPoint7.X.ToString(), pPoint7.Y.ToString());
GeometryBag<IArea> pGeometryBag = new GeometryBag<IArea>();
pGeometryBag.AddGeometry(new Circle(10.0, pPoint7 as IPoint));
pGeometryBag.AddGeometry(pEnvelope);
Console.WriteLine("Total area: {0}", pGeometryBag.Area);
Operation<IArea, double> op = new Operation<IArea, double>(GeometryBag<IArea>.Sum);
Console.WriteLine("Total area: {0}", op(new Circle(10.0, pPoint7 as IPoint), pEnvelope));
Console.ReadLine();
}
}
}
Qui puoi scaricare la soluzione in VS2008 Generics