private void ConnectCloseCountriesOverWater(int maxDistance) { List <OceanConnection> oceanConnections = new List <OceanConnection>(); foreach (Country source in Map.Countries) { foreach (Country target in Map.Countries) { foreach (Point sourcePoint in source.AreaPixels) { foreach (Point targetPoint in target.AreaPixels) { if (source != target && !source.Neighbours.Contains(target) && !target.Neighbours.Contains(source) && !WithinWaterConnectionCountryRange(source, target)) { int distance = (int)(Math.Sqrt((targetPoint.X - sourcePoint.X) * (targetPoint.X - sourcePoint.X) + ((targetPoint.Y - sourcePoint.Y) * (targetPoint.Y - sourcePoint.Y)))); if (distance <= maxDistance) { // Found new short connection OceanConnection newConnection = new OceanConnection(distance, source, target, sourcePoint, targetPoint); // Check if not crossing land bool valid = true; int steps = newConnection.Distance; for (int i = 0; i < steps; i++) { int targetX = (int)(newConnection.SourcePoint.X + ((newConnection.TargetPoint.X - newConnection.SourcePoint.X) / steps * i)); int targetY = (int)(newConnection.SourcePoint.Y + ((newConnection.TargetPoint.Y - newConnection.SourcePoint.Y) / steps * i)); if (!(Map.CountryMap[targetX, targetY] == MapPixelType.OCEAN || Map.CountryMap[targetX, targetY] == MapPixelType.BORDER || Map.CountryMap[targetX, targetY] == newConnection.SourceCountry.Id || Map.CountryMap[targetX, targetY] == newConnection.TargetCountry.Id)) { valid = false; } } if (valid) { // Check if connection between those country exists if (oceanConnections.Where(x => source == x.SourceCountry && target == x.TargetCountry).Count() > 0) { OceanConnection oldCon = oceanConnections.Where(x => source == x.SourceCountry && target == x.TargetCountry).FirstOrDefault(); if (distance < oldCon.Distance) { oceanConnections.Remove(oldCon); oceanConnections.Add(newConnection); newConnection.SourceCountry.AddNeighbour(newConnection.TargetCountry); newConnection.TargetCountry.AddNeighbour(newConnection.SourceCountry); } } else { oceanConnections.Add(newConnection); newConnection.SourceCountry.AddNeighbour(newConnection.TargetCountry); newConnection.TargetCountry.AddNeighbour(newConnection.SourceCountry); } } } } } } } } foreach (OceanConnection con in oceanConnections) { // Draw connection to map double startX = con.SourcePoint.X; double startY = con.SourcePoint.Y; double endX = con.TargetPoint.X; double endY = con.TargetPoint.Y; int circlesDrawn = 0; int steps = con.Distance / 4; for (int i = 0; i < steps; i++) { int targetX = (int)(startX + ((endX - startX) / steps * i)); int targetY = (int)(startY + ((endY - startY) / steps * i)); if (Map.CountryMap[targetX, targetY] == MapPixelType.OCEAN) { Map.GetWriteableBitmap().FillEllipseCentered(targetX, targetY, 1, 1, Color.FromArgb(255, 255, 0, 0)); circlesDrawn++; } } if (circlesDrawn == 0) { Map.GetWriteableBitmap().FillEllipseCentered((int)(startX + (endX - startX) / 2), (int)(startY + (endY - startY) / 2), 1, 1, Color.FromArgb(255, 255, 0, 0)); } } Map.SetMap(MapGenerator.ConvertWriteableBitmapToBitmapImage(Map.GetWriteableBitmap()), false); RefreshMap(); }
private void ConnectIslands() { List <HashSet <Country> > Clusters = new List <HashSet <Country> >(); foreach (Country c in Map.Countries) { // Create new cluster if country is not in one if (Clusters.Where(x => x.Contains(c)).Count() == 0) { HashSet <Country> newCluster = new HashSet <Country>(); newCluster.Add(c); foreach (Country n in c.Neighbours) { newCluster.Add(n); } Clusters.Add(newCluster); } // Add to cluster if country already is in one else { HashSet <Country> cluster = Clusters.Where(x => x.Contains(c)).First(); foreach (Country n in c.Neighbours) { cluster.Add(n); } } } // Merge clusters List <Country> inMultipleClusters = Map.Countries.Where(x => (Clusters.Where(l => l.Contains(x)).Count() > 1)).ToList(); foreach (Country c in inMultipleClusters) { List <HashSet <Country> > ClustersToMerge = Clusters.Where(l => l.Contains(c)).ToList(); if (ClustersToMerge.Count > 1) { HashSet <Country> ClusterToKeep = ClustersToMerge[0]; List <HashSet <Country> > ClustersToRemove = ClustersToMerge.Skip(1).ToList(); foreach (HashSet <Country> toRemove in ClustersToRemove) { foreach (Country c2 in toRemove) { ClusterToKeep.Add(c2); } Clusters.Remove(toRemove); } } } // Connect clusters while (Clusters.Count > 1) { HashSet <Country> clusterToConnect = Clusters[0]; List <OceanConnection> connections = new List <OceanConnection>(); // Find nearest neighbours foreach (Country c1 in clusterToConnect) { foreach (HashSet <Country> others in Clusters.Skip(1).ToList()) { foreach (Country c2 in others) { foreach (Point p1 in c1.AreaPixels) { foreach (Point p2 in c2.AreaPixels) { int distance = (int)(Math.Sqrt((p2.X - p1.X) * (p2.X - p1.X) + ((p2.Y - p1.Y) * (p2.Y - p1.Y)))); if (connections.Count < islandConnections || distance < connections[0].Distance) { // Found new short connection OceanConnection newConnection = new OceanConnection(distance, c1, c2, p1, p2, others); // Check if not crossing land bool valid = true; int steps = newConnection.Distance / 4; for (int i = 0; i < steps; i++) { int targetX = (int)(newConnection.SourcePoint.X + ((newConnection.TargetPoint.X - newConnection.SourcePoint.X) / steps * i)); int targetY = (int)(newConnection.SourcePoint.Y + ((newConnection.TargetPoint.Y - newConnection.SourcePoint.Y) / steps * i)); if (!(Map.CountryMap[targetX, targetY] == MapPixelType.OCEAN || Map.CountryMap[targetX, targetY] == MapPixelType.BORDER || Map.CountryMap[targetX, targetY] == newConnection.SourceCountry.Id || Map.CountryMap[targetX, targetY] == newConnection.TargetCountry.Id)) { valid = false; } } if (valid) { // Check if connection between those country exists if (connections.Where(x => c1 == x.SourceCountry && c2 == x.TargetCountry).Count() > 0) { OceanConnection oldCon = connections.Where(x => c1 == x.SourceCountry && c2 == x.TargetCountry).FirstOrDefault(); if (distance < oldCon.Distance) { connections.Remove(oldCon); connections.Add(newConnection); } } else { connections.Add(newConnection); } connections = connections.OrderBy(x => x.Distance).Take(islandConnections).OrderByDescending(x => x.Distance).ToList(); } } } } } } } // Add neighbours foreach (OceanConnection con in connections) { con.SourceCountry.AddNeighbour(con.TargetCountry); con.TargetCountry.AddNeighbour(con.SourceCountry); foreach (Country c in con.TargetCluster) { clusterToConnect.Add(c); } Clusters.Remove(con.TargetCluster); // Draw connection to map double startX = con.SourcePoint.X; double startY = con.SourcePoint.Y; double endX = con.TargetPoint.X; double endY = con.TargetPoint.Y; int circlesDrawn = 0; int steps = con.Distance / 4; for (int i = 0; i < steps; i++) { int targetX = (int)(startX + ((endX - startX) / steps * i)); int targetY = (int)(startY + ((endY - startY) / steps * i)); if (Map.CountryMap[targetX, targetY] == MapPixelType.OCEAN) { Map.GetWriteableBitmap().FillEllipseCentered(targetX, targetY, 1, 1, Color.FromArgb(255, 255, 0, 0)); circlesDrawn++; } } if (circlesDrawn == 0) { Map.GetWriteableBitmap().FillEllipseCentered((int)(startX + (endX - startX) / 2), (int)(startY + (endY - startY) / 2), 1, 1, Color.FromArgb(255, 255, 0, 0)); } } Map.SetMap(MapGenerator.ConvertWriteableBitmapToBitmapImage(Map.GetWriteableBitmap()), false); RefreshMap(); } }