more type hinting, now in the route class

This commit is contained in:
Laura Klünder 2024-12-17 23:19:46 +00:00
parent 53070ef4f9
commit 29c8b01e33
2 changed files with 45 additions and 26 deletions

View file

@ -2,13 +2,16 @@
from collections import OrderedDict, deque from collections import OrderedDict, deque
from dataclasses import dataclass from dataclasses import dataclass
import typing from typing import TYPE_CHECKING, Sequence, Optional, Mapping
import numpy as np import numpy as np
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
if typing.TYPE_CHECKING: from c3nav.mapdata.models import Location
from c3nav.routing.router import Router from c3nav.routing.models import RouteOptions
if TYPE_CHECKING:
from c3nav.routing.router import Router, RouterLocation, RouterNodeAndEdge
def describe_location(location, locations): def describe_location(location, locations):
@ -23,9 +26,18 @@ def describe_location(location, locations):
return location return location
#@dataclass @dataclass
class Route: class Route:
router: "Router" router: "Router"
origin: "RouterLocation"
destination: "RouterLocation"
path_nodes: Sequence[int]
options: RouteOptions
origin_addition: Optional["RouterNodeAndEdge"]
destination_addition: Optional["RouterNodeAndEdge"]
origin_xyz: np.ndarray | None
destination_xyz: np.ndarray | None
visible_locations: Mapping[int, Location]
def __init__(self, router, origin, destination, path_nodes, options, def __init__(self, router, origin, destination, path_nodes, options,
origin_addition, destination_addition, origin_xyz, destination_xyz, origin_addition, destination_addition, origin_xyz, destination_xyz,

View file

@ -5,7 +5,7 @@ from collections import deque, namedtuple
from dataclasses import dataclass, field from dataclasses import dataclass, field
from functools import reduce from functools import reduce
from itertools import chain from itertools import chain
from typing import Optional, TypeVar, Generic, Mapping, Any, Sequence, TypeAlias, ClassVar from typing import Optional, TypeVar, Generic, Mapping, Any, Sequence, TypeAlias, ClassVar, NamedTuple
import numpy as np import numpy as np
from django.conf import settings from django.conf import settings
@ -33,7 +33,13 @@ except ImportError:
logger = logging.getLogger('c3nav') logger = logging.getLogger('c3nav')
NodeConnectionsByNode: TypeAlias = dict[int, tuple["RouterNode", "RouterEdge"] | tuple[None, None]]
class RouterNodeAndEdge(NamedTuple):
node: Optional["RouterNode"]
edge: Optional["RouterEdge"]
NodeConnectionsByNode: TypeAlias = dict[int, RouterNodeAndEdge]
PointCompatible: TypeAlias = Point | CustomLocation | CustomLocationProxyMixin PointCompatible: TypeAlias = Point | CustomLocation | CustomLocationProxyMixin
EdgeIndex: TypeAlias = tuple[int, int] EdgeIndex: TypeAlias = tuple[int, int]
@ -185,15 +191,15 @@ class Router:
for node in space_nodes: for node in space_nodes:
line = LineString([(node.x, node.y), (fallback_node.x, fallback_node.y)]) line = LineString([(node.x, node.y), (fallback_node.x, fallback_node.y)])
if line.length < 5 and not clear_geom_prep.intersects(line): if line.length < 5 and not clear_geom_prep.intersects(line):
area.fallback_nodes[node.i] = ( area.fallback_nodes[node.i] = RouterNodeAndEdge(
fallback_node, node=fallback_node,
RouterEdge.create(from_node=fallback_node, to_node=node, waytype=0) edge=RouterEdge.create(from_node=fallback_node, to_node=node, waytype=0)
) )
if not area.fallback_nodes: if not area.fallback_nodes:
nearest_node = min(space_nodes, key=lambda node: fallback_point.distance(node.point)) nearest_node = min(space_nodes, key=lambda node: fallback_point.distance(node.point))
area.fallback_nodes[nearest_node.i] = ( area.fallback_nodes[nearest_node.i] = RouterNodeAndEdge(
fallback_node, node=fallback_node,
RouterEdge.create(from_node=fallback_node, to_node=nearest_node, waytype=0) edge=RouterEdge.create(from_node=fallback_node, to_node=nearest_node, waytype=0)
) )
for poi in space_obj.pois.all(): for poi in space_obj.pois.all():
@ -552,18 +558,19 @@ class Router:
while last_node != origin_node: while last_node != origin_node:
last_node = predecessors[origin_node, last_node] last_node = predecessors[origin_node, last_node]
path_nodes.appendleft(last_node) path_nodes.appendleft(last_node)
path_nodes = tuple(path_nodes)
origin_addition = origin.nodes_addition.get(origin_node) return Route(
destination_addition = destination.nodes_addition.get(destination_node) router=self,
origin=origin,
# get additional distance at origin and destination destination=destination,
origin_xyz = origin.xyz if isinstance(origin, RouterPoint) else None path_nodes=tuple(path_nodes),
destination_xyz = destination.xyz if isinstance(destination, RouterPoint) else None options=options,
origin_addition=origin.nodes_addition.get(origin_node),
return Route(self, origin, destination, path_nodes, options, destination_addition=destination.nodes_addition.get(destination_node),
origin_addition, destination_addition, origin_xyz, destination_xyz, origin_xyz=origin.xyz if isinstance(origin, RouterPoint) else None,
visible_locations) destination_xyz=destination.xyz if isinstance(destination, RouterPoint) else None,
visible_locations=visible_locations
)
CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'altitude', CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'altitude',
@ -699,11 +706,11 @@ class RouterAltitudeArea:
node = all_nodes[node] node = all_nodes[node]
line = LineString([(node.x, node.y), (point.x, point.y)]) line = LineString([(node.x, node.y), (point.x, point.y)])
if line.length < 10 and not self.clear_geometry_prep.intersects(line): if line.length < 10 and not self.clear_geometry_prep.intersects(line):
nodes[node.i] = (None, None) nodes[node.i] = RouterNodeAndEdge(node=None, edge=None)
if not nodes: if not nodes:
nearest_node = min(tuple(all_nodes[node] for node in self.nodes), nearest_node = min(tuple(all_nodes[node] for node in self.nodes),
key=lambda node: point.distance(node.point)) key=lambda node: point.distance(node.point))
nodes[nearest_node.i] = (None, None) nodes[nearest_node.i] = RouterNodeAndEdge(node=None, edge=None)
else: else:
nodes = self.fallback_nodes nodes = self.fallback_nodes
return nodes return nodes
@ -800,7 +807,7 @@ class RouterLocation:
def nodes(self) -> frozenset[int]: def nodes(self) -> frozenset[int]:
return reduce(operator.or_, (location.nodes for location in self.locations), frozenset()) return reduce(operator.or_, (location.nodes for location in self.locations), frozenset())
def get_location_for_node(self, node): def get_location_for_node(self, node) -> RouterPoint | None:
for location in self.locations: for location in self.locations:
if node in location.nodes: if node in location.nodes:
return location return location