using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HotelPms.Share.Windows.GraphicsApi
{
public class Geometry
{
///
/// 任意二点の距離
///
///
///
///
public static double Dist2d(PointD coord1, PointD coord2)
{
double dx = coord1.X - coord2.X;
double dy = coord1.Y - coord2.Y;
return Math.Sqrt(dx * dx + dy * dy);
}
///
/// 二点同じ?
///
///
///
///
public static bool Equals(PointD coord1, PointD coord2)
{
return coord1.X == coord2.X && coord1.Y == coord2.Y;
}
///
/// 平行移動
///
///
///
///
public static IList OffsetCoords(IList coords, double offset)
{
var path = new List();
int N = coords.Count - 1;
int max = N;
double mi, mi1, li, li1, ri, ri1, si, si1, Xi1, Yi1;
PointD p0, p1, p2;
var isClosed = Equals(coords[0], coords[N]);
if (!isClosed)
{
p0 = coords[0];
p1 = coords[1];
double qq1 = Dist2d(p0, p1);
double qq2 = (p1.Y - p0.Y);
double qq3 = qq2 / qq1;
double qq4 = qq3 * offset;
double qq5 = p0.X + qq4;
p2 = new PointD(p0.X + (p1.Y - p0.Y) / Dist2d(p0, p1) * offset, p0.Y - (p1.X - p0.X) / Dist2d(p0, p1) * offset);
path.Add(p2);
coords.Add(coords[N].Clone());
N++;
max--;
}
for (var i = 0; i < max; i++)
{
p0 = coords[i];
p1 = coords[(i + 1) % N];
p2 = coords[(i + 2) % N];
mi = (p1.Y - p0.Y) / (p1.X - p0.X);
mi1 = (p2.Y - p1.Y) / (p2.X - p1.X);
// Prevent alignements
if (Math.Abs(mi - mi1) > 1e-10) //0.0000000001
{
li = Math.Sqrt((p1.X - p0.X) * (p1.X - p0.X) + (p1.Y - p0.Y) * (p1.Y - p0.Y));
li1 = Math.Sqrt((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y));
ri = p0.X + offset * (p1.Y - p0.Y) / li;
ri1 = p1.X + offset * (p2.Y - p1.Y) / li1;
si = p0.Y - offset * (p1.X - p0.X) / li;
si1 = p1.Y - offset * (p2.X - p1.X) / li1;
Xi1 = (mi1 * ri1 - mi * ri + si - si1) / (mi1 - mi);
Yi1 = (mi * mi1 * (ri1 - ri) + mi1 * si - mi * si1) / (mi1 - mi);
// Correction for vertical lines
if (p1.X - p0.X == 0)
{
Xi1 = p1.X + offset * (p1.Y - p0.Y) / Math.Abs(p1.Y - p0.Y);
Yi1 = mi1 * Xi1 - mi1 * ri1 + si1;
}
if (p2.X - p1.X == 0)
{
Xi1 = p2.X + offset * (p2.Y - p1.Y) / Math.Abs(p2.Y - p1.Y);
Yi1 = mi * Xi1 - mi * ri + si;
}
path.Add(new PointD(Xi1, Yi1));
}
}
if (isClosed)
{
path.Add(path[0].Clone());
}
else
{
coords.RemoveAt(coords.Count - 1);
p0 = coords[coords.Count - 1];
p1 = coords[coords.Count - 2];
p2 = new PointD(p0.X - (p1.Y - p0.Y) / Dist2d(p0, p1) * offset, p0.Y + (p1.X - p0.X) / Dist2d(p0, p1) * offset);
path.Add(p2);
}
return path;
}
}
}