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#

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;
}
}
}