Пример #1
0
        /// <summary>
        /// Gets the route path of an OSM route.
        /// </summary>
        /// <param name="routeId">The osm id of the route(relation)</param>
        /// <param name="memberType">The type of members to retrieve (This parameter is currently not used.).</param>
        /// <param name="connectionString">The connection string of the database</param>
        /// <param name="correction">The correction types to be applied.</param>
        /// <returns>Return a list of nodes</returns>
        /// <seealso cref="GetRoutePathExperimental"/>
        public static List <OsmNode> GetRoutePath(string routeId, int memberType, String connectionString, RouteCorrection correction = RouteCorrection.RemoveDuplicates | RouteCorrection.FixReversedLine | RouteCorrection.RemoveDeadends)
        {
            Aram.OSMParser.Relation rell = new Aram.OSMParser.Relation(routeId);
            var members      = rell.GetMembersPostgreSQLByType(routeId, memberType, connectionString);
            var way          = new Aram.OSMParser.Way();
            var withoutAreas = members.Where(
                m =>
                way.GetTagsStockholmPostgreSQL(m.ReferenceId, connectionString)
                .Where(w => w.KeyValueSQL[0] == "area" && w.KeyValueSQL[1] == "yes").Count() == 0);
            var sorted = withoutAreas.ToList();

            sorted.Sort((m1, m2) => m1.order.CompareTo(m2.order));

            var     Nodes = sorted.Select(w => way.GetNodesPostgreSQL(w.ReferenceId, connectionString)).ToList();
            OsmNode start;
            OsmNode end;

            // Finding all the closed paths such as squares, roundabout or circles.
            var closedLines = new List <Member>();

            for (int i = 0; i < sorted.Count; i++)
            {
                start = Nodes[i][0];
                end   = Nodes[i][Nodes[i].Count - 1];
                if (start.EqualsById(end))
                {
                    closedLines.Add(sorted[i]);
                }
            }


            var original = sorted;
            var tempList = new List <Member>();
            // Remove deadends.

            bool deadendFound = true;


            bool closed     = false;
            bool prevclosed = false;
            bool nextclosed = false;

            // Recursive removal of deadends
            if (correction == RouteCorrection.RemoveDeadends)
            {
                // while (deadendFound)
                {
                    deadendFound = false;
                    if (tempList.Count != 0)
                    {
                        original = new List <Member>(tempList);
                        original.Sort((m1, m2) => m1.order.CompareTo(m2.order));
                    }
                    tempList.Clear();
                    tempList.Add(original[0]);
                    Nodes = original.Select(w => way.GetNodesPostgreSQL(w.ReferenceId, connectionString)).ToList();
                    for (int i = 1; i < original.Count - 1; i++)
                    {
                        // CHEK IF ANY OF THE INSTANCES IS A closed line
                        start      = Nodes[i][0];
                        end        = Nodes[i][Nodes[i].Count - 1];
                        closed     = closedLines.Contains(original[i]);
                        prevclosed = closedLines.Contains(original[i - 1]);
                        nextclosed = closedLines.Contains(original[i + 1]);
                        if (!(closed || prevclosed || nextclosed))
                        {
                            var startFound =
                                Nodes.Where(n => (
                                                (n[0].EqualsById(start) || n[n.Count - 1].EqualsById(start)) &&
                                                !(n[0].EqualsById(start) && n[n.Count - 1].EqualsById(end))
                                                )).Count() != 0;
                            var endFound =
                                Nodes.Where(n => (
                                                (n[0].EqualsById(end) || n[n.Count - 1].EqualsById(end)) &&
                                                !(n[0].EqualsById(start) && n[n.Count - 1].EqualsById(end))
                                                )).Count() != 0;

                            if (startFound && endFound)
                            {
                                tempList.Add(original[i]);
                            }
                            else
                            {
                                deadendFound = true;
                            }
                        }
                        else
                        {
                            // Search all the nodes on the line to find connections.
                            var startFound =
                                Nodes[i].Any(n => Nodes[i - 1].ContainsOsmNodeById(n));
                            var endFound =
                                Nodes[i].Any(n => Nodes[i + 1].ContainsOsmNodeById(n));
                            if (startFound && endFound)
                            {
                                tempList.Add(original[i]);
                            }
                        }
                    }
                    tempList.Add(original[original.Count - 1]);
                }

                Nodes = tempList.Select(w => way.GetNodesPostgreSQL(w.ReferenceId, connectionString)).ToList();
            }
            //closedLines.Clear();
            //for (int i = 0; i < tempList.Count; i++)
            //{
            //    start = Nodes[i][0];
            //    end = Nodes[i][Nodes[i].Count - 1];
            //    if (start.EqualsById(end))
            //        closedLines.Add(sorted[i]);
            //}

            //string route = "";
            List <OsmNode[]> correctPath = new List <OsmNode[]>();

            //route = tempList[0].RelationId;
            correctPath.Add(Nodes[0].ToArray());
            for (int i = 1; i < Nodes.Count; i++)
            {
                // It could be a circle
                var isCircle     = Nodes[i][0].EqualsById(Nodes[i][Nodes[i].Count - 1]);
                var isPrevCircle = Nodes[i - 1][0].EqualsById(Nodes[i - 1][Nodes[i - 1].Count - 1]);
                var isReverse    = Nodes[i][Nodes[i].Count - 1].EqualsById(Nodes[i - 1][Nodes[i - 1].Count - 1]);
                if (!isCircle && !isReverse)
                {
                    // Draw normally

                    correctPath.Add(Nodes[i].ToArray());
                }
                else
                {
                    if (isCircle)
                    {
                        // Find the correct portion and draw it
                        // Intersection with the previous line
                        OsmNode intersectionWithPrevious =
                            Nodes[i].Intersect(Nodes[i - 1],
                                               new LambdaComparer <OsmNode>((o1, o2) => o1.EqualsById(o2))
                                               ).FirstOrDefault();
                        OsmNode intersectionWithNext = null;
                        if (i < Nodes.Count - 1)
                        {
                            intersectionWithNext = Nodes[i].Intersect(Nodes[i + 1],
                                                                      new LambdaComparer <OsmNode>((o1, o2) => o1.EqualsById(o2))
                                                                      ).FirstOrDefault();
                        }

                        int firstNodeIndex;
                        int LastNodeIndex;

                        if (i < Nodes.Count - 1)
                        { // If it is not the last line.
                            firstNodeIndex = intersectionWithPrevious.order < intersectionWithNext.order ? intersectionWithPrevious.order : intersectionWithNext.order;
                            LastNodeIndex  = intersectionWithPrevious.order > intersectionWithNext.order ? intersectionWithPrevious.order : intersectionWithNext.order;
                        }
                        else
                        {
                            // If it is the last line
                            firstNodeIndex = intersectionWithPrevious.order < Nodes[i][Nodes[i].Count - 1].order ? intersectionWithPrevious.order : Nodes[i][Nodes[i].Count - 1].order;
                            LastNodeIndex  = intersectionWithPrevious.order > Nodes[i][Nodes[i].Count - 1].order ? Nodes[i][Nodes[i].Count - 1].order : intersectionWithPrevious.order;
                        }
                        var tempNode = new List <OsmNode>();
                        // TODO
                        // If first and last are the same then the line is the last and is a circle, draw normally.
                        if (firstNodeIndex == LastNodeIndex)
                        {
                            // Draw normally

                            correctPath.Add(Nodes[i].ToArray());
                        }
                        else
                        {
                            var CirclePortion = new List <OsmNode>();
                            Nodes[i].Sort((m1, m2) => m1.order.CompareTo(m2.order));
                            int idx1 = Nodes[i].IndexOf(Nodes[i].Where(n => n.order == firstNodeIndex).FirstOrDefault());
                            int idx2 = Nodes[i].IndexOf(Nodes[i].Where(n => n.order == LastNodeIndex).FirstOrDefault());

                            for (int idx = idx1; i <= idx2; idx++)
                            {
                                CirclePortion.Add(Nodes[i][idx]);
                            }

                            correctPath.Add(CirclePortion.ToArray());
                        }
                    }
                    else if (isPrevCircle && !isReverse)
                    {
                        // Draw normally

                        correctPath.Add(Nodes[i].ToArray());
                    }
                    else if (!isPrevCircle && isReverse)
                    {
                        var rev = new OsmNode[Nodes[i].Count];
                        for (int revidx = 0; revidx < rev.Length; revidx++)
                        {
                            rev[revidx] = Nodes[i][rev.Length - revidx - 1];
                        }

                        correctPath.Add(rev);
                    }
                    else
                    {
                        // It is not a reversed line, nor it is a circle or a previous is a circle
                    }
                }
            }
            List <OsmNode> result = new List <OsmNode>();

            foreach (var w in correctPath)
            {
                result.AddRange(w);
            }
            if (correction == RouteCorrection.RemoveDuplicates)
            {
                // Remove immediate duplicates
                List <OsmNode> duplicateFree = new List <OsmNode>();
                duplicateFree.Add(result[0]);
                foreach (var w in result)
                {
                    if (!duplicateFree[duplicateFree.Count - 1].EqualsByGeoPosition(w))
                    {
                        duplicateFree.Add(w);
                    }
                }
                result = duplicateFree;
            }
            return(result);
        }
Пример #2
0
        /// <summary>
        /// Gets the route path of an OSM route.
        /// </summary>
        /// <param name="routeId">The osm id of the route(relation)</param>
        /// <param name="memberType">The type of members to retrieve (This parameter is currently not used.).</param>
        /// <param name="connectionString">The connection string of the database</param>
        /// <returns>Return a list of nodes</returns>
        /// <seealso cref="GetRoutePath"/>
        public static List <OsmNode> GetRoutePathExperimental(string routeId, int memberType, String connectionString)
        {
            Aram.OSMParser.Relation rel = new Aram.OSMParser.Relation(routeId);
            var            membersTemp  = rel.GetMembersPostgreSQL(connectionString);
            List <OsmNode> nodesTemp    = new List <OsmNode>();
            // Getting ways
            var mt2 = membersTemp.Where(mt => mt.Type == 1).ToList();
            // Exclude areas
            List <Member> tempWayList = new List <Member>();
            Tag           AreaTag     = new Tag()
            {
                KeyValueSQL = new string[] { "area", "yes" }
            };


            foreach (var m in mt2)
            {
                Aram.OSMParser.Way w = new Aram.OSMParser.Way(m.ReferenceId);
                var tags             = w.GetTagsStockholmPostgreSQL(connectionString);

                if (tags.Where(wt => wt.KeyValueSQL[0] == AreaTag.KeyValueSQL[0] && wt.KeyValueSQL[1] == AreaTag.KeyValueSQL[1]).Count() == 0)
                {
                    tempWayList.Add(m);
                }
            }
            mt2 = tempWayList;

            Aram.OSMParser.Way wtemp = new Aram.OSMParser.Way();

            var AllWaysNodes = mt2.Select(
                wt => wtemp.GetNodesPostgreSQL(wt.ReferenceId, connectionString).ToArray()).ToArray();


            for (int workit = 0; workit < mt2.Count; workit++)
            {
                //var currentLine = GlobalSimulationPlannerBaseClass.client
                //	.GetWayNodes(mt2[workit].ReferenceId, wcfCon).ToArray();
                var currentLine = AllWaysNodes[workit];

                if (workit > 1)
                {
                    if (nodesTemp[nodesTemp.Count - 1].PositionSQL.Lat == currentLine[0].PositionSQL.Lat &&
                        nodesTemp[nodesTemp.Count - 1].PositionSQL.Lon == currentLine[0].PositionSQL.Lon)
                    {
                        nodesTemp.AddRange(currentLine);
                    }
                    else
                    {
                        var rev = new OsmNode[currentLine.Length];
                        for (int revidx = 0; revidx < rev.Length; revidx++)
                        {
                            rev[revidx] = currentLine[rev.Length - revidx - 1];
                        }
                        nodesTemp.AddRange(rev);
                        //Debug.Log(mt2[workit].ReferenceId + " Reverse!");
                    }
                }
                else if (workit == 1)
                {
                    if (nodesTemp[nodesTemp.Count - 1].PositionSQL.Lat == currentLine[0].PositionSQL.Lat &&
                        nodesTemp[nodesTemp.Count - 1].PositionSQL.Lon == currentLine[0].PositionSQL.Lon)
                    {
                        nodesTemp.AddRange(currentLine);
                        // Add the line normally.
                    }
                    else if (nodesTemp[0].PositionSQL.Lat == currentLine[currentLine.Length - 1].PositionSQL.Lat &&
                             nodesTemp[0].PositionSQL.Lon == currentLine[currentLine.Length - 1].PositionSQL.Lon)
                    {
                        // Reverse the first line
                        var rev = new OsmNode[nodesTemp.Count];
                        for (int revidx = 0; revidx < rev.Length; revidx++)
                        {
                            rev[revidx] = nodesTemp[rev.Length - revidx - 1];
                        }
                        nodesTemp.Clear();
                        nodesTemp.AddRange(rev);
                        nodesTemp.AddRange(currentLine);
                    }
                    else
                    {
                        // Reverse the current line
                        var rev = new OsmNode[currentLine.Length];
                        for (int revidx = 0; revidx < rev.Length; revidx++)
                        {
                            rev[revidx] = currentLine[rev.Length - revidx - 1];
                        }
                        nodesTemp.AddRange(rev);
                    }
                }
                else
                {
                    nodesTemp.AddRange(currentLine);
                }
            }

            return(nodesTemp);
        }