private static void AddWireSegment(ILayoutAccess lo, LayoutWiringPoints wiringData, WireSegment proposedSeg) { Location loc0 = proposedSeg.End0; Location loc1 = proposedSeg.End1; Dictionary <WireSegment, Location?> intersects = new Dictionary <WireSegment, Location?>(); List <Location> breaks = new List <Location>(); foreach (WireSegment w in wiringData.GetWiresContaining(loc0)) { intersects[w] = intersects.ContainsKey(w) ? (Location?)null : loc0; } foreach (WireSegment w in wiringData.GetWiresContaining(loc1)) { intersects[w] = intersects.ContainsKey(w) ? (Location?)null : loc1; } foreach (Location loc in proposedSeg.GetLocationsOnWire(Constants.GRID_SIZE, false)) { foreach (WireSegment w in wiringData.GetWiresEndingAt(loc)) { intersects[w] = intersects.ContainsKey(w) ? (Location?)null : loc; } if (wiringData.IsPortAt(loc)) { breaks.Add(loc); } } List <WireSegment> toRemove = new List <WireSegment>(); List <WireSegment> toAdd = new List <WireSegment>(); List <Location> endpoints = new List <Location>(); endpoints.Add(loc0); endpoints.Add(loc1); foreach (WireSegment w in intersects.Keys) { Location?intersect = intersects[w]; if (!intersect.HasValue) // segment crosses both endpoints - delete subsegment { toRemove.Add(w); } else if (w.IsCollinear(proposedSeg, Constants.GRID_SIZE)) { toRemove.Add(w); endpoints.Add(w.End0); endpoints.Add(w.End1); } else // segment crosses over this one - maybe we should split it { Location at = intersect.Value; breaks.Add(at); if (at != w.End0 && at != w.End1) { toRemove.Add(w); toAdd.Add(new WireSegment(w.End0, at)); toAdd.Add(new WireSegment(at, w.End1)); } } } endpoints.Sort(Location.XComparer); breaks.Add(endpoints[0]); breaks.Add(endpoints[endpoints.Count - 1]); breaks.Sort(Location.XComparer); Location cur = breaks[0]; foreach (Location loc in breaks) { if (cur != loc) { toAdd.Add(new WireSegment(cur, loc)); cur = loc; } } foreach (WireSegment seg in toRemove) { lo.RemoveWire(seg); } foreach (WireSegment seg in toAdd) { lo.AddWire(seg.End0, seg.End1); } }
public static void CheckForMerges(ILayoutAccess lo, LayoutWiringPoints wireData, IEnumerable <Location> toCheck) { HashSet <Location> done = new HashSet <Location>(); HashSet <WireSegment> toMerge = new HashSet <WireSegment>(); List <WireSegment> w0s = new List <WireSegment>(); List <WireSegment> w1s = new List <WireSegment>(); foreach (Location loc in toCheck) { if (!done.Contains(loc) && !wireData.IsPortAt(loc)) { done.Add(loc); WireSegment w0 = null; WireSegment w1 = null; bool moreFound = false; foreach (WireSegment w in wireData.GetWiresEndingAt(loc)) { if (w0 == null) { w0 = w; } else if (w1 == null) { w1 = w; } else { moreFound = true; break; } } if (!moreFound && w1 != null && w0.IsCollinear(w1, Constants.GRID_SIZE)) { w0s.Add(w0); w1s.Add(w1); toMerge.Add(w0); toMerge.Add(w1); } } } UnionFind <WireSegment> uf = new UnionFind <WireSegment>(toMerge); for (int i = 0; i < w0s.Count; i++) { uf[w0s[i]].Unite(uf[w1s[i]]); } foreach (UnionFindNode <WireSegment> root in uf.Roots) { List <Location> locs = new List <Location>(); foreach (UnionFindNode <WireSegment> member in root.GetSetMembers()) { WireSegment w = member.Value; lo.RemoveWire(w); locs.Add(w.End0); locs.Add(w.End1); } locs.Sort(Location.XComparer); lo.AddWire(locs[0], locs[locs.Count - 1]); } }