まあ、UnityにはGraphicsPathがありません(ポリゴンを塗りつぶし、それらを描画し、輪郭を描き、ユーティリティを一般的な形状で使用するため)、独自の実装を行っています。まあ、どちらが最良の選択肢か議論することもできますが、実際には、私は多くのことを学んでいるので、これを好みます.
アイデアは次のとおりです。ポリゴンが与えられた場合、ClipperLib を使用してオフセット ポリゴン (内側と外側) を作成し、後で LibTessDotNet を使用して三角測量を行い、これを出力します。
緑、青、黄色のピクセルは、すべての三角形の辺です。この形状の 501 個の三角形のような LibTessDotNet 出力。
だから、 @SimpleVarのおかげで私はこれをやった:
public static IEnumerable<T> PointsInTriangle<T>(T pt1, T pt2, T pt3)
where T : IPoint
{
/*
// https://www.geeksforgeeks.org/check-whether-triangle-valid-not-sides-given/
a + b > c
a + c > b
b + c > a
*/
float a = Vector2.Distance(new Vector2(pt1.x, pt1.y), new Vector2(pt2.x, pt2.y)),
b = Vector2.Distance(new Vector2(pt2.x, pt2.y), new Vector2(pt3.x, pt3.y)),
c = Vector2.Distance(new Vector2(pt3.x, pt3.y), new Vector2(pt1.x, pt1.y));
// (new[] { pt1, pt2, pt3 }).Distinct(new PointComparer()).Count() == 0
if (a + b <= c || a + c <= b || b + c <= a)
{
Debug.LogWarning($"The given points must form a triangle. {{{pt1}, {pt2}, {pt3}}}");
yield break;
}
T tmp;
if (pt2.x < pt1.x)
{
tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}
if (pt3.x < pt2.x)
{
tmp = pt2;
pt2 = pt3;
pt3 = tmp;
if (pt2.x < pt1.x)
{
tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}
}
var baseFunc = CreateFunc(pt1, pt3);
var line1Func = pt1.x == pt2.x ? (x => pt2.y) : CreateFunc(pt1, pt2);
for (var x = pt1.x; x < pt2.x; ++x)
{
int maxY;
int minY = GetRange(line1Func(x), baseFunc(x), out maxY);
for (int y = minY; y <= maxY; ++y)
yield return (T)Activator.CreateInstance(typeof(T), x, y);
}
var line2Func = pt2.x == pt3.x ? (x => pt2.y) : CreateFunc(pt2, pt3);
for (var x = pt2.x; x <= pt3.x; ++x)
{
int maxY;
int minY = GetRange(line2Func(x), baseFunc(x), out maxY);
for (int y = minY; y <= maxY; ++y)
yield return (T)Activator.CreateInstance(typeof(T), x, y);
}
}
private static int GetRange(float y1, float y2, out int maxY)
{
if (y1 < y2)
{
maxY = Mathf.FloorToInt(y2);
return Mathf.CeilToInt(y1);
}
maxY = Mathf.FloorToInt(y1);
return Mathf.CeilToInt(y2);
}
private static Func<int, float> CreateFunc<T>(T pt1, T pt2)
where T : IPoint
{
var y0 = pt1.y;
if (y0 == pt2.y)
return x => y0;
float m = (float)(pt2.y - y0) / (pt2.x - pt1.x);
return x => m * (x - pt1.x) + y0;
}
実際には機能しますが、うまくいきません。オーバーフローが発生するためです (このコードで大量の RAM が使用されるため、Process Explorer で Unity プロセスを強制終了する必要があります)。
ブレークポイントを使用してこのことをデバッグしましたが、実際にどこに問題があるのか わかりません。
問題は次のブロックまたは次のブロックにあると思いfor (var x = pt1.x; x < pt2.x; ++x)
ますfor (int y = minY; y <= maxY; ++y)
...しかし、私が言ったように、WinFormsで慣れているようにデバッグすることはできません。オーバーフローに達すると、Visual Studio がデバッグを停止し、Unity がクラッシュするため、少し行き詰まります。
オーバーフローを行う DotNetFiddle を実行しようとしましたが、ここでは何もわかりません...だから...コードを改善するために何ができるかわかりません。
あなたが見つけたすべてが最適化されていないこと、および私の主な目標を改善するために私ができるアプローチを説明してください.