public static void LoadOSMFile(string OsmFilepath, out Dictionary <string, OSMNode> nodes, out Dictionary <string, OSMWay> ways, out List <OSMMapMembers> relations)
        {
            nodes     = new Dictionary <string, OSMNode>();
            ways      = new Dictionary <string, OSMWay>();
            relations = new List <OSMMapMembers>();
            if (File.Exists(OsmFilepath))
            {
                var xmlText = File.ReadAllText(OsmFilepath);

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlText);
                var nodesDoc = doc.DocumentElement.ChildNodes;

                foreach (XmlNode node in nodesDoc)
                {
                    if (node.Name == "node")
                    {
                        OSMNode n = new OSMNode(node);
                        if (!nodes.ContainsKey(n.id))
                        {
                            nodes.Add(n.id, n);
                        }
                    }
                    else if (node.Name == "way")
                    {
                        OSMWay way = new OSMWay(node);
                        if (!ways.ContainsKey(way.id))
                        {
                            ways.Add(way.id, way);
                        }
                    }
                    else if (node.Name == "relation")
                    {
                        relations.Add(new OSMMapMembers(node));
                    }
                }
            }
        }
        public static void GenerateTrees(TerrainContainerObject container, List <GameObject> m_treesPrefabs, float m_treeDensity, float TreeScaleFactor, float TreeRandomScaleFactor, float m_TreeDistance, float m_BillBoardStartDistance, Dictionary <string, OSMNode> nodes, Dictionary <string, OSMWay> ways, List <OSMMapMembers> relations)
        {
            TreeDistance           = m_TreeDistance;
            BillBoardStartDistance = m_BillBoardStartDistance;

            AddTreesToTerrains(container, m_treesPrefabs);

            treeNodes   = new List <OSMNode>();
            woodWays    = new List <OSMWay>();
            treeRowWays = new List <OSMWay>();

            foreach (KeyValuePair <string, OSMNode> pair in nodes)
            {
                OSMNode n = pair.Value;
                if (n.HasTag("natural", "tree"))
                {
                    treeNodes.Add(n);
                }
            }

            foreach (KeyValuePair <string, OSMWay> pair in ways)
            {
                OSMWay w = pair.Value;
                if (w.HasTag("natural", "wood") || w.HasTags("landuse", "forest", "park"))
                {
                    woodWays.Add(w);
                }
                else if (w.HasTag("natural", "tree_row"))
                {
                    treeRowWays.Add(w);
                }
            }


            totalTreeCount = treeNodes.Count + treeRowWays.Count + woodWays.Count;

            if (totalTreeCount == 0)
            {
                return;
            }

            alreadyCreated = new HashSet <string>();

            var treeDensity = m_treeDensity;

            var TLPMercator_X = container.TLPointMercator.x;
            var TLPMercator_Y = container.TLPointMercator.y;

            var DRPMercator_X = container.DRPointMercator.x;
            var DRPMercator_Y = container.DRPointMercator.y;


            for (int i = 0; i < treeNodes.Count; i++)
            {
                OSMNode node = treeNodes[i];

                if (alreadyCreated.Contains(node.id))
                {
                    continue;
                }

                alreadyCreated.Add(node.id);

                var NodeP_Merc = GeoRefConversion.LatLongToMercat(node.Longitude, node.Latitude);

                double Offest_x = (NodeP_Merc.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);

                double Offest_y = 1 - (NodeP_Merc.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                Vector3 WSPos = new Vector3((float)(container.transform.position.x + container.size.x * Offest_x), 0, (float)(container.size.z + container.size.z * Offest_y));

                SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, WSPos);
            }

            for (int index = 0; index < treeRowWays.Count; index++)
            {
                OSMWay way = treeRowWays[index];
                if (alreadyCreated.Contains(way.id))
                {
                    continue;
                }
                alreadyCreated.Add(way.id);
                List <Vector3> points = OSMWay.GetGlobalPointsFromWay(way, nodes);

                for (int i = 0; i < points.Count; i++)
                {
                    Vector3 WSPos = points[i];

                    var WSPos_Merc = GeoRefConversion.LatLongToMercat(WSPos.x, WSPos.z);

                    double Offest_x = (WSPos_Merc.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);
                    double Offest_y = 1 - (WSPos_Merc.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                    WSPos.x = (float)(container.transform.position.x + container.size.x * Offest_x);
                    WSPos.z = (float)(container.transform.position.z + container.size.z * Offest_y);

                    points[i] = WSPos;
                }

                for (int i = 0; i < points.Count - 1; i++)
                {
                    int len = Mathf.RoundToInt((points[i] - points[i + 1]).magnitude / m_treeDensity);
                    if (len > 0)
                    {
                        for (int j = 0; j <= len; j++)
                        {
                            SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, Vector3.Lerp(points[i], points[i + 1], j / (float)len));
                        }
                    }
                    else
                    {
                        SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, points[i]);
                    }
                }
            }

            for (int index = 0; index < woodWays.Count; index++)
            {
                OSMWay way = woodWays[index];
                if (alreadyCreated.Contains(way.id))
                {
                    continue;
                }
                alreadyCreated.Add(way.id);
                List <Vector3> points = OSMWay.GetGlobalPointsFromWay(way, nodes);

                for (int i = 0; i < points.Count; i++)
                {
                    Vector3 p = points[i];

                    var sp = GeoRefConversion.LatLongToMercat(p.x, p.z);

                    double rx = (sp.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);
                    double ry = 1 - (sp.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                    p.x = (float)(container.transform.position.x + container.size.x * rx);
                    p.z = (float)(container.transform.position.z + container.size.z * ry);

                    points[i] = p;
                }

                Rect rect = Extensions.GetRectFromPoints(points);
                int  lx   = Mathf.RoundToInt(rect.width / m_treeDensity);
                int  ly   = Mathf.RoundToInt(rect.height / m_treeDensity);

                if (lx > 0 && ly > 0)
                {
                    m_currentWayID = way.id;

                    GenerateTerrainsTrees(TreeScaleFactor, TreeRandomScaleFactor, container, treeDensity, lx, ly, rect, points);
                }
            }
        }