Compare commits

...

112 Commits

Author SHA1 Message Date
41b73081a5 Prepare Merge 2024-07-22 05:01:41 +02:00
c16452068c Updated to new Structure of regions 2024-07-22 04:56:22 +02:00
db6d6ccaef Upgrade to .net 8 2024-07-19 17:59:19 +02:00
7e1d03abf7
Update README.md 2022-11-18 01:02:25 +01:00
cb7500a4fa Merge branch 'main' of https://github.com/C9Glax/astar 2022-11-17 20:39:54 +01:00
94234b3498 Package "Graph" renamed to "GeoGraph" 2022-11-17 20:39:50 +01:00
f1c7ff4b47 combined warnings #debug 2022-11-17 20:36:08 +01:00
cc48016874 Removed unreachable state and added check to remove duplicate entries in toVisit 2022-11-17 20:33:21 +01:00
6db8278581
Update README.md 2022-11-13 16:58:16 +01:00
3770ff9b57 error 2022-11-13 16:55:22 +01:00
4c0a3edd4a Merge branch 'main' of https://github.com/C9Glax/astar 2022-11-13 16:53:06 +01:00
32a9f8afa6 Added launch args 2022-11-13 16:53:03 +01:00
413052e031
Update README.md 2022-11-13 16:38:34 +01:00
8f42c34b97
Update README.md 2022-11-13 16:37:27 +01:00
f6d55c7f3e
Merge pull request #10 from C9Glax/Importer-Split
Importer split
2022-11-13 16:34:03 +01:00
c67bb94e30 readme update 2022-11-13 16:33:31 +01:00
903958a22a
Merge pull request #9 from C9Glax/dev
Merge before Project Split
2022-11-13 16:10:38 +01:00
5f9b41753c
Merge pull request #8 from C9Glax/DatastructureAndAlgoChange
Structure Change
2022-11-13 16:08:36 +01:00
d677214573 Moved Projects 2022-11-13 15:29:31 +01:00
246ba9d182 Added log 2022-11-13 15:03:35 +01:00
adda057b88 removed duplicate 2022-11-13 14:59:06 +01:00
3498fe5ae3 Changed protection of Graph.nodes to private 2022-11-13 14:19:07 +01:00
6d338018b5 Null pointer fixes 2022-11-13 14:14:55 +01:00
a4ebf05d7a Initial change 2022-11-13 14:02:27 +01:00
23bab6a593 Changed distance back to double 2022-11-13 13:21:24 +01:00
a971e4ed6c GetEdgeToNode Nullable 2022-11-03 19:35:04 +01:00
f2cf676c31 Added "Route" 2022-11-03 19:14:14 +01:00
a1fb19a080 distance and time import 2022-11-03 19:14:07 +01:00
fcae3e5be2 Changed Distance to meters 2022-11-03 19:13:53 +01:00
88ed5472a8 timeSpent -> TimeRequired 2022-11-03 19:13:38 +01:00
b88e1a8dfc Added Distance 2022-11-03 19:13:26 +01:00
4930423cb5 Removed unessecary duplication of graph 2022-11-03 18:21:13 +01:00
485f04e6a2 More logging 2022-11-03 18:16:53 +01:00
12d7f9b78c pathLength => Timespent 2022-11-02 18:09:30 +01:00
d23cf87dd4 Nullable Node 2022-11-02 18:07:22 +01:00
f50961d37c
Merge pull request #7 from C9Glax/temp
dev
2022-11-01 16:08:38 +01:00
1ade0ce1af Added id for future use 2022-11-01 05:09:17 +01:00
a1e3a60c48 Added id for future use 2022-11-01 05:09:01 +01:00
7e8d8e2a74 Different Call 2022-11-01 05:08:52 +01:00
681cb25ecf Streamlined pathfinding 2022-11-01 05:08:09 +01:00
2cae5539b5 Improved Import for less memory Usage 2022-11-01 03:52:23 +01:00
4f65e2ea8d Changed Waystructure 2022-11-01 02:02:38 +01:00
7c3b9a4e71 refactor 2022-10-31 23:10:42 +01:00
bd06937b55 Readkey 2022-10-31 23:10:33 +01:00
77bc712eba double to float 2022-10-31 23:10:28 +01:00
13dd052c3d Update Readme 2022-05-11 22:25:09 +02:00
569b10cc8a Update readme 2022-05-11 22:24:12 +02:00
f4d2e3dacd
Merge pull request #6 from C9Glax/dev
Speed Improvements and Bugfixes
2022-05-11 22:21:58 +02:00
04979c5159 Changed Logging 2022-05-11 22:18:33 +02:00
559e26891e Added more logging,
Fixed map loading
2022-05-11 22:18:13 +02:00
97d3cc8af9 Fixed Comparer (was sorting largest to smallest),
Added second check to ensure shortest path
2022-05-11 22:17:44 +02:00
e212aeef0d Rewrote Edge-adding 2022-05-11 21:30:54 +02:00
e0f17c1953 Added custom-file functionality 2022-05-11 21:13:33 +02:00
69a97d628f Fixed missing nodes on import 2022-05-11 21:04:43 +02:00
2d7b13181e
Merge pull request #5 from C9Glax/dev
Improved route calculation and import
2022-05-11 20:42:33 +02:00
8942dc5e35 Improved Importer:
Only junctions are imported
2022-05-11 20:41:47 +02:00
52254de1aa Intellisense 2022-05-11 20:25:13 +02:00
f38f7f4c87 changed weight calculation based on waytype 2022-05-11 20:13:19 +02:00
db7ca6141a
Merge pull request #4 from C9Glax/dev
Capitalzation
2022-05-11 20:00:30 +02:00
48090b3cbd
Merge branch 'main' into dev 2022-05-11 20:00:23 +02:00
f9e90663bb Catchup with bced45f688 2022-05-11 19:49:49 +02:00
a700d429d4 Update with 0ad913e54b 2022-05-11 19:45:35 +02:00
5a33c29259
Merge pull request #3 from C9Glax/dev
Logging to Separate Project
2022-05-11 19:05:38 +02:00
bced45f688 Moved Logging to https://github.com/C9Glax/Logging 2022-05-11 19:04:42 +02:00
d76a9baf3a Moved Logging to https://github.com/C9Glax/Logging 2022-05-11 19:04:15 +02:00
f2db3e5395
Update README.md 2022-05-06 01:02:33 +02:00
b38f99670f Merge branch 'main' of https://github.com/C9Glax/astar 2022-05-06 00:58:28 +02:00
04cef8c328 Release 0.1 2022-05-06 00:58:16 +02:00
da80e74cae
Merge pull request #2 from C9Glax/dev
dev branch test
2022-05-06 00:50:18 +02:00
aa9f5a1bad test revert 2022-05-06 00:49:41 +02:00
6eae4df1f3 test 2022-05-06 00:49:16 +02:00
1384abfaf2 Optional Logger 2022-05-06 00:47:57 +02:00
d29ab7e01e Relocated Import 2022-05-06 00:40:58 +02:00
66f4641fb7 supress warning 2022-05-06 00:40:45 +02:00
31a61b3000 Short Type 2022-05-06 00:32:45 +02:00
cfaaeceb27 reader close 2022-05-06 00:31:35 +02:00
44511beb02 Added pathlength to goaldistance criteria 2022-05-06 00:31:26 +02:00
f6d5fe5905 Implementation of A* 2022-05-06 00:02:28 +02:00
0760803685 Fixed missing node-import, Changed loglevels 2022-05-06 00:02:10 +02:00
c27d5094a5 Fixed Debug levels 2022-05-06 00:01:23 +02:00
2b3a1bb5bc changed weight factor to double 2022-05-06 00:01:02 +02:00
7c61d9565b Fixed level 2022-05-05 23:47:15 +02:00
702ce6f1fb Added loglevel VERBOSE 2022-05-05 23:45:21 +02:00
a5d50a7174 supress issue 2022-05-05 16:32:45 +02:00
1de8133489 value might not return 2022-05-05 16:32:34 +02:00
7b6b17519e Graph fix 2022-05-05 16:32:19 +02:00
dd19505dbb Removed from Logging 2022-05-05 16:29:02 +02:00
665d9d83b8 Intermedite 2022-05-05 16:28:45 +02:00
7a39b31761 Revert "removed weight from info"
This reverts commit 7e881c1360.
2022-05-05 16:26:15 +02:00
7e881c1360 removed weight from info 2022-05-05 16:26:00 +02:00
74ca9a3435 added space 2022-05-05 16:25:42 +02:00
6a66ea9f63 intermediate 2022-05-05 16:23:00 +02:00
e3fd034590 Refactored Graph and Importer into separate projects 2022-05-05 16:12:40 +02:00
29eef71d4a return 2022-05-05 16:02:49 +02:00
f30cef46c9 Added Logging Levels 2022-05-05 16:00:56 +02:00
958913d3d2 Importer 2022-05-05 15:49:28 +02:00
9977031578 Added replace functionality 2022-05-05 15:49:19 +02:00
08885de1c0 Placed Importer in different class 2022-05-05 15:48:45 +02:00
7babf63a6c removed using Directive 2022-05-05 14:46:04 +02:00
6b78fdbf6a ignoring .vs 2022-05-05 14:45:20 +02:00
63fd6ff8fc Ignoring obj bin .vs 2022-05-05 14:44:06 +02:00
04a032aa0c .gitignore 2022-05-05 14:40:54 +02:00
30931cd202 branch merge 2022-05-05 14:37:54 +02:00
3a696b5ca7 b 2022-05-05 14:36:29 +02:00
33790cb021
Merge pull request #1 from C9Glax/master
Master
2022-05-05 02:01:41 +02:00
9d3b580a19 Logging to Console or File 2022-05-05 02:01:05 +02:00
119c9edf43 Loading Xml from Ressourcefile 2022-05-05 02:00:55 +02:00
0e4faef6a4 Executable Console 2022-05-05 02:00:38 +02:00
69ed5e35e7 vs 2022-05-05 02:00:18 +02:00
05ad938ec7 init 2022-05-05 01:33:56 +02:00
d69557481b init 2022-05-05 01:33:29 +02:00
b946dae68f
Initial commit 2022-05-05 01:20:54 +02:00
14 changed files with 586 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
**/bin
**/obj
**/.vs

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\astar\astar.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GlaxArguments" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Graph">
<HintPath>..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\Graph.dll</HintPath>
</Reference>
<Reference Include="OSM_Graph">
<HintPath>..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\OSM_Graph.dll</HintPath>
</Reference>
<Reference Include="OSM_Regions">
<HintPath>..\..\OSM_Regions\OSM_Regions\bin\Debug\net8.0\OSM_Regions.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

80
Executable/Program.cs Normal file
View File

@ -0,0 +1,80 @@
using System.Diagnostics;
using System.Globalization;
using astar;
using GlaxArguments;
using GlaxLogger;
using Microsoft.Extensions.Logging;
using OSM_Regions;
Logger logger = new(LogLevel.Debug, consoleOut: Console.Out);
Argument pathArg = new (["-p", "--path"], 1, "Path to OSM-XML-File");
Argument regionArg = new (["-r", "--regionSize"], 1, "Region-Size");
Argument importPathArg = new (["-i", "--importPath"], 1, "Region-Directory");
Argument routeCoordinateArg = new(["-c", "--route", "--coordinates"], 4, "Start and end coordinates");
ArgumentFetcher af = new ([pathArg, regionArg, importPathArg, routeCoordinateArg]);
Dictionary<Argument, string[]> arguments = af.Fetch(args);
if (!arguments.ContainsKey(regionArg))
{
PrintUsage();
return;
}
if (!float.TryParse(arguments[regionArg][0], NumberFormatInfo.InvariantInfo, out float regionSize))
{
logger.LogError($"Failed to parse region Size from input w{arguments[regionArg][0]}");
return;
}
if (!arguments.ContainsKey(routeCoordinateArg))
{
PrintUsage();
return;
}
if (!float.TryParse(arguments[routeCoordinateArg][0], NumberFormatInfo.InvariantInfo, out float startLat) ||
!float.TryParse(arguments[routeCoordinateArg][1], NumberFormatInfo.InvariantInfo, out float startLon) ||
!float.TryParse(arguments[routeCoordinateArg][2], NumberFormatInfo.InvariantInfo, out float endLat) ||
!float.TryParse(arguments[routeCoordinateArg][3], NumberFormatInfo.InvariantInfo, out float endLon) )
{
logger.LogError($"Failed to parse start/end coordinates.");
return;
}
string? importPath = null;
if (arguments.TryGetValue(importPathArg, out string[]? importPathVal))
{
importPath = importPathVal[0];
}
if (arguments.TryGetValue(pathArg, out string[]? pathValue))
{
if(!File.Exists(pathValue[0]))
{
logger.LogError($"File doesn't exist {pathValue[0]}");
PrintUsage();
return;
}
Converter converter = new (regionSize, importPath, logger: logger);
converter.SplitOsmExportIntoRegionFiles(pathValue[0]);
}
Route route = Astar.FindPath(startLat, startLon, endLat, endLon, regionSize, importPath, logger);
if(route.RouteFound)
Console.WriteLine($"{string.Join("\n", route.Steps)}\n" +
$"Distance: {route.Distance:000000.00}m");
else
Console.WriteLine("No route found.");
Console.WriteLine($"Visited Nodes: {route.Graph.Nodes.Values.Count(node => node.Previous is not null)}");
void PrintUsage()
{
Console.WriteLine($"Usage: {Process.GetCurrentProcess().MainModule?.FileName} <-r regionSize> <-c startLat startLon endLat endLon> <options>\n" +
$"Options:\n" +
$"\t-h onlyHighways\n" +
$"\t-p Path to OSM-XML file to split into regions");
}

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/.idea.astar.iml
/contentModel.xml
/modules.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders>
<Path>../../astar</Path>
</attachedFolders>
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

240
astar/Astar.cs Normal file
View File

@ -0,0 +1,240 @@
using Microsoft.Extensions.Logging;
using Graph.Utils;
using OSM_Regions;
namespace astar
{
public static class Astar
{
public static Route FindPath(float startLat, float startLon, float endLat, float endLon, float regionSize, string? importFolderPath = null,
ILogger? logger = null)
{
RegionLoader rl = new(regionSize, importFolderPath, logger: logger);
Graph graph = Spiral(rl, startLat, startLon, regionSize);
KeyValuePair<ulong, Node> startNode = graph.ClosestNodeToCoordinates(startLat, startLon);
startNode.Value.PreviousIsFromStart = true;
startNode.Value.Previous = new KeyValuePair<ulong, float>(startNode.Key, 0f);
Graph endRegion = Spiral(rl, endLat, endLon, regionSize);
graph.ConcatGraph(endRegion);
KeyValuePair<ulong, Node> endNode = graph.ClosestNodeToCoordinates(endLat, endLon);
endNode.Value.PreviousIsFromStart = false;
endNode.Value.Previous = new KeyValuePair<ulong, float>(endNode.Key, 0f);
logger?.Log(LogLevel.Information,
"From {0:00.00000}#{1:000.00000} to {2:00.00000}#{3:000.00000} Great-Circle {4:00000.00}km",
startNode.Value.Lat, startNode.Value.Lon, endNode.Value.Lat, endNode.Value.Lon,
NodeUtils.DistanceBetween(startNode.Value, endNode.Value) / 1000);
PriorityQueue<ulong, double> toVisitStart = new();
toVisitStart.Enqueue(startNode.Key, NodeUtils.DistanceBetween(startNode.Value, endNode.Value));
PriorityQueue<ulong, double> toVisitEnd = new();
toVisitEnd.Enqueue(endNode.Key, NodeUtils.DistanceBetween(endNode.Value, startNode.Value));
while (toVisitStart.Count > 0 && toVisitEnd.Count > 0)
{
logger?.LogDebug($"Length toVisit-Start: {toVisitStart.Count} -End: {toVisitEnd.Count}");
/*
* FROM START
*/
ulong currentNodeStartId = toVisitStart.Dequeue();
Node? currentNodeStart;
if (!graph.ContainsNode(currentNodeStartId))
{
Graph? newRegion = Graph.FromGraph(rl.LoadRegionFromNodeId(currentNodeStartId));
if (newRegion is null)
{
logger?.LogError($"Could not load Region for Node {currentNodeStartId}");
currentNodeStart = null;
}
else
{
graph.ConcatGraph(newRegion);
currentNodeStart = graph.Nodes[currentNodeStartId];
}
}
else
currentNodeStart = graph.Nodes[currentNodeStartId];
logger?.LogTrace($"Current Node Start: {currentNodeStartId} {currentNodeStart}");
if (currentNodeStart is not null)
{
foreach ((ulong nodeId, ulong wayId) in currentNodeStart.Neighbors)
{
//TODO checks for way-stuff
Node? neighbor;
if (!graph.ContainsNode(nodeId))
{
Graph? newRegion = Graph.FromGraph(rl.LoadRegionFromNodeId(nodeId));
if (newRegion is null)
{
logger?.LogError($"Could not load Region for Node {nodeId}");
neighbor = null;
}
else
{
graph.ConcatGraph(newRegion);
neighbor = Node.FromGraphNode(graph.Nodes[nodeId]);
}
}
else
{
neighbor = graph.Nodes[nodeId];
}
if (neighbor is not null)
{
/*
* IMPORTANT SHIT BELOW
*/
if (neighbor.PreviousIsFromStart is false)//Check if we found the opposite End
return PathFound(graph, currentNodeStart, neighbor);
float distance = currentNodeStart.Previous!.Value.Value + (float)neighbor.DistanceTo(currentNodeStart);
if (neighbor.Previous is null || neighbor.Previous.Value.Value > distance)
{
neighbor.Previous = new KeyValuePair<ulong, float>(currentNodeStartId, distance);
neighbor.PreviousIsFromStart = true;
toVisitStart.Enqueue(nodeId, NodeUtils.DistanceBetween(neighbor, endNode.Value));
}
logger?.LogTrace($"Neighbor {nodeId} {neighbor}");
}
}
}
/*
* FROM END
*/
ulong currentNodeEndId = toVisitEnd.Dequeue();
Node? currentNodeEnd;
if (!graph.ContainsNode(currentNodeEndId))
{
Graph? newRegion = Graph.FromGraph(rl.LoadRegionFromNodeId(currentNodeEndId));
if (newRegion is null)
{
logger?.LogError($"Could not load Region for Node {currentNodeEndId}");
currentNodeEnd = null;
}
else
{
graph.ConcatGraph(newRegion);
currentNodeEnd = graph.Nodes[currentNodeEndId];
}
}
else
currentNodeEnd = graph.Nodes[currentNodeEndId];
logger?.LogTrace($"Current Node End: {currentNodeEndId} {currentNodeEnd}");
if (currentNodeEnd is not null)
{
foreach ((ulong nodeId, ulong wayId) in currentNodeEnd.Neighbors)
{
//TODO checks for way-stuff
Node? neighbor;
if (!graph.ContainsNode(nodeId))
{
Graph? newRegion = Graph.FromGraph(rl.LoadRegionFromNodeId(nodeId));
if (newRegion is null)
{
logger?.LogError($"Could not load Region for Node {nodeId}");
neighbor = null;
}
else
{
graph.ConcatGraph(newRegion);
neighbor = Node.FromGraphNode(graph.Nodes[nodeId]);
}
}
else
{
neighbor = graph.Nodes[nodeId];
}
if (neighbor is not null)
{
/*
* IMPORTANT SHIT BELOW
*/
if (neighbor.PreviousIsFromStart is true)//Check if we found the opposite End
return PathFound(graph, neighbor, currentNodeEnd);
float distance = currentNodeEnd.Previous!.Value.Value + (float)neighbor.DistanceTo(currentNodeEnd);
if (neighbor.Previous is null || neighbor.Previous.Value.Value > distance)
{
neighbor.Previous = new KeyValuePair<ulong, float>(currentNodeEndId, distance);
neighbor.PreviousIsFromStart = false;
toVisitEnd.Enqueue(nodeId, NodeUtils.DistanceBetween(neighbor, startNode.Value));
}
logger?.LogTrace($"Neighbor {nodeId} {neighbor}");
}
}
}
}
return new Route(graph, Array.Empty<Step>().ToList(), false);
}
private static Route PathFound(Graph graph, Node fromStart, Node fromEnd)
{
List<Step> path = new();
Node current = fromStart;
while (current.Previous is not null && current.Previous.Value.Value == 0f)
{
Step step = new((float)NodeUtils.DistanceBetween(graph.Nodes[current.Previous.Value.Key], current), graph.Nodes[current.Previous.Value.Key], current);
path.Add(step);
current = graph.Nodes[current.Previous.Value.Key];
}
path.Reverse();//Since we go from the middle backwards until here
path.Add(new Step((float)NodeUtils.DistanceBetween(fromStart, fromEnd), fromStart, fromEnd));
current = fromEnd;
while (current.Previous is not null && current.Previous.Value.Value == 0f)
{
Step step = new((float)NodeUtils.DistanceBetween(graph.Nodes[current.Previous.Value.Key], current), current, graph.Nodes[current.Previous.Value.Key]);
path.Add(step);
current = graph.Nodes[current.Previous.Value.Key];
}
return new Route(graph, path, true);
}
private static Graph Spiral(RegionLoader loader, float lat, float lon, float regionSize)
{
Graph? ret = Graph.FromGraph(loader.LoadRegionFromCoordinates(lat, lon));
int iteration = 1;
while (ret is null)
{
for (int x = -iteration; x <= iteration; x++)
{
Graph? g1 = Graph.FromGraph(loader.LoadRegionFromCoordinates(lat + x * regionSize, lon - iteration * regionSize));
Graph? g2 = Graph.FromGraph(loader.LoadRegionFromCoordinates(lat + x * regionSize, lon + iteration * regionSize));
if (ret is not null)
{
ret.ConcatGraph(g1);
ret.ConcatGraph(g2);
}
else if (ret is null && g1 is not null)
{
ret = g1;
ret.ConcatGraph(g2);
}else if (ret is null && g2 is not null)
ret = g2;
}
for (int y = -iteration + 1; y < iteration; y++)
{
Graph? g1 = Graph.FromGraph(loader.LoadRegionFromCoordinates(lat - iteration * regionSize, lon + y * regionSize));
Graph? g2 = Graph.FromGraph(loader.LoadRegionFromCoordinates(lat + iteration * regionSize, lon + y * regionSize));
if (ret is not null)
{
ret.ConcatGraph(g1);
ret.ConcatGraph(g2);
}
else if (ret is null && g1 is not null)
{
ret = g1;
ret.ConcatGraph(g2);
}else if (ret is null && g2 is not null)
ret = g2;
}
iteration++;
}
return ret;
}
}
}

61
astar/Graph.cs Normal file
View File

@ -0,0 +1,61 @@
using Graph;
namespace astar;
public class Graph
{
public readonly Dictionary<ulong, Node> Nodes = new();
public readonly Dictionary<ulong, Way> Ways = new ();
public static Graph? FromGraph(global::Graph.Graph? graph)
{
if (graph is null)
return null;
Graph ret = new();
foreach ((ulong id, global::Graph.Node? node) in graph.Nodes)
ret.Nodes.Add(id, Node.FromGraphNode(node));
foreach ((ulong id, Way? way) in graph.Ways)
ret.Ways.Add(id, way);
return ret;
}
public void ConcatGraph(Graph? graph)
{
if (graph is null)
return;
foreach ((ulong id, Node n) in graph.Nodes)
this.Nodes.TryAdd(id, n);
foreach ((ulong id, Way w) in graph.Ways)
this.Ways.TryAdd(id, w);
}
public bool ContainsNode(Node node)
{
return Nodes.ContainsValue(node);
}
public bool ContainsNode(ulong nodeId)
{
return Nodes.ContainsKey(nodeId);
}
public bool ContainsWay(Way way)
{
return Ways.ContainsValue(way);
}
public bool ContainsWay(ulong wayId)
{
return Ways.ContainsKey(wayId);
}
public KeyValuePair<ulong, Node> ClosestNodeToCoordinates(float lat, float lon)
{
return Nodes.MinBy(n => n.Value.DistanceTo(lat, lon));
}
public override string ToString()
{
return $"Graph {Nodes.Count} Nodes {Ways.Count} Ways.";
}
}

14
astar/Node.cs Normal file
View File

@ -0,0 +1,14 @@
namespace astar;
public class Node(float lat, float lon, Dictionary<ulong, ulong>? neighbors = null) : global::Graph.Node(lat, lon, neighbors)
{
public KeyValuePair<ulong, float>? Previous = null;
public bool? PreviousIsFromStart = null;
public static Node FromGraphNode(global::Graph.Node node) => new (node.Lat, node.Lon, node.Neighbors);
public override string ToString()
{
return $"{Lat:00.000000} {Lon:000.000000} Previous {Previous?.Key} {(PreviousIsFromStart is not null ? PreviousIsFromStart.Value ?"Start":"End" : null)}";
}
}

57
astar/Route.cs Normal file
View File

@ -0,0 +1,57 @@
namespace astar
{
public class Route(Graph graph, List<Step> steps, bool routeFound)
{
public Graph Graph { get; } = graph;
public List<Step> Steps { get; } = steps;
public bool RouteFound { get; } = routeFound;
public float Distance => Steps.Sum(step => step.Distance);
public KeyValuePair<float, float> MinCoordinates()
{
float minLat, minLon;
if (RouteFound)
{
Step minLatStep = Steps.MinBy(step => step.Node1.Lat < step.Node2.Lat ? step.Node1.Lat : step.Node2.Lat);
Step minLonStep = Steps.MinBy(step => step.Node1.Lon < step.Node2.Lon ? step.Node1.Lon : step.Node2.Lon);
minLat = minLatStep.Node1.Lat < minLatStep.Node2.Lat ? minLatStep.Node1.Lat : minLatStep.Node2.Lat;
minLon = minLonStep.Node1.Lon < minLonStep.Node2.Lon ? minLonStep.Node1.Lon : minLonStep.Node2.Lon;
}
else
{
minLat = Graph.Nodes.MinBy(node => node.Value.Lat).Value.Lat;
minLon = Graph.Nodes.MinBy(node => node.Value.Lon).Value.Lon;
}
return new KeyValuePair<float, float>(minLat, minLon);
}
public KeyValuePair<float, float> MaxCoordinates()
{
float maxLat, maxLon;
if (RouteFound)
{
Step maxLatStep = Steps.MaxBy(step => step.Node1.Lat > step.Node2.Lat ? step.Node1.Lat : step.Node2.Lat);
Step maxLonStep = Steps.MaxBy(step => step.Node1.Lon > step.Node2.Lon ? step.Node1.Lon : step.Node2.Lon);
maxLat = maxLatStep.Node1.Lat > maxLatStep.Node2.Lat ? maxLatStep.Node1.Lat : maxLatStep.Node2.Lat;
maxLon = maxLonStep.Node1.Lon > maxLonStep.Node2.Lon ? maxLonStep.Node1.Lon : maxLonStep.Node2.Lon;
}
else
{
maxLat = Graph.Nodes.MaxBy(node => node.Value.Lat).Value.Lat;
maxLon = Graph.Nodes.MaxBy(node => node.Value.Lon).Value.Lon;
}
return new KeyValuePair<float, float>(maxLat, maxLon);
}
}
public struct Step(float distance, Node node1, Node node2)
{
public readonly Node Node1 = node1, Node2 = node2;
public readonly float Distance = distance;
public override string ToString()
{
return $"{Node1.Lat:00.000000} {Node1.Lon:000.000000} --- {Distance:0000.00}m ---> {Node2.Lat:00.000000} {Node2.Lon:000.000000}";
}
}
}

27
astar/astar.csproj Normal file
View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GlaxLogger" Version="1.0.7.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Graph">
<HintPath>..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\Graph.dll</HintPath>
</Reference>
<Reference Include="OSM_Graph">
<HintPath>..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\OSM_Graph.dll</HintPath>
</Reference>
<Reference Include="OSM_Regions">
<HintPath>..\..\OSM_Regions\OSM_Regions\bin\Debug\net8.0\OSM_Regions.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

31
astar/astar.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32421.90
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "astar", "astar.csproj", "{4B7782F4-DE4B-424D-B46B-E7BC750D0838}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Executable", "..\Executable\Executable.csproj", "{9B311732-9631-480D-97A3-54823CC27CC8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4B7782F4-DE4B-424D-B46B-E7BC750D0838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B7782F4-DE4B-424D-B46B-E7BC750D0838}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B7782F4-DE4B-424D-B46B-E7BC750D0838}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B7782F4-DE4B-424D-B46B-E7BC750D0838}.Release|Any CPU.Build.0 = Release|Any CPU
{9B311732-9631-480D-97A3-54823CC27CC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B311732-9631-480D-97A3-54823CC27CC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B311732-9631-480D-97A3-54823CC27CC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B311732-9631-480D-97A3-54823CC27CC8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {056285B9-87B5-4757-AEBD-491F4A326AA9}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005CGeo_002DGraph_005CGeo_002DGraph_005Cbin_005CDebug_005Cnet6_002E0_005CGeo_002DGraph_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_002DXML_002DImporter_005COSM_002DXML_002DImporter_005Cbin_005CDebug_005Cnet8_002E0_005COSM_002DXML_002DImporter_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_005FGraph_005COSM_005FGraph_005Cbin_005CDebug_005Cnet8_002E0_005CGraph_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_005FGraph_005COSM_005FGraph_005Cbin_005CDebug_005Cnet8_002E0_005COSM_005FGraph_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_005FRegions_005COSM_005FRegions_005Cbin_005CDebug_005Cnet8_002E0_005CGraph_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_005FRegions_005COSM_005FRegions_005Cbin_005CDebug_005Cnet8_002E0_005COSM_005FGraph_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005COSM_005FRegions_005COSM_005FRegions_005Cbin_005CDebug_005Cnet8_002E0_005COSM_005FRegions_002Edll/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>