///<summary> /// Gets the list of <see cref="OsmNode"/> elements for the given way id from the original OSM data on the database. /// <strong>Note:</strong>The connection will not be closed after the process is done. /// </summary> /// <param name="wayId">The way id to look for</param> /// <param name="con"> The connection to the database. Please refer to .Net Data Provider for PostgreSql for format specifications</param> /// <returns>Returns a list of <see cref="OsmNode"/>s that is ordered node sequence.</returns> public List <OsmNode> GetNodesPostgreSQL(String wayId, NpgsqlConnection con) { Way temp = new Way(); List <OsmNode> NodesSQLtemp = new List <OsmNode>(); NpgsqlCommand com = new NpgsqlCommand("", con); com.CommandText = "select wayId,nodeId,Latitude,Longitude,sort from waynodeinfoaram_cachedfromview where wayId='" + wayId + "' order by sort"; // com.CommandText = "select wayId,nodeId,Latitude,Longitude,sort from viewWayNodeInfoAram where wayId='" + wayId + "' order by sort"; NpgsqlDataReader reader = com.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { OsmNode tempNode = new OsmNode(); tempNode.id = reader["nodeId"].ToString(); tempNode.PositionSQL = new GeoPosition((int)reader["Latitude"] / scale, (int)reader["Longitude"] / scale); tempNode.order = int.Parse(reader["sort"].ToString(), CultureInfo.InvariantCulture); NodesSQLtemp.Add(tempNode); } if (!reader.IsClosed) { reader.Close(); } return(NodesSQLtemp); } else { if (!reader.IsClosed) { reader.Close(); } return(null); } }
/// <summary> /// Checks whether <paramref name="nodes"/> contain <paramref name="targetNode"/>. /// </summary> /// <param name="nodes">The list of OsmNode elements</param> /// <param name="targetNode">The seeking OsmNode.</param> /// <returns></returns> public static bool ContainsOsmNodeById(this List <OsmNode> nodes, OsmNode targetNode) { foreach (var n in nodes) { if (n.EqualsById(targetNode)) { return(true); } } return(false); }
public List <OsmNode> GetNodesSQL(String wayId, String connectionString) { Way temp = new Way(); List <OsmNode> NodesSQLtemp = new List <OsmNode>(); SqlConnection con = new SqlConnection(connectionString); con.Open(); SqlCommand com = new SqlCommand("", con); com.CommandText = "select wayId,nodeId,Latitude,Longitude,sort from WayNodeInfoAram where wayId='" + wayId + "' order by sort"; SqlDataReader reader = com.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { OsmNode tempNode = new OsmNode(); tempNode.id = reader["nodeId"].ToString(); tempNode.PositionSQL = new GeoPosition((double)reader["Latitude"], (double)reader["Longitude"]); tempNode.order = int.Parse(reader["sort"].ToString(), CultureInfo.InvariantCulture); NodesSQLtemp.Add(tempNode); } if (!reader.IsClosed) { reader.Close(); } con.Close(); return(NodesSQLtemp); } else { if (!reader.IsClosed) { reader.Close(); } con.Close(); return(null); } }
/// <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); }
/// <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); }
/// <summary> /// Compares two OsmNode objects by id property. /// </summary> /// <param name="node">The first node</param> /// <param name="node2">The seconds node</param> /// <returns></returns> public static bool EqualsById(this OsmNode node, OsmNode node2) { return(node.id == node2.id); }
/// <summary> /// Compares two OsmNode objects by PositionSQL property. /// </summary> /// <param name="node">The first node</param> /// <param name="node2">The seconds node</param> /// <returns></returns> public static bool EqualsByGeoPosition(this OsmNode node, OsmNode node2) { return(node.PositionSQL.EqualsManual(node2.PositionSQL)); }