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
|
{
|
/// <summary>
|
/// 任意二点の距離
|
/// </summary>
|
/// <param name="coord1"></param>
|
/// <param name="coord2"></param>
|
/// <returns></returns>
|
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);
|
}
|
|
/// <summary>
|
/// 二点同じ?
|
/// </summary>
|
/// <param name="coord1"></param>
|
/// <param name="coord2"></param>
|
/// <returns></returns>
|
public static bool Equals(PointD coord1, PointD coord2)
|
{
|
return coord1.X == coord2.X && coord1.Y == coord2.Y;
|
}
|
|
/// <summary>
|
/// 平行移動
|
/// </summary>
|
/// <param name="coords"></param>
|
/// <param name="offset"></param>
|
/// <returns></returns>
|
public static IList<PointD> OffsetCoords(IList<PointD> coords, double offset)
|
{
|
var path = new List<PointD>();
|
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;
|
}
|
}
|
}
|