You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.5 KiB
C#
191 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Txgy.EWS.Client.FocalMechanism.Model
|
|
{
|
|
// summary
|
|
// object for the result of polygon
|
|
public class Polygon :Graph
|
|
{
|
|
public List<FMStation> upperBound { get; set; }
|
|
public List<FMStation> lowerBound { get; set; }
|
|
|
|
public Line axis { get; set; }
|
|
|
|
public Polygon()
|
|
{
|
|
upperBound = new List<FMStation>();
|
|
lowerBound = new List<FMStation>();
|
|
}
|
|
|
|
// summary
|
|
// add point to current polygon
|
|
public void addPoint(FMStation p)
|
|
{
|
|
if (p == null) return;
|
|
//upper bound
|
|
int upIndex = getPoint(upperBound, p);
|
|
if (upIndex == upperBound.Count)
|
|
{
|
|
upperBound.Add(p);
|
|
smoothUppderBound(upperBound, upperBound.Count - 1);
|
|
}
|
|
else if (upIndex == -1)
|
|
{
|
|
upperBound.Insert(0, p);
|
|
smoothUppderBound(upperBound, 0);
|
|
}
|
|
else if (p.X == upperBound[upIndex].X)
|
|
{
|
|
if (p.Y > upperBound[upIndex].Y)
|
|
{
|
|
upperBound[upIndex] = p;
|
|
smoothUppderBound(upperBound, upIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isAbove(upperBound[upIndex - 1], upperBound[upIndex], p))
|
|
{
|
|
upperBound.Insert(upIndex, p);
|
|
smoothUppderBound(upperBound, upIndex);
|
|
}
|
|
}
|
|
|
|
//lower bound
|
|
int downIndex = getPoint(lowerBound, p);
|
|
if (downIndex == lowerBound.Count)
|
|
{
|
|
lowerBound.Add(p);
|
|
smoothLowerBound(lowerBound, lowerBound.Count - 1);
|
|
}
|
|
else if (downIndex == -1)
|
|
{
|
|
lowerBound.Insert(0, p);
|
|
smoothLowerBound(lowerBound, 0);
|
|
}
|
|
else if (p.X == lowerBound[downIndex].X)
|
|
{
|
|
if (p.Y > lowerBound[downIndex].Y)
|
|
{
|
|
lowerBound[downIndex] = p;
|
|
smoothLowerBound(lowerBound, downIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isBelow(lowerBound[downIndex - 1], lowerBound[downIndex], p))
|
|
{
|
|
lowerBound.Insert(downIndex, p);
|
|
smoothLowerBound(lowerBound, downIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// summary
|
|
// check if this polygon contains this station
|
|
public bool contains(FMStation p)
|
|
{
|
|
if (p == null) return false;
|
|
//upper bound
|
|
int upIndex = getPoint(upperBound, p);
|
|
if (upIndex == upperBound.Count || upIndex == -1)
|
|
{
|
|
return false;
|
|
}
|
|
else if (p.X == upperBound[upIndex].X)
|
|
{
|
|
if (p.Y > upperBound[upIndex].Y)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isAbove(upperBound[upIndex - 1], upperBound[upIndex], p))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//lower bound
|
|
int downIndex = getPoint(lowerBound, p);
|
|
if (downIndex == lowerBound.Count || downIndex == -1)
|
|
{
|
|
return false;
|
|
}
|
|
else if (p.X == lowerBound[downIndex].X)
|
|
{
|
|
if (p.Y > lowerBound[downIndex].Y)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isBelow(lowerBound[downIndex - 1], lowerBound[downIndex], p))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private int getPoint(List<FMStation> l, FMStation p)
|
|
{
|
|
if (l.Count == 0 || p.X < l[0].X) return -1;
|
|
for (int i = 0; i < l.Count; i++)
|
|
{
|
|
if (p.X <= l[i].X) return i;
|
|
}
|
|
return l.Count;
|
|
}
|
|
|
|
private void smoothUppderBound(List<FMStation> l, int i)
|
|
{
|
|
while (l.Count - i > 2 && isBelow(l[i], l[i + 2], l[i + 1]))
|
|
{
|
|
l.RemoveAt(i + 1);
|
|
}
|
|
while (i > 1 && isBelow(l[i - 2], l[i], l[i - 1]))
|
|
{
|
|
l.RemoveAt(i - 1);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
private void smoothLowerBound(List<FMStation> l, int i)
|
|
{
|
|
while (l.Count - i > 2 && isAbove(l[i], l[i + 2], l[i + 1]))
|
|
{
|
|
l.RemoveAt(i + 1);
|
|
}
|
|
while (i > 1 && isAbove(l[i - 2], l[i], l[i - 1]))
|
|
{
|
|
l.RemoveAt(i - 1);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// summary
|
|
// return if target point is above the line from a to b
|
|
private bool isAbove(FMStation a, FMStation b, FMStation target)
|
|
{
|
|
double lineY = (b.Y - a.Y) / (b.X - a.X) * (target.X - a.X) + a.Y;
|
|
return target.Y >= lineY;
|
|
}
|
|
|
|
// summary
|
|
// return if target point is below the line from a to b
|
|
private bool isBelow(FMStation a, FMStation b, FMStation target)
|
|
{
|
|
double lineY = (b.Y - a.Y) / (b.X - a.X) * (target.X - a.X) + a.Y;
|
|
return target.Y <= lineY;
|
|
}
|
|
}
|
|
}
|