private static ChannelCells GetChannelZones(ChannelsTree channelsTree, int mapW, int mapH) { var result = new Dictionary <Channel, IEnumerable <(int, int)> >(); channelsTree.VisitChannelsFromTop(channel => { var visited = new HashSet <(int, int)>(); var channelZone = new List <(int, int)>(); foreach (var point in channel.Points) { var x0 = Math.Max(0, point.X - ZoneR); var y0 = Math.Max(0, point.Y - ZoneR); var x1 = Math.Min(mapW - 1, point.X + ZoneR); var y1 = Math.Min(mapH - 1, point.Y + ZoneR); for (var x = x0; x <= x1; x++) { for (var y = y0; y < y1; y++) { if (!visited.Contains((x, y))) { visited.Add((x, y)); channelZone.Add((x, y)); } } } } result[channel] = channelZone; }); return(result); }
public static Targets Create(ChannelsTree channelsTree, GridMap targetMap, double targetValue, GridMap floodMap) { var zones = GetChannelZones(channelsTree, targetMap.Width, targetMap.Height); var needFlood = new ChannelCells(); var alreadyFlooded = new ChannelCells(); foreach (var channelZone in zones) { var zoneFloodedCells = new List <(int, int)>(); var zoneDryCells = new List <(int, int)>(); foreach (var(x, y) in channelZone.Value) { if (targetMap[x, y] == targetValue) { if (floodMap[x, y] == 0) { zoneDryCells.Add((x, y)); } else { zoneFloodedCells.Add((x, y)); } } } needFlood[channelZone.Key] = zoneDryCells; alreadyFlooded[channelZone.Key] = zoneFloodedCells; } return(new Targets(zones, needFlood, alreadyFlooded)); }
private static void BinarizeChannels(ChannelsTree channelsTree) { var newId = 0L; // start numeration of new channels without intersections with old channels channelsTree.VisitChannelsFromTop(channel => { newId = Math.Max(channel.Id, newId) + 1; }); channelsTree.VisitChannelsFromTop(channel => { var childrenDict = new Dictionary <ChannelPoint, List <Channel> >(); foreach (var child in channel.Connecions) { var closestPoint = FindClosestPoint(channel, child); if (closestPoint != null) { if (!childrenDict.ContainsKey(closestPoint)) { childrenDict[closestPoint] = new List <Channel>(); } childrenDict[closestPoint].Add(child); } } var curChannel = channel; var curPoints = new List <ChannelPoint>(); var points = new List <ChannelPoint>(channel.Points); for (var i = 0; i < points.Count; i++) { var point = points[i]; curPoints.Add(point); if (childrenDict.ContainsKey(point)) { var channelChildren = childrenDict[point]; curChannel.Points = curPoints; curChannel.Connecions = channelChildren; var newChannel = new Channel(newId++) { Points = new List <ChannelPoint>(curPoints), }; if (i != points.Count - 1) { curChannel.Connecions.Add(newChannel); } curChannel = newChannel; curPoints = new List <ChannelPoint>(); } } if (curPoints.Count > 0) { curChannel.Points = curPoints; } }); }
private static void CheckChannels(ChannelsTree tree) { tree.VisitChannelsFromTop(channel => { for (var i = 1; i < channel.Points.Count; i++) { var p0 = channel.Points[i - 1]; var p1 = channel.Points[i]; var dist = Dist(p0, p1); if (Dist(p0, p1) > 2) { Console.WriteLine($"Points {p0} and {p1} are too far in {channel.Id} with dist {dist}"); } } if (channel.Points.Count == 0) { Console.WriteLine($"{channel.Id} is empty"); } foreach (var child in channel.Connecions) { if (child != null) { var p = FindClosestPoint(channel, child); if (p != null) { var dist = Dist(p, child.Points[0]); if (dist > 1) { Console.WriteLine($"Child {child.Id} is too far from it's parent {channel.Id} with dist {dist}"); } if (dist == 0) { Console.WriteLine($"Child {child.Id} has shared point {p} with it's parent {channel.Id}"); } } } } }); }
private static void RestoreChildren(ChannelsTree channelsTree) { channelsTree.VisitChannelsFromTop(channel => { foreach (var child in channel.Connecions) { var origin = child.Points[0]; var closestPoint = FindClosestPoint(channel, child); if (closestPoint != null) { var dist = Dist(origin, closestPoint); if (dist >= 1) { // child.Points.InsertRange(0, Bresenham(closestPoint, origin)); } var sharedPoints = GetSharedPoints(channel, child); child.Points = child.Points.Except(sharedPoints).ToList(); } } }); }
private static void RestoreHoles(ChannelsTree channelsTree) { channelsTree.VisitChannelsFromTop(channel => { var set = new HashSet <ChannelPoint>(); for (var i = 1; i < channel.Points.Count; i++) { var p0 = channel.Points[i - 1]; var p1 = channel.Points[i]; var points = Bresenham(p0, p1); set.UnionWith(points); } if (channel.Points.Count == 1) { var p = channel.Points[0]; set.Add(new ChannelPoint(p.X, p.Y)); } var result = new List <ChannelPoint>(); while (result.Count != set.Count) { var count = result.Count; foreach (var point in set) { if (result.Contains(point)) { continue; } if (result.Count == 0) { result.Add(point); continue; } var x = point.X; var y = point.Y; var xs = result[0].X; var ys = result[0].Y; var xe = result[result.Count - 1].X; var ye = result[result.Count - 1].Y; if (Math.Abs(xs - x) + Math.Abs(ys - y) <= 5) { result.Insert(0, point); } else if (Math.Abs(xe - x) + Math.Abs(ye - y) <= 5) { result.Add(point); } } if (result.Count == count) { break; } } result.Reverse(); channel.Points = result; }); }
private static Bitmap DrawDirectionsBitmap(ChannelsTree channels, GridMap vxMap, GridMap vyMap) { var undecidedChannels = new List <Channel>(); var channelCos = new Dictionary <Channel, double>(); channels.VisitChannelsFromTop(channel => { if (channel.Points.Count == 0) { return; } double vxSum = 0; double vySum = 0; foreach (var point in channel.Points) { vxSum += vxMap[point.X, point.Y]; vySum += vyMap[point.X, point.Y]; } double vLen = Length(vxSum, vySum); if (Math.Abs(vLen) < 1e-6) { undecidedChannels.Add(channel); return; } double vx = vxSum / vLen; double vy = vySum / vLen; var p1 = channel.Points[0]; if (channel.Connecions.Count == 0) { undecidedChannels.Add(channel); } else { double p2x = 0; double p2y = 0; foreach (var child in channel.Connecions) { p2x += child.Points[0].X; p2y += child.Points[0].Y; } p2x /= channel.Connecions.Count; p2y /= channel.Connecions.Count; double px = p2x - p1.X; double py = p2y - p1.Y; double pLen = Length(px, py); if (Math.Abs(pLen) < 1e-6) { undecidedChannels.Add(channel); return; } px /= pLen; py /= pLen; var cosVal = px * vx + py * vy; channelCos[channel] = cosVal; } }); return(Drawing.DrawBitmap(944, 944, graphics => { Drawing.DrawChannels(graphics, undecidedChannels, new SolidBrush(Color.DarkOrchid)); foreach (var entry in channelCos) { var cos = entry.Value; var color = cos < 0 ? Drawing.GetColorBetween(Color.Black, Color.Red, cos * -1) : Drawing.GetColorBetween(Color.Black, Color.LawnGreen, cos); Drawing.DrawChannels(graphics, new [] { entry.Key }, new SolidBrush(color)); } })); }
public static ChannelSystemStats GetStats( ChannelsTree channelsTree, GridMap floodMap, GridMap typeUseMap, ISet <double> hozValues, ISet <double> socValues, double nonCadastrId, int r) { var selfStatsDict = new Dictionary <Channel, Stats>(); var aggrStatsDict = new Dictionary <Channel, Stats>(); channelsTree.VisitChannelsFromTop(channel => { var nonCadastrFlooded = 0; var nonCadastrNotFlooded = 0; var hozFlooded = 0; var hozNotFlooded = 0; var socNotFlooded = 0; var visitedCells = new HashSet <(int, int)>(); foreach (var point in channel.Points) { for (var x = point.X - r; x <= point.X + r; x++) { for (var y = point.Y - r; y <= point.Y + r; y++) { if (x >= 0 && x < typeUseMap.Width && y >= 0 && y < typeUseMap.Height && !visitedCells.Contains((x, y))) { var targetVal = typeUseMap[x, y]; var floodVal = floodMap[x, y]; if (targetVal == nonCadastrId) { if (floodVal == 0) { nonCadastrNotFlooded++; } else { nonCadastrFlooded++; } } else if (hozValues.Contains(targetVal)) { if (floodVal == 0) { hozNotFlooded++; } else { hozFlooded++; } } else if (socValues.Contains(targetVal) && floodVal == 0) { socNotFlooded++; } } visitedCells.Add((x, y)); } } } var selfStats = new Stats( channel.Points.Count, nonCadastrFlooded, nonCadastrNotFlooded, hozFlooded, hozNotFlooded, socNotFlooded); selfStatsDict[channel] = selfStats; }); var channelsStats = new List <ChannelStats>(); channelsTree.VisitChannelsFromBottom(channel => { var channelStats = selfStatsDict[channel]; var aggrLength = channelStats.Length; var aggrNonCadastrFlooded = channelStats.NonCadastrFlooded; var aggrNonCadastrNotFlooded = channelStats.NonCadastrNotFlooded; var aggrHozFlooded = channelStats.HozFlooded; var aggrHozNotFlooded = channelStats.HozNotFlooded; var aggrSocNotFlooded = channelStats.SocNotFlooded; foreach (var child in channel.Connecions) { var childAggrStats = aggrStatsDict[child]; aggrLength += childAggrStats.Length; aggrNonCadastrFlooded += childAggrStats.NonCadastrFlooded; aggrNonCadastrNotFlooded += childAggrStats.NonCadastrNotFlooded; aggrHozFlooded += childAggrStats.HozFlooded; aggrHozNotFlooded += childAggrStats.HozNotFlooded; aggrSocNotFlooded += childAggrStats.SocNotFlooded; } var aggrStats = new Stats( aggrLength, aggrNonCadastrFlooded, aggrNonCadastrNotFlooded, aggrHozFlooded, aggrHozNotFlooded, aggrSocNotFlooded); aggrStatsDict[channel] = aggrStats; channelsStats.Add(new ChannelStats(channel, channelStats, aggrStats)); }); return(new ChannelSystemStats(channelsStats)); }