不然做TopCoder的时候总是吃亏。
在此,还要感谢Linda指出了多处错误。
using System;
namespace TopCoderLibrary
{
class Geometry
{
// maximum Integer
int maxInt { get { return 2 ^ 31 - 1; } }
// miminum Integer
int minInt { get { return -2 ^ 31; } }
// point (x,y)
class XYpoint
{
public XYpoint() { }
public XYpoint(double _x, double _y) { x = _x; y = _y; }
public double x, y;
}
// line in the format of Ax+By+C=0 defined by a,b, and c
class XYline
{
public XYline() { }
public XYline(double _A, double _B, double _C) { A = _A; B = _B; C = _C; }
public XYline(XYpoint a, XYpoint b) :
this(b.y - a.y, a.x - b.x, a.y*b.x - a.x*b.y) { }
public double A, B, C;
}
// line segment ab
class XYsegment
{
public XYsegment() { }
public XYsegment(XYpoint _a, XYpoint _b) { a = _a; b = _b; }
public XYpoint a, b;
}
// polygon
class XYpolygon
{
public XYpolygon(XYpoint[] _ps) { ps = _ps; }
public XYpoint[] ps;
}
// distance from point a to point b
double distance(XYpoint a, XYpoint b)
{
return Math.Sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
// distance from point a to line l
double distance(XYpoint a, XYline l)
{
return Math.Abs(l.A * a.x + l.B * a.y + l.C) / Math.Sqrt(l.A * l.A + l.B * l.B);
}
// the area of triangle with vetices points a, b, and c
double area(XYpoint a, XYpoint b, XYpoint c)
{
return Math.Abs(0.5 * ((c.y - a.y) * (b.x - a.x) - (b.y - a.y) * (c.x - a.x)));
}
// if Intersect Lines
bool isIL(XYline l1, XYline l2)
{
return l1.A * l2.B != l1.B * l2.A;
}
// if Parallel Lines
bool isPL(XYline l1, XYline l2)
{
return l1.A * l2.B == l1.B * l2.A &&
!(l1.A * l2.C == l1.C * l2.A && l1.B * l2.C == l1.C * l2.B);
}
// if Ovevlapping Lines
bool isOL(XYline l1, XYline l2)
{
return l1.A * l2.B == l1.B * l2.A && l1.A * l2.C == l1.C * l2.A && l1.B * l2.C == l1.C * l2.B;
}
// get Intersect Point
XYpoint getIP(XYline l1, XYline l2)
{
if (l1.A * l2.B == l1.B * l2.A) return new XYpoint();
return new XYpoint(-(l1.C * l2.B - l2.C * l1.B) / (l1.A * l2.B - l2.A * l1.B),
-(l1.C * l2.A - l2.C * l1.A) / (l1.B * l2.A - l2.B * l1.A));
}
// get the Inclination Angle of two lines l1, l2 (in radian value)
double angle_LL(XYline l1, XYline l2)
{
if ((l1.A * l2.A + l1.B * l2.B) == 0) return 1e100;
return Math.Atan(Math.Abs((l1.A * l2.B - l2.A * l1.B) / (l1.A * l2.A + l1.B * l2.B)));
}
// get line l's perpendicular line, which passing through point p
XYline getPL(XYpoint p, XYline l)
{
return new XYline(l.B, -l.A, -l.B * p.x + l.A * p.y);
}
// if segment abc is turning Clock Wise on point b
bool isCW(XYpoint a, XYpoint b, XYpoint c)
{
return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y) > 0);
}
// if segment abc is turning Counter Clock Wise on point b
bool isCCW(XYpoint a, XYpoint b, XYpoint c)
{
return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y) < 0);
}
// if three points a, b, and c are collinear points
bool isCP(XYpoint a, XYpoint b, XYpoint c)
{
return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y) == 0);
}
// if two segments have intersection points
bool isIS(XYsegment u, XYsegment v)
{
return ((Math.Max(u.a.x, u.b.x) >= Math.Min(v.a.x, v.b.x)) &&
(Math.Max(v.a.x, v.b.x) >= Math.Min(u.a.x, u.b.x)) &&
(Math.Max(u.a.y, u.b.y) >= Math.Min(v.a.y, v.b.y)) &&
(Math.Max(v.a.y, v.b.y) >= Math.Min(u.a.y, u.b.y)) &&
(isCP(v.a, u.b, u.a) || isCP(u.b, v.b, u.a) || isCW(v.a, u.b, u.a) == isCW(u.b, v.b, u.a)) &&
(isCP(u.a, v.b, v.a) || isCP(v.b, u.b, v.a) || isCW(u.a, v.b, v.a) == isCW(v.b, u.b, v.a)));
}
// if Point p is On Segment l
bool isPOS(XYsegment l, XYpoint p)
{
return isCP(l.a, l.b, p) && p.x >= Math.Min(l.a.x, l.b.x) && p.x <= Math.Max(l.a.x, l.b.x) &&
p.y >= Math.Min(l.a.y, l.b.y) && p.y <= Math.Max(l.a.y, l.b.y);
}
// if Point p is Inside Polygon p
bool isPIP(XYpoint p, XYpolygon g)
{
XYpoint[] ver = new XYpoint[g.ps.Length + 1];
double mr = g.ps[0].x;
for (int i = 0; i < ver.Length; i++)
{
ver[i] = g.ps[i % g.ps.Length];
mr = Math.Max(mr, ver[i].x);
}
bool ret = false;
XYsegment line = new XYsegment(p, new XYpoint(mr, p.y));
for (int i = 0; i < g.ps.Length; i++)
{
XYsegment edge = new XYsegment(ver[i], ver[i + 1]);
if (isPOS(edge, p))
return true;
if (isIS(line, edge))
ret = !ret;
}
return ret;
}
}
}