/// The method steps to the next index in a circular list 0, 1 ..., n.
///
/// Index to increase.
/// Largest index
///
/// The increased index.
///
private static int Increase(int i, int n)
{
i++;
if (i>n)
{
i = 0;
}
return i;
}
///
/// The method steps to the previous index in a circular list 0, 1 ..., n.
///
/// Index to decrease.
/// Largest index
///
/// The decreased index.
///
private static int Decrease(int i, int n)
{
i--;
if (i < 0)
{
i = n;
}
return i;
}
///
/// Checks if the lines lineA and lineB shares a point either as a real
/// crossing point or as a shared end point or a end point of the one
/// line being in the other line.
///
/// Line.
/// Line.
/// Point.
///
/// True if lineA and lineB has shared point. False otherwise
/// The shared point if any is returned in the intersectionPoint
/// parameter that is called by reference
///
protected static bool IntersectionPoint(XYLine Linea, XYLine Lineb, ref XYPoint intersectionPoint)
{
if( DoLineSegmentsIntersect(Linea, Lineb))
{
intersectionPoint = CalculateIntersectionPoint(Linea, Lineb);
return true;
}
if( IsPointInLine(Linea.P2, Lineb))
{
intersectionPoint = Linea.P2;
return true;
}
if( IsPointInLine(Lineb.P2, Linea))
{
intersectionPoint = Lineb.P2;
return true;
}
if( IsPointInLine(Lineb.P1, Linea))
{
intersectionPoint = Lineb.P1;
return true;
}
if( IsPointInLine(Linea.P1, Lineb))
{
intersectionPoint = Linea.P1;
return true;
}
return false;
}
///
/// Determines if a point is included in a line either in the interior
/// or as one of the end points.
///
/// x-coordinate
/// y-coordinate
/// Line.
///
/// Determines if a point is included in a line.
///
protected static bool IsPointInLine(double x, double y, XYLine line)
{
bool result = false;
if( line.P1.X-line.P2.X != 0 )
{
if ((x >= Math.Min(line.P1.X, line.P2.X)) && (x <= Math.Max(line.P1.X, line.P2.X)))
{
if( Math.Abs(y-line.P1.Y-(line.P2.Y-line.P1.Y)/(line.P1.X-line.P2.X)*(line.P1.X-x)) < EPSILON*EPSILON)
{
result = true;
}
}
}
else
{
if (line.P1.X == x)
{
if ( (y >= Math.Min(line.P1.Y, line.P2.Y)) && (y <= Math.Max(line.P1.Y, line.P2.Y)) )
{
result = true;
}
}
}
return result;
}
///
/// Determines if a point is included in a line either in the interior
/// or as one of the end points.
/// Overload to: IsPointInLine(double x, double y, XYLine line)
///
///
/// Point
/// Line.
///
///
/// Determines if a point is included in a line.
///
protected static bool IsPointInLine(XYPoint point, XYLine line)
{
return IsPointInLine( point.X, point.Y, line);
}
///
/// Determines if a point is included in a lines interior. I.e. included
/// in the line and not an endpoint.
///
/// x-coordinate
/// y-coordinate
/// Line.
///
/// Determines if a point is included in a line.
///
protected static bool IsPointInLineInterior(double x, double y, XYLine line)
{
bool result = false;
if( line.P1.X-line.P2.X != 0 ) //line is not vertical
{
if ((x > Math.Min(line.P1.X, line.P2.X)) && (x < Math.Max(line.P1.X, line.P2.X)))
{
if( Math.Abs(y-line.P1.Y-(line.P2.Y-line.P1.Y)/(line.P1.X-line.P2.X)*(line.P1.X-x)) < EPSILON*EPSILON)
{
result = true;
}
}
}
else //line is vertical
{
if (line.P1.X == x)
{
if ( (y > Math.Min(line.P1.Y, line.P2.Y)) && (y < Math.Max(line.P1.Y, line.P2.Y)) )
{
result = true;
}
}
}
return result;
}
///
/// Determines if a point is included in a lines interior. I.e. included
/// in the line and not an endpoint.
/// Overload to:IsPointInLineInterior(double x, double y, XYLine line)
///
/// Point.
/// Line.
///
/// Determines if a point is included in a line.
///
protected static bool IsPointInLineInterior(XYPoint point, XYLine line)
{
return IsPointInLineInterior( point.X, point.Y, line);
}
///
/// Calculates the distance from a polyline to a point in the plane.
/// The algorithm decides weather the point lies besides the line
/// segment in which case the distance is the length along a line
/// perpendicular to the line. Alternatively the distance is the
/// smallest of the distances to either endpoint.
///
/// Line
/// Point
///
/// Length of the shortest path between the line and the point.
///
protected static double CalculateLineToPointDistance (XYLine line, XYPoint point)
{
double dist = 0;
double a = Math.Sqrt((line.P2.X-point.X)*(line.P2.X-point.X) + (line.P2.Y-point.Y)*(line.P2.Y-point.Y));
double b = Math.Sqrt((line.P2.X-line.P1.X)*(line.P2.X-line.P1.X)+(line.P2.Y-line.P1.Y)*(line.P2.Y-line.P1.Y));
double c = Math.Sqrt((line.P1.X-point.X)*(line.P1.X-point.X)+(line.P1.Y-point.Y)*(line.P1.Y-point.Y));
if ((a == 0) || (c == 0))
{
dist = 0;
}
else if (b == 0)
{
dist = a;
}
else
{
double alpha = Math.Acos((b*b+c*c-a*a)/(2*b*c));
double beta = Math.Acos((a*a+b*b-c*c)/(2*a*b));
if (Math.Max(alpha,beta)
/// Finds the shortest distance between any line segment of the polyline
/// and the point.
///
/// PolyLine.
/// Point
///
/// Length of the shortest path between the polyline and the point.
///
public static double CalculatePolylineToPointDistance (XYPolyline polyLine, XYPoint point)
{
double dist = 0;
int i = 0;
while (i < polyLine.Points.Count - 1)
{
if (i == 0)
{
dist = CalculateLineToPointDistance (polyLine.GetLine(0), point);
}
else
{
dist = Math.Min(dist, CalculateLineToPointDistance (polyLine.GetLine(i), point));
}
i++;
}
return dist;
}
///
/// Determines if a point in inside or outside a polygon.
/// Works for both convex and concave polygons (Winding number test)
///
/// Point
/// Polygon
///
/// true: If the point is inside the polygon
/// false: Otherwise.
///
public static bool IsPointInPolygon(XYPoint point, XYPolygon polygon)
{
return IsPointInPolygon(point.X, point.Y, polygon);
}
///
/// Determines if a point in inside or outside a polygon.
/// Works for both convex and concave polygons (Winding number test)
///
/// x-coordinate for the point
/// y-coordiante for the point
/// Polygon
///
/// true: If the point is inside the polygon
/// false: If the point is outside the polygon.
///
public static bool IsPointInPolygon(double x, double y, XYPolygon polygon)
{
double x1,x2,y1,y2;
double xinters;
bool isInside = false;
int n = polygon.Points.Count;
for (int i = 0; i < n; i++)
{
if (i < n - 1)
{
x1 = ((XYPoint)polygon.Points[i]).X;
x2 = ((XYPoint)polygon.Points[i+1]).X;
y1 = ((XYPoint)polygon.Points[i]).Y;
y2 = ((XYPoint)polygon.Points[i+1]).Y;
}
else
{
x1 = ((XYPoint)polygon.Points[n-1]).X;
x2 = ((XYPoint)polygon.Points[0]).X;
y1 = ((XYPoint)polygon.Points[n-1]).Y;
y2 = ((XYPoint)polygon.Points[0]).Y;
}
if (y > Math.Min(y1,y2))
{
if (y <= Math.Max(y1,y2))
{
if ( x <= Math.Max(x1,x2))
{
if (y1 != y2)
{
xinters = (y - y1)*(x2 - x1)/(y2 - y1) + x1;
if (x1 == x2 || x <= xinters)
{
isInside = !isInside;
}
}
}
}
}
}
return isInside;
}
///
/// Determines if a point in inside or outside a polygon. Inside
/// includes on the edge for this method.
/// Works for both convex and concave polygons (Winding number test)
///
/// x-coordinate for the point
/// y-coordiante for the point
/// Polygon
///
/// true: If the point is inside the polygon
/// false: If the point is outside the polygon.
///
protected static bool IsPointInPolygonOrOnEdge(double x, double y, XYPolygon polygon)
{
bool result = IsPointInPolygon(x, y, polygon);
if( result )
{
return result;
}
else
{
int iLine = 0;
while( (!result) && (iLine < polygon.Points.Count) )
{
XYLine line = new XYLine();
line = polygon.GetLine(iLine);
result = IsPointInLine(x, y, line);
iLine++;
}
}
return result;
}
///
/// The methods calculates the shared area of two arbitrarily shaped
/// polygons.
///
/// Polygon
/// Polygon
///
/// The shared area.
///
public static double CalculateSharedArea (XYPolygon polygonA, XYPolygon polygonB)
{
ArrayList triangleListA = polygonA.GetTriangulation();
ArrayList triangleListB = polygonB.GetTriangulation();
double area = 0;
for (int ia = 0; ia < triangleListA.Count; ia++)
{
XYPolygon triangleA = new XYPolygon((XYPolygon)triangleListA[ia]);
for (int ib = 0; ib < triangleListB.Count; ib++)
{
XYPolygon triangleB = new XYPolygon((XYPolygon)triangleListB[ib]);
area = area + TriangleIntersectionArea(triangleA, triangleB);
}
}
return area;
}
}
}