JD2022-TU1/main/tools/legacy/UA_AtlasEditor/Math/TriangulateEarClipping/CPolygon.cs

479 lines
16 KiB
C#

using System;
namespace GeometryUtility
{
/// <summary>
/// Summary description for CPolygon.
/// </summary>
public class CPolygon
{
private readonly CPoint2D[] _aVertices;
public CPoint2D this[int index]
{
set
{
_aVertices[index]=value;
}
get
{
return _aVertices[index];
}
}
public CPolygon()
{
}
//-----------------------------------------------------------------------------------------
public CPolygon(CPoint2D[] points)
{
int numPoints = points.Length;
try
{
if (numPoints < 3)
{
InvalidInputGeometryDataException ex= new InvalidInputGeometryDataException();
throw ex;
}
else
{
_aVertices = new CPoint2D[numPoints];
for (int i = 0; i < numPoints; i++) _aVertices[i] = points[i];
}
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine( e.Message+e.StackTrace);
}
}
//-----------------------------------------------------------------------------------------
public CPolygon(CPoint2D[] points, int[] index)
{
int numPoints = index.Length;
try
{
if (numPoints < 3)
{
InvalidInputGeometryDataException ex = new InvalidInputGeometryDataException();
throw ex;
}
else
{
_aVertices = new CPoint2D[numPoints];
for (int i = 0; i < numPoints; i++) _aVertices[i] = points[index[i]];
}
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine(e.Message + e.StackTrace);
}
}
/***********************************
From a given point, get its vertex index.
If the given point is not a polygon vertex,
it will return -1
***********************************/
public int VertexIndex(CPoint2D vertex)
{
int nIndex=-1;
int nNumPts=_aVertices.Length;
for (int i=0; i<nNumPts; i++) //each vertex
{
if (CPoint2D.SamePoints(_aVertices[i], vertex))
nIndex=i;
}
return nIndex;
}
/***********************************
From a given vertex, get its previous vertex point.
If the given point is the first one,
it will return the last vertex;
If the given point is not a polygon vertex,
it will return null;
***********************************/
public CPoint2D PreviousPoint(CPoint2D vertex)
{
int nIndex;
nIndex=VertexIndex(vertex);
if (nIndex==-1)
return null;
else //a valid vertex
{
if (nIndex==0) //the first vertex
{
int nPoints=_aVertices.Length;
return _aVertices[nPoints-1];
}
else //not the first vertex
return _aVertices[nIndex-1];
}
}
/***************************************
From a given vertex, get its next vertex point.
If the given point is the last one,
it will return the first vertex;
If the given point is not a polygon vertex,
it will return null;
***************************************/
public CPoint2D NextPoint(CPoint2D vertex)
{
CPoint2D nextPt=new CPoint2D();
int nIndex;
nIndex=VertexIndex(vertex);
if (nIndex==-1)
return null;
else //a valid vertex
{
int nNumOfPt=_aVertices.Length;
if (nIndex==nNumOfPt-1) //the last vertex
{
return _aVertices[0];
}
else //not the last vertex
return _aVertices[nIndex+1];
}
}
/******************************************
To calculate the polygon's area
Good for polygon with holes, but the vertices make the
hole should be in different direction with bounding
polygon.
Restriction: the polygon is not self intersecting
ref: www.swin.edu.au/astronomy/pbourke/
geometry/polyarea/
*******************************************/
public double PolygonArea()
{
double dblArea=0;
int nNumOfVertices=_aVertices.Length;
int j;
for (int i=0; i<nNumOfVertices; i++)
{
j=(i+1) % nNumOfVertices;
dblArea += _aVertices[i].X*_aVertices[j].Y;
dblArea -= (_aVertices[i].Y*_aVertices[j].X);
}
dblArea=dblArea/2;
return Math.Abs(dblArea);
}
/******************************************
To calculate the area of polygon made by given points
Good for polygon with holes, but the vertices make the
hole should be in different direction with bounding
polygon.
Restriction: the polygon is not self intersecting
ref: www.swin.edu.au/astronomy/pbourke/
geometry/polyarea/
As polygon in different direction, the result coulb be
in different sign:
If dblArea>0 : polygon in clock wise to the user
If dblArea<0: polygon in count clock wise to the user
*******************************************/
public static double PolygonArea(CPoint2D[] points)
{
double dblArea=0;
int nNumOfPts=points.Length;
int j;
for (int i=0; i<nNumOfPts; i++)
{
j=(i+1) % nNumOfPts;
dblArea += points[i].X*points[j].Y;
dblArea -= (points[i].Y*points[j].X);
}
dblArea=dblArea/2;
return dblArea;
}
/***********************************************
To check a vertex concave point or a convex point
-----------------------------------------------------------
The out polygon is in count clock-wise direction
************************************************/
public VertexType PolygonVertexType(CPoint2D vertex)
{
VertexType vertexType=VertexType.ErrorPoint;
if (PolygonVertex(vertex))
{
CPoint2D pti=vertex;
CPoint2D ptj=PreviousPoint(vertex);
CPoint2D ptk=NextPoint(vertex);
double dArea=PolygonArea(new CPoint2D[] {ptj,pti, ptk});
if (dArea<0)
vertexType= VertexType.ConvexPoint;
else if (dArea> 0)
vertexType= VertexType.ConcavePoint;
}
return vertexType;
}
/*********************************************
To check the Line of vertex1, vertex2 is a Diagonal or not
To be a diagonal, Line vertex1-vertex2 has no intersection
with polygon lines.
If it is a diagonal, return true;
If it is not a diagonal, return false;
reference: www.swin.edu.au/astronomy/pbourke
/geometry/lineline2d
*********************************************/
public bool Diagonal(CPoint2D vertex1, CPoint2D vertex2)
{
bool bDiagonal=false;
int nNumOfVertices=_aVertices.Length;
int j=0;
for (int i= 0; i<nNumOfVertices; i++) //each point
{
bDiagonal=true;
j= (i+1) % nNumOfVertices; //next point of i
//Diagonal line:
double x1=vertex1.X;
double y1=vertex1.Y;
double x2=vertex1.X;
double y2=vertex1.Y;
//CPolygon line:
double x3=_aVertices[i].X;
double y3=_aVertices[i].Y;
double x4=_aVertices[j].X;
double y4=_aVertices[j].Y;
double de=(y4-y3)*(x2-x1)-(x4-x3)*(y2-y1);
double ub=-1;
if (Math.Abs(de-0)>ConstantValue.SmallValue) //lines are not parallel
ub=((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/de;
if ((ub> 0) && (ub<1))
{
bDiagonal=false;
}
}
return bDiagonal;
}
/*************************************************
To check FaVertices make a convex polygon or
concave polygon
Restriction: the polygon is not self intersecting
Ref: www.swin.edu.au/astronomy/pbourke
/geometry/clockwise/index.html
********************************************/
public PolygonType GetPolygonType()
{
int nNumOfVertices=_aVertices.Length;
bool bSignChanged=false;
int nCount=0;
int j=0, k=0;
for (int i=0; i<nNumOfVertices; i++)
{
j=(i+1) % nNumOfVertices; //j:=i+1;
k=(i+2) % nNumOfVertices; //k:=i+2;
double crossProduct=(_aVertices[j].X- _aVertices[i].X)
*(_aVertices[k].Y- _aVertices[j].Y);
crossProduct=crossProduct-(
(_aVertices[j].Y- _aVertices[i].Y)
*(_aVertices[k].X- _aVertices[j].X)
);
//change the value of nCount
if ((crossProduct>0) && (nCount==0) )
nCount=1;
else if ((crossProduct<0) && (nCount==0))
nCount=-1;
if (((nCount==1) && (crossProduct<0))
||( (nCount==-1) && (crossProduct>0)) )
bSignChanged=true;
}
if (bSignChanged)
return PolygonType.Concave;
else
return PolygonType.Convex;
}
/***************************************************
Check a Vertex is a principal vertex or not
ref. www-cgrl.cs.mcgill.ca/~godfried/teaching/
cg-projects/97/Ian/glossay.html
PrincipalVertex: a vertex pi of polygon P is a principal vertex if the
diagonal pi-1, pi+1 intersects the boundary of P only at pi-1 and pi+1.
*********************************************************/
public bool PrincipalVertex(CPoint2D vertex)
{
bool bPrincipal=false;
if (PolygonVertex(vertex)) //valid vertex
{
CPoint2D pt1=PreviousPoint(vertex);
CPoint2D pt2=NextPoint(vertex);
if (Diagonal(pt1, pt2))
bPrincipal=true;
}
return bPrincipal;
}
/*********************************************
To check whether a given point is a CPolygon Vertex
**********************************************/
public bool PolygonVertex(CPoint2D point)
{
bool bVertex=false;
int nIndex=VertexIndex(point);
if ((nIndex>=0) && (nIndex<=_aVertices.Length-1))
bVertex=true;
return bVertex;
}
/*****************************************************
To reverse polygon vertices to different direction:
clock-wise <------->count-clock-wise
******************************************************/
public void ReverseVerticesDirection()
{
int nVertices=_aVertices.Length;
CPoint2D[] aTempPts=new CPoint2D[nVertices];
for (int i=0; i<nVertices; i++)
aTempPts[i]=_aVertices[i];
for (int i=0; i<nVertices; i++)
_aVertices[i]=aTempPts[nVertices-1-i];
}
/*****************************************
To check vertices make a clock-wise polygon or
count clockwise polygon
Restriction: the polygon is not self intersecting
Ref: www.swin.edu.au/astronomy/pbourke/
geometry/clockwise/index.html
*****************************************/
public PolygonDirection VerticesDirection()
{
int nCount=0, j=0, k=0;
int nVertices=_aVertices.Length;
for (int i=0; i<nVertices; i++)
{
j=(i+1) % nVertices; //j:=i+1;
k=(i+2) % nVertices; //k:=i+2;
double crossProduct=(_aVertices[j].X - _aVertices[i].X)
*(_aVertices[k].Y- _aVertices[j].Y);
crossProduct=crossProduct-(
(_aVertices[j].Y- _aVertices[i].Y)
*(_aVertices[k].X- _aVertices[j].X)
);
if (crossProduct>0)
nCount++;
else
nCount--;
}
if( nCount<0)
return PolygonDirection.Count_Clockwise;
else if (nCount> 0)
return PolygonDirection.Clockwise;
else
return PolygonDirection.Unknown;
}
/*****************************************
To check given points make a clock-wise polygon or
count clockwise polygon
Restriction: the polygon is not self intersecting
*****************************************/
public static PolygonDirection PointsDirection(
CPoint2D[] points)
{
int nCount=0, j=0, k=0;
int nPoints=points.Length;
if (nPoints<3)
return PolygonDirection.Unknown;
for (int i=0; i<nPoints; i++)
{
j=(i+1) % nPoints; //j:=i+1;
k=(i+2) % nPoints; //k:=i+2;
double crossProduct=(points[j].X - points[i].X)
*(points[k].Y- points[j].Y);
crossProduct=crossProduct-(
(points[j].Y- points[i].Y)
*(points[k].X- points[j].X)
);
if (crossProduct>0)
nCount++;
else
nCount--;
}
if( nCount<0)
return PolygonDirection.Count_Clockwise;
else if (nCount> 0)
return PolygonDirection.Clockwise;
else
return PolygonDirection.Unknown;
}
//-----------------------------------------------------------------------------------------
public static void ReversePointsDirection( CPoint2D[] points )
{
int nVertices=points.Length;
CPoint2D[] aTempPts=new CPoint2D[nVertices];
for (int i=0; i<nVertices; i++) aTempPts[i]=points[i];
for (int i=0; i<nVertices; i++) points[i]=aTempPts[nVertices-1-i];
}
//-----------------------------------------------------------------------------------------
public static void ReversePointsIndexDirection(int[] pointsIndex)
{
int nVertices = pointsIndex.Length;
int[] aTempPts = new int[nVertices];
for (int i = 0; i < nVertices; i++) aTempPts[i] = pointsIndex[i];
for (int i = 0; i < nVertices; i++) pointsIndex[i] = aTempPts[nVertices - 1 - i];
}
}
}