135 lines
4.8 KiB
C#
135 lines
4.8 KiB
C#
using UnityEngine;
|
|
|
|
namespace SuperTiled2Unity.Editor.Geometry
|
|
{
|
|
// A polygon edge that may be shared with another polygon
|
|
public class PolygonEdge
|
|
{
|
|
public bool HasBeenMerged { get; private set; }
|
|
|
|
public Vector2 P { get; }
|
|
public Vector2 Q { get; }
|
|
public float Length2 { get; }
|
|
|
|
// Our Major partner (the edge PQ will be counter-clockwise on this polygon)
|
|
// When we merge polygons it is always the Major partner that absorbs
|
|
public CompositionPolygon MajorPartner { get; private set; }
|
|
public int MajorPartner_pIndex { get; private set; }
|
|
public int MajorPartner_qIndex { get; private set; }
|
|
|
|
// Our Minor partner (the edge PQ will clockwise on this polygon)
|
|
public CompositionPolygon MinorPartner { get; private set; }
|
|
public int MinorPartner_pIndex { get; private set; }
|
|
public int MinorPartner_qIndex { get; private set; }
|
|
|
|
public PolygonEdge(CompositionPolygon compPolygon, int p)
|
|
{
|
|
Debug.Assert(compPolygon.Points.Count >= 3);
|
|
|
|
HasBeenMerged = false;
|
|
|
|
// P and Q make up our edge
|
|
int q = (p + 1) % compPolygon.Points.Count;
|
|
P = compPolygon.Points[p];
|
|
Q = compPolygon.Points[q];
|
|
|
|
// Create a compositional polygon with our edge
|
|
MajorPartner = compPolygon;
|
|
MajorPartner_pIndex = p;
|
|
MajorPartner_qIndex = q;
|
|
|
|
// Calculate the squared length
|
|
float x = (P.x - Q.x);
|
|
float y = (P.y - Q.y);
|
|
Length2 = (x * x) + (y * y);
|
|
}
|
|
|
|
public void AssignMinorPartner(CompositionPolygon polygon)
|
|
{
|
|
Debug.Assert(MinorPartner == null);
|
|
Debug.Assert(MajorPartner != null);
|
|
|
|
ReplaceMinor(polygon);
|
|
}
|
|
|
|
public void ReplaceMajor(CompositionPolygon polygon)
|
|
{
|
|
MajorPartner = polygon;
|
|
MajorPartner_pIndex = MajorPartner.Points.IndexOf(P);
|
|
MajorPartner_qIndex = MajorPartner.Points.IndexOf(Q);
|
|
}
|
|
|
|
public void ReplaceMinor(CompositionPolygon polygon)
|
|
{
|
|
MinorPartner = polygon;
|
|
MinorPartner_pIndex = MinorPartner.Points.IndexOf(P);
|
|
MinorPartner_qIndex = MinorPartner.Points.IndexOf(Q);
|
|
}
|
|
|
|
public bool CanMergePolygons()
|
|
{
|
|
// The two polygon partners can be merged if the two vectors on each point where they would merge don't create a concave polygon
|
|
// Concave testing is done through a cross product and assumes CCW winding of the polyon points
|
|
|
|
// Can merge point P of the Major/CCW partner?
|
|
{
|
|
// A = CWW[P - 1]
|
|
// B = CWW[P]
|
|
// C = CW[P + 1]
|
|
var A = MajorPartner.PrevPoint(MajorPartner_pIndex);
|
|
var B = MajorPartner.Points[MajorPartner_pIndex];
|
|
var C = MinorPartner.NextPoint(MinorPartner_pIndex);
|
|
float cross = GeoMath.Cross(A, B, C);
|
|
if (cross > 0)
|
|
return false;
|
|
}
|
|
|
|
// Can merge point Q of Major/CCW partner?
|
|
{
|
|
// A = CWW[Q + 1]
|
|
// B = CWW[Q]
|
|
// C = CW[Q-1]
|
|
var A = MajorPartner.NextPoint(MajorPartner_qIndex);
|
|
var B = MajorPartner.Points[MajorPartner_qIndex];
|
|
var C = MinorPartner.PrevPoint(MinorPartner_qIndex);
|
|
float cross = GeoMath.Cross(A, B, C);
|
|
if (cross < 0)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void MergePolygons()
|
|
{
|
|
Debug.Assert(HasBeenMerged == false);
|
|
|
|
// The major polygon will absorb the minor
|
|
MajorPartner.AbsorbPolygon(MajorPartner_qIndex, MinorPartner, MinorPartner_pIndex);
|
|
|
|
// All edges that referened the minor will need to reference the major
|
|
MinorPartner.ReplaceEdgesWithPolygon(MajorPartner, this);
|
|
|
|
// All edges that reference the major will need their P/Q indices updated
|
|
MajorPartner.UpdateEdgeIndices(this);
|
|
|
|
// This edge has now been processed and we shouldn't merge on it again
|
|
HasBeenMerged = true;
|
|
}
|
|
|
|
public void UpdateIndices(CompositionPolygon polygon)
|
|
{
|
|
if (polygon == this.MajorPartner)
|
|
{
|
|
MajorPartner_pIndex = polygon.Points.IndexOf(P);
|
|
MajorPartner_qIndex = polygon.Points.IndexOf(Q);
|
|
}
|
|
else if (polygon == MinorPartner)
|
|
{
|
|
MinorPartner_pIndex = polygon.Points.IndexOf(P);
|
|
MinorPartner_qIndex = polygon.Points.IndexOf(Q);
|
|
}
|
|
}
|
|
}
|
|
}
|