private YnvPolySplit TryGetSplit(Dictionary <YnvPoly, YnvPolySplit> polysplits, YnvPoly poly) { if (poly == null) { return(null); } YnvPolySplit r = null; polysplits.TryGetValue(poly, out r); return(r); }
private List <YnvPoly> SplitPolys(List <YnvPoly> polys, bool xaxis) { var newpolys = new List <YnvPoly>(); var verts1 = new List <Vector3>(); var verts2 = new List <Vector3>(); var edges1 = new List <YnvEdge>(); var edges2 = new List <YnvEdge>(); var polysplits = new Dictionary <YnvPoly, YnvPolySplit>(); foreach (var poly in polys) //split along borders { var verts = poly.Vertices; if (verts == null) { continue; } //ignore empty polys.. if (verts.Length < 3) { continue; } //not enough verts for a triangle! Vector2I gprev = NavGrid.GetCellPos(verts[0]); int split1 = 0; int split2 = 0; for (int i = 1; i < verts.Length; i++) { Vector2I g = NavGrid.GetCellPos(verts[i]); int g1 = xaxis ? g.X : g.Y; int g2 = xaxis ? gprev.X : gprev.Y; if (g1 != g2) //this poly is crossing a border { if (split1 == 0) { split1 = i; } else { split2 = i; break; } } gprev = g; } if (split1 > 0) { var split2beg = (split2 > 0) ? split2 - 1 : verts.Length - 1; var split2end = split2beg + 1; var sv11 = verts[split1 - 1]; var sv12 = verts[split1]; var sv21 = verts[split2beg]; var sv22 = verts[split2]; var sp1 = GetSplitPos(sv11, sv12, xaxis); var sp2 = GetSplitPos(sv21, sv22, xaxis); //if ((sp1 == sp2) || (sp1 == sv11) || (sp1 == sv12) || (sp2 == sv21) || (sp2 == sv22)) if (!IsValidSplit(sp1, sp2, sv11, sv12, sv21, sv22)) { //split did nothing, just leave this poly alone newpolys.Add(poly); } else { //split it! var poly1 = new YnvPoly(); var poly2 = new YnvPoly(); poly1.RawData = poly.RawData; poly2.RawData = poly.RawData; verts1.Clear(); verts2.Clear(); for (int i = 0; i < split1; i++) { verts1.Add(verts[i]); } verts1.Add(sp1); verts1.Add(sp2); for (int i = split2end; i < verts.Length; i++) { verts1.Add(verts[i]); } verts2.Add(sp1); for (int i = split1; i < split2end; i++) { verts2.Add(verts[i]); } verts2.Add(sp2); poly1.Vertices = verts1.ToArray(); poly2.Vertices = verts2.ToArray(); //save this information for the edge splitting pass var polysplit = new YnvPolySplit(); polysplit.Orig = poly; polysplit.New1 = poly1; polysplit.New2 = poly2; polysplit.Split1 = split1; polysplit.Split2 = split2end; polysplits[poly] = polysplit; newpolys.Add(poly1); newpolys.Add(poly2); } } else { //no need to split newpolys.Add(poly); } } foreach (var polysplit in polysplits.Values) //build new edges for split polys { //the two edges that were split each need to be turned into two new edges (1 for each poly). //also, the split itself needs to be added as a new edge to the original poly. var poly = polysplit.Orig; var poly1 = polysplit.New1; var poly2 = polysplit.New2; var edges = poly.Edges; var verts = poly.Vertices; var ec = edges?.Length ?? 0; if (ec <= 0) { continue; } //shouldn't happen - no edges? if (ec != poly.Vertices?.Length) { continue; } //shouldn't happen var split1beg = polysplit.Split1 - 1; var split1end = polysplit.Split1; var split2beg = polysplit.Split2 - 1; var split2end = polysplit.Split2; edges1.Clear(); edges2.Clear(); var se1 = edges[split1beg]; //the two original edges that got split var se2 = edges[split2beg]; var sp1 = TryGetSplit(polysplits, se1.Poly1); //could use Poly2, but they should be the same.. var sp2 = TryGetSplit(polysplits, se2.Poly1); var sv1a = verts[split1beg]; var sv2a = verts[split2beg]; var sp1a = sp1?.GetNearest(sv1a); var sp1b = sp1?.GetOther(sp1a); var sp2b = sp2?.GetNearest(sv2a); var sp2a = sp2?.GetOther(sp2b); var edge1a = new YnvEdge(se1, sp1a); var edge1b = new YnvEdge(se1, sp1b); var edge2a = new YnvEdge(se2, sp2a); var edge2b = new YnvEdge(se2, sp2b); var splita = new YnvEdge(se1, poly2); var splitb = new YnvEdge(se1, poly1); for (int i = 0; i < split1beg; i++) { edges1.Add(edges[i]); //untouched edges } edges1.Add(edge1a); edges1.Add(splita); edges1.Add(edge2a); for (int i = split2end; i < ec; i++) { edges1.Add(edges[i]); //untouched edges } edges2.Add(edge1b); for (int i = split1end; i < split2beg; i++) { edges2.Add(edges[i]); //untouched edges } edges2.Add(edge2b); edges2.Add(splitb); poly1.Edges = edges1.ToArray(); poly2.Edges = edges2.ToArray(); if (poly1.Edges.Length != poly1.Vertices.Length) { } //debug if (poly2.Edges.Length != poly2.Vertices.Length) { } //debug } foreach (var poly in newpolys) //fix any untouched edges that joined to split polys { if (poly.Edges?.Length != poly.Vertices?.Length) { continue; } //shouldn't happen (no edges?) for (int i = 0; i < poly.Edges.Length; i++) { var edge = poly.Edges[i]; var vert = poly.Vertices[i]; if (edge == null) { continue; } //shouldn't happen if (edge.Poly1 != edge.Poly2) { continue; } //shouldn't happen? if (edge.Poly1 == null) { continue; } //probably this edge joins to nothing YnvPolySplit polysplit; if (polysplits.TryGetValue(edge.Poly1, out polysplit)) { var newpoly = polysplit.GetNearest(vert); if (newpoly == null) { } //debug edge.Poly1 = newpoly; edge.Poly2 = newpoly; } } } return(newpolys); }