11import math
22from abc import ABC , abstractmethod
33
4- import pyproj
54from haversine import Unit , haversine
65
76from yaramo .base_element import BaseElement
87
8+ from .utils .coordinateconversion import transform_dbref_to_wgs84 , transform_wgs84_to_dbref
9+
910
1011class GeoNode (ABC , BaseElement ):
1112 """This is the baseclass of specific GeoNodes that use different coordinate systems.
1213
1314 A GeoNode is characterized by it's x and y coordinates.
1415 """
1516
16- def __init__ (self , x , y , ** kwargs ):
17+ def __init__ (self , x , y , dbref_crs : str = "ER0" , ** kwargs ):
1718 super ().__init__ (** kwargs )
1819 self .x = x
1920 self .y = y
21+ self .dbref_crs = dbref_crs
2022
2123 @abstractmethod
2224 def get_distance_to_other_geo_node (self , geo_node_b : "GeoNode" ):
@@ -31,36 +33,63 @@ def to_wgs84(self) -> "Wgs84GeoNode":
3133 def to_dbref (self ) -> "DbrefGeoNode" :
3234 pass
3335
36+ @abstractmethod
37+ def to_euclidean (self ) -> "EuclideanGeoNode" :
38+ pass
39+
3440 def to_serializable (self ):
3541 return self .__dict__ , {}
3642
3743
3844class Wgs84GeoNode (GeoNode ):
39- def get_distance_to_other_geo_node (self , geo_node_b : "Wgs84GeoNode" ):
40- assert type (self ) == type (
41- geo_node_b
42- ), "You cannot calculate the distance between a Wgs84GeoNode and a DbrefGeoNode!"
45+ def get_distance_to_other_geo_node (self , geo_node_b : "GeoNode" ):
46+ geo_node_b = geo_node_b .to_wgs84 ()
4347 return self .__haversine_distance (geo_node_b )
4448
4549 def __haversine_distance (self , geo_node_b : "GeoNode" ):
4650 own = (self .x , self .y )
4751 other = (geo_node_b .x , geo_node_b .y )
4852 return haversine (own , other , unit = Unit .METERS )
4953
50- def to_wgs84 (self ):
54+ def to_wgs84 (self ) -> "Wgs84GeoNode" :
5155 return self
5256
53- def to_dbref (self ):
54- transformer = pyproj .Transformer .from_crs ("epsg:4326" , "epsg:31468" )
55- x , y = transformer .transform (self .y , self .x )
56- return DbrefGeoNode (x , y )
57+ def to_dbref (self ) -> "DbrefGeoNode" :
58+ x , y = transform_wgs84_to_dbref (self .x , self .y , self .dbref_crs )
59+ return DbrefGeoNode (x , y , self .dbref_crs )
60+
61+ def to_euclidean (self ) -> "EuclideanGeoNode" :
62+ return self .to_dbref ().to_euclidean ()
5763
5864
5965class DbrefGeoNode (GeoNode ):
60- def get_distance_to_other_geo_node (self , geo_node_b : "DbrefGeoNode" ):
61- assert type (self ) == type (
62- geo_node_b
63- ), "You cannot calculate the distance between a DbrefGeoNode and a Wgs84GeoNode!"
66+ def get_distance_to_other_geo_node (self , geo_node_b : "GeoNode" ):
67+ # Separate DB Ref distance method not implemented yet, therefore use WGS84 distance
68+ return self .to_wgs84 ().get_distance_to_other_geo_node (geo_node_b )
69+
70+ def to_wgs84 (self ) -> "Wgs84GeoNode" :
71+ x , y = transform_dbref_to_wgs84 (self .x , self .y , self .dbref_crs )
72+ return Wgs84GeoNode (x , y , self .dbref_crs )
73+
74+ def to_dbref (self ) -> "DbrefGeoNode" :
75+ return self
76+
77+ def to_euclidean (self ) -> "EuclideanGeoNode" :
78+ # This transformation is just for testing purposes and not correct, see documentation in EuclideanGeoNode.
79+ _x_shift = 4533770.0
80+ _y_shift = 5625780.0
81+ return EuclideanGeoNode (self .x - _x_shift , self .y - _y_shift , self .dbref_crs )
82+
83+
84+ class EuclideanGeoNode (GeoNode ):
85+ """
86+ The Euclidean geo node is a simple geo node based on the simple concept of x and y coordinates and
87+ the Euclidean distance between two geo nodes. It's mainly for testing purposes and can only be converted to
88+ DBRef geo nodes, but the conversion is just a simple coordinate shift and with this, probably incorrect.
89+ """
90+
91+ def get_distance_to_other_geo_node (self , geo_node_b : "EuclideanGeoNode" ):
92+ geo_node_b = geo_node_b .to_euclidean ()
6493 return self .__eucldian_distance (geo_node_b )
6594
6695 def __eucldian_distance (self , geo_node_b : "GeoNode" ):
@@ -70,8 +99,13 @@ def __eucldian_distance(self, geo_node_b: "GeoNode"):
7099 max_y = max (self .y , geo_node_b .y )
71100 return math .sqrt (math .pow (max_x - min_x , 2 ) + math .pow (max_y - min_y , 2 ))
72101
73- def to_wgs84 (self ):
74- raise NotImplementedError
102+ def to_wgs84 (self ) -> "Wgs84GeoNode" :
103+ return self .to_dbref ().to_wgs84 ()
104+
105+ def to_dbref (self ) -> "DbrefGeoNode" :
106+ _x_shift = 4533770.0
107+ _y_shift = 5625780.0
108+ return DbrefGeoNode (self .x + _x_shift , self .y + _y_shift , self .dbref_crs )
75109
76- def to_dbref (self ):
110+ def to_euclidean (self ) -> "EuclideanGeoNode" :
77111 return self
0 commit comments