示例#1
0
        /// <summary>
        /// Поменять lat и lon у полигонов
        /// </summary>
        private static void SwitchLatLon()
        {
            using (var db = new TransportContext())
            {
                var buildingsWithPolygon = db.Buildings.Where(b => b.Polygon != null);
                var progress = new ProgressBar(buildingsWithPolygon.Count(), "Перерасчет площадей... ");
                var indx = 0;
                foreach (var building in buildingsWithPolygon)
                {
                    // для каждого полигона внутри building.Polygon
                    var polyTexts = building.Polygon.AsText()
                        .Split(new[] { ")), ((", "), (" }, StringSplitOptions.RemoveEmptyEntries);

                    DbGeography polygon = null;
                    foreach (var polyText in polyTexts)
                    {
                        var matches = Regex.Matches(polyText, @"(?:\d*\.)?\d+");
                        polygon = polygon == null
                            ? GeoUtils.CreatePolygon(matches.Cast<Match>().Select(m => m.Value))
                            : polygon.Union(GeoUtils.CreatePolygon(matches.Cast<Match>().Select(m => m.Value)));
                    }

                    building.Polygon = polygon;
                    building.Square = polygon?.Area ?? 0;
                    progress.Report(indx++);
                }
                progress.Pause();
                Console.WriteLine("Сохраняем в БД...");
                db.SaveChanges();
            }
        }
        static async Task Main(string[] args)
        {
            StreamWriter streamWriter = null;

            try
            {
                // Get the current directory and make it a DirectoryInfo object.
                // Do not use Environment.CurrentDirectory, vistual studio
                // and visual studio code will return different result:
                // Visual studio will return @"projectDir\bin\Release\netcoreapp2.0\", yet
                // vs code will return @"projectDir\"
                var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

                // On windows, the current directory is the compiled binary sits,
                // so string like @"bin\Release\netcoreapp2.0\" will follow the project directory.
                // Hense, the project directory is the great grand-father of the current directory.
                string projectDirectory = currentDirectory.Parent.Parent.Parent.FullName;

                string dataDirectory = Path.Combine(projectDirectory, "Data");

                var countriesSourceFilePath      = Path.Combine(dataDirectory, "SeedCountry.csv");
                var countriesDestinationFilePath = Path.Combine(dataDirectory, "SeedCountryWithBoundary.csv");

                if (!File.Exists(countriesSourceFilePath))
                {
                    throw new ArgumentException($"File '{countriesSourceFilePath}' does not exist");
                }

                string kmlFilePath = Path.Combine(dataDirectory, "UIA_World_Countries_Boundaries.kml");

                if (!File.Exists(kmlFilePath))
                {
                    throw new ArgumentException($"File '{kmlFilePath}' does not exist");
                }

                // Read countries from file
                var countries = FileReader.GetCountries(FileReader.GetFileData(dataDirectory, "SeedCountry.csv"));

                streamWriter = new StreamWriter(path: countriesDestinationFilePath, append: false);
                await streamWriter.WriteLineAsync("CountryId,Name,Alpha2,Alpha3,AffiliationId,CountryBoundaries");

                using (var sr = new StreamReader(kmlFilePath))
                {
                    // Read all data from the reader
                    string kml = sr.ReadToEnd();

                    kml = kml.Replace("xmlns=\"http://earth.google.com/kml/2.0\"", ""); // HACK
                    kml = kml.Replace("xmlns='http://earth.google.com/kml/2.0'", "");   // DOUBLE HACK
                    kml = kml.Replace("xmlns=\"http://earth.google.com/kml/2.1\"", ""); // MULTI HACK!
                    kml = kml.Replace("xmlns='http://earth.google.com/kml/2.1'", "");   // M-M-M-M-M-M-M-MONSTER HACK!!!!

                    kml = kml.Replace("xmlns=\"http://www.opengis.net/kml/2.2\"", "");  // HACK
                    kml = kml.Replace("xmlns='http://www.opengis.net/kml/2.2'", "");    // DOUBLE HACK

                    // Open the downloaded xml in an System.Xml.XmlDocument to allow for XPath searching
                    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                    doc.LoadXml(kml);

                    // Try to find some sort of name for this kml from various places
                    System.Xml.XmlNode node = doc.SelectSingleNode("//Document[name]/name");

                    // Load Placemarks recursively and put them in folders
                    System.Xml.XmlNode documentNode = doc.SelectSingleNode("/kml/Document");
                    if (documentNode == null)
                    {
                        documentNode = doc.SelectSingleNode("/kml");
                    }

                    if (documentNode != null)
                    {
                        // Find Folders and initialize them recursively
                        System.Xml.XmlNodeList folders = documentNode.SelectNodes("Folder");
                        foreach (System.Xml.XmlNode folderNode in folders)
                        {
                            // Parse all Placemarks that have a name and Polygon
                            System.Xml.XmlNodeList placemarkNodes = folderNode.SelectNodes("Placemark");

                            foreach (System.Xml.XmlNode placemarkNode in placemarkNodes)
                            {
                                System.Xml.XmlNodeList simpleDataNodes = placemarkNode.SelectNodes("ExtendedData/SchemaData/SimpleData");

                                var countryCode = simpleDataNodes[2].InnerText;
                                var countryName = simpleDataNodes[1].InnerText;

                                Console.WriteLine($"Parsing {countryName}...");

                                DbGeography geoBorder = null;

                                System.Xml.XmlNodeList polygonNodes = placemarkNode.SelectNodes("Polygon");
                                foreach (System.Xml.XmlNode polygonNode in polygonNodes)
                                {
                                    // Parse Outer Ring
                                    System.Xml.XmlNode outerRingNode = polygonNode.SelectSingleNode("outerBoundaryIs/LinearRing/coordinates");
                                    if (outerRingNode != null)
                                    {
                                        var points     = GeographicCoordinate.ParseCoordinates(outerRingNode);
                                        var geoPolygon = GeographicCoordinate.ConvertGeoCoordinatesToPolygon(points);

                                        if (geoBorder == null)
                                        {
                                            geoBorder = geoPolygon;
                                        }
                                        else
                                        {
                                            try
                                            {
                                                geoBorder = geoBorder.Union(geoPolygon);
                                            }
                                            catch (Exception ex)
                                            {
                                                Console.ForegroundColor = ConsoleColor.Blue;
                                                Console.WriteLine(ex.Message);
                                                Console.ResetColor();
                                            }
                                        }
                                    }
                                }

                                polygonNodes = placemarkNode.SelectNodes("MultiGeometry/Polygon");
                                foreach (System.Xml.XmlNode polygonNode in polygonNodes)
                                {
                                    // Parse Outer Ring
                                    System.Xml.XmlNode outerRingNode = polygonNode.SelectSingleNode("outerBoundaryIs/LinearRing/coordinates");
                                    if (outerRingNode != null)
                                    {
                                        var points     = GeographicCoordinate.ParseCoordinates(outerRingNode);
                                        var geoPolygon = GeographicCoordinate.ConvertGeoCoordinatesToPolygon(points);

                                        if (geoBorder == null)
                                        {
                                            geoBorder = geoPolygon;
                                        }
                                        else
                                        {
                                            try
                                            {
                                                geoBorder = geoBorder.Union(geoPolygon);
                                            }
                                            catch (Exception ex)
                                            {
                                                Console.ForegroundColor = ConsoleColor.Blue;
                                                Console.WriteLine(ex.Message);
                                                Console.ResetColor();
                                            }
                                        }
                                    }
                                }

                                try
                                {
                                    await SaveCountryInDatabase(countryCode, countryName, geoBorder.AsText());
                                    await SaveCountryInFile(countryCode, countries, geoBorder, streamWriter);
                                }
                                catch (Exception ex)
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    Console.WriteLine($"Country {countryCode} is not added. Error: {ex.Message}");
                                    Console.ResetColor();
                                }
                            }
                        }
                    }
                }

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Done");
                Console.ResetColor();
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex.Message);
                Console.ResetColor();
            }
            finally
            {
                if (streamWriter != null)
                {
                    streamWriter.Dispose();
                }
            }

            Console.ReadLine();
        }