Compare commits
112 Commits
2776db2ff8
...
41b73081a5
Author | SHA1 | Date | |
---|---|---|---|
41b73081a5 | |||
c16452068c | |||
db6d6ccaef | |||
7e1d03abf7 | |||
cb7500a4fa | |||
94234b3498 | |||
f1c7ff4b47 | |||
cc48016874 | |||
6db8278581 | |||
3770ff9b57 | |||
4c0a3edd4a | |||
32a9f8afa6 | |||
413052e031 | |||
8f42c34b97 | |||
f6d55c7f3e | |||
c67bb94e30 | |||
903958a22a | |||
5f9b41753c | |||
d677214573 | |||
246ba9d182 | |||
adda057b88 | |||
3498fe5ae3 | |||
6d338018b5 | |||
a4ebf05d7a | |||
23bab6a593 | |||
a971e4ed6c | |||
f2cf676c31 | |||
a1fb19a080 | |||
fcae3e5be2 | |||
88ed5472a8 | |||
b88e1a8dfc | |||
4930423cb5 | |||
485f04e6a2 | |||
12d7f9b78c | |||
d23cf87dd4 | |||
f50961d37c | |||
1ade0ce1af | |||
a1e3a60c48 | |||
7e8d8e2a74 | |||
681cb25ecf | |||
2cae5539b5 | |||
4f65e2ea8d | |||
7c3b9a4e71 | |||
bd06937b55 | |||
77bc712eba | |||
13dd052c3d | |||
569b10cc8a | |||
f4d2e3dacd | |||
04979c5159 | |||
559e26891e | |||
97d3cc8af9 | |||
e212aeef0d | |||
e0f17c1953 | |||
69a97d628f | |||
2d7b13181e | |||
8942dc5e35 | |||
52254de1aa | |||
f38f7f4c87 | |||
db7ca6141a | |||
48090b3cbd | |||
f9e90663bb | |||
a700d429d4 | |||
5a33c29259 | |||
bced45f688 | |||
d76a9baf3a | |||
f2db3e5395 | |||
b38f99670f | |||
04cef8c328 | |||
da80e74cae | |||
aa9f5a1bad | |||
6eae4df1f3 | |||
1384abfaf2 | |||
d29ab7e01e | |||
66f4641fb7 | |||
31a61b3000 | |||
cfaaeceb27 | |||
44511beb02 | |||
f6d5fe5905 | |||
0760803685 | |||
c27d5094a5 | |||
2b3a1bb5bc | |||
7c61d9565b | |||
702ce6f1fb | |||
a5d50a7174 | |||
1de8133489 | |||
7b6b17519e | |||
dd19505dbb | |||
665d9d83b8 | |||
7a39b31761 | |||
7e881c1360 | |||
74ca9a3435 | |||
6a66ea9f63 | |||
e3fd034590 | |||
29eef71d4a | |||
f30cef46c9 | |||
958913d3d2 | |||
9977031578 | |||
08885de1c0 | |||
7babf63a6c | |||
6b78fdbf6a | |||
63fd6ff8fc | |||
04a032aa0c | |||
30931cd202 | |||
3a696b5ca7 | |||
33790cb021 | |||
9d3b580a19 | |||
119c9edf43 | |||
0e4faef6a4 | |||
69ed5e35e7 | |||
05ad938ec7 | |||
d69557481b | |||
b946dae68f |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
**/bin
|
||||||
|
**/obj
|
||||||
|
**/.vs
|
31
Executable/Executable.csproj
Normal file
31
Executable/Executable.csproj
Normal 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
80
Executable/Program.cs
Normal 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");
|
||||||
|
}
|
13
astar/.idea/.idea.astar/.idea/.gitignore
vendored
Normal file
13
astar/.idea/.idea.astar/.idea/.gitignore
vendored
Normal 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
|
4
astar/.idea/.idea.astar/.idea/encodings.xml
Normal file
4
astar/.idea/.idea.astar/.idea/encodings.xml
Normal 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>
|
10
astar/.idea/.idea.astar/.idea/indexLayout.xml
Normal file
10
astar/.idea/.idea.astar/.idea/indexLayout.xml
Normal 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>
|
7
astar/.idea/.idea.astar/.idea/vcs.xml
Normal file
7
astar/.idea/.idea.astar/.idea/vcs.xml
Normal 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
240
astar/Astar.cs
Normal 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
61
astar/Graph.cs
Normal 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
14
astar/Node.cs
Normal 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
57
astar/Route.cs
Normal 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
27
astar/astar.csproj
Normal 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
31
astar/astar.sln
Normal 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
|
8
astar/astar.sln.DotSettings.user
Normal file
8
astar/astar.sln.DotSettings.user
Normal 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>
|
Loading…
Reference in New Issue
Block a user