private IEnumerable <RegionQuadtree <T> > traverseInternal(RegionQuadtree <T>[] a) { var sides = QDO.Sides; var t = new RegionQuadtree <T> [8]; if (Type == QuadType.Grey) { for (int i = 0; i < 4; i++) { var d = sides[i]; t[(int)d] = soni(a[(int)d], QDO.Quad(QDO.OpSide(d), QDO.CSide(d))); t[(int)QDO.Quad(d, QDO.CSide(d))] = soni(a[(int)QDO.Quad(d, QDO.CSide(d))], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); t[(int)QDO.CSide(d)] = soni(a[(int)QDO.CSide(d)], QDO.Quad(d, QDO.CCSide(d))); t[(int)QDO.Quad(QDO.OpSide(d), QDO.CSide(d))] = soni(a[(int)QDO.CSide(d)], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); t[(int)QDO.OpSide(d)] = this[QDO.Quad(QDO.OpSide(d), QDO.CSide(d))]; t[(int)QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))] = this[QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))]; t[(int)QDO.CCSide(d)] = this[QDO.Quad(d, QDO.CCSide(d))]; t[(int)QDO.Quad(d, QDO.CCSide(d))] = soni(a[(int)d], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); foreach (var item in this[QDO.Quad(d, QDO.CSide(d))].traverseInternal(t)) { yield return(item); } } } else if (Type == QuadType.Black) { for (int i = 0; i < 8; i++) { if (a[i] != null && a[i].Type == QuadType.White) { a[i] = null; } } yield return(this); } }
private List <RegionQuadtree <T> > getAllWhoShareEdge(QuadDirection direction, QuadType type) { QuadDirection[] dir; var op = QDO.OpSide(direction); if ((int)direction % 2 == 0) { dir = new QuadDirection[] { QDO.Quad(op, QDO.CSide(op)), QDO.Quad(op, QDO.CCSide(op)) }; } else { dir = new QuadDirection[] { QDO.OpSide(op) }; } if (type == QuadType.Grey) { throw new ArgumentException("Grey isn't allowed!"); } var share = new List <RegionQuadtree <T> >(); getAllWhoShareEdgeInternal(type, this, share, dir); return(share); }
private void cclInternal(RegionQuadtree <T>[] a, List <DisjointSet <int> > linked, Dictionary <RegionQuadtree <T>, int> labels, QuadDirection[] sides, bool quadrants) { var t = new RegionQuadtree <T> [8]; if (Type == QuadType.Grey) { for (int i = 0; i < 4; i++) { var d = sides[i]; t[(int)d] = soni(a[(int)d], QDO.Quad(QDO.OpSide(d), QDO.CSide(d))); t[(int)QDO.CSide(d)] = soni(a[(int)QDO.CSide(d)], QDO.Quad(d, QDO.CCSide(d))); t[(int)QDO.OpSide(d)] = this[QDO.Quad(QDO.OpSide(d), QDO.CSide(d))]; t[(int)QDO.CCSide(d)] = this[QDO.Quad(d, QDO.CCSide(d))]; if (quadrants) { t[(int)QDO.Quad(d, QDO.CSide(d))] = soni(a[(int)QDO.Quad(d, QDO.CSide(d))], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); t[(int)QDO.Quad(QDO.OpSide(d), QDO.CSide(d))] = soni(a[(int)QDO.CSide(d)], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); t[(int)QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))] = this[QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))]; t[(int)QDO.Quad(d, QDO.CCSide(d))] = soni(a[(int)d], QDO.Quad(QDO.OpSide(d), QDO.CCSide(d))); } this[QDO.Quad(d, QDO.CSide(d))].cclInternal(t, linked, labels, sides, quadrants); } } else if (Type == QuadType.Black) { bool noNeighbors = true; var neighborLabels = new List <int>(); for (int i = 0; i < 8; i++) { if (a[i] != null && a[i].Type == QuadType.White) { a[i] = null; } if (a[i] != null) { if (a[i].Type == QuadType.Black && labels.ContainsKey(a[i])) { neighborLabels.Add(labels[a[i]]); noNeighbors = false; } else if (a[i].Type == QuadType.Grey) { var share = getAllWhoShareEdge((QuadDirection)i, QuadType.Black); foreach (var shareBlack in share) { if (labels.ContainsKey(shareBlack)) { neighborLabels.Add(labels[shareBlack]); noNeighbors = false; } } } } } if (noNeighbors) { var nextLabel = linked.Count; linked.Add(new DisjointSet <int>(nextLabel)); labels[this] = nextLabel; } else { labels[this] = neighborLabels.Min(); for (int i = 0; i < neighborLabels.Count; i++) { for (int j = 0; j < neighborLabels.Count; j++) { linked[neighborLabels[i]].Union(linked[neighborLabels[j]]); } } } } }