# Path: roadmaptools/printer.py
# def print_info(info, file=sys.stdout, end="\n"):
#     print("[{0}]: {1}".format(datetime.now().strftime('%H:%M:%S'), info), file=file, end=end)
# 
# Path: roadmaptools/road_structures.py
# class LinestringEdge:
# 
# 	def __init__(self, geojson_linestring: geojson.geometry.LineString,
# 				 coordinate_convertor: Callable[[float, float], Tuple[float, float]], node_from: Node, node_to: Node):
# 		self.geojson_linestring = geojson_linestring
# 		self.linestring = roadmaptools.geojson_shp.geojson_linestring_to_shp_linestring(geojson_linestring,
# 																							coordinate_convertor)
# 		self.node_from = node_from
# 		self.node_to = node_to
# 		self.id = get_edge_id(node_from.id, node_to.id)
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# class Node:
# 	def __init__(self, x: float, y: float, id: int):
# 		self.id = id
# 		self.x = x
# 		self.y = y
# 		self._point = None
# 
# 	def get_point(self) -> Point:
# 		if not self._point:
# 			self._point = Point(self.x, self.y)
# 
# 		return self._point
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# Path: roadmaptools/utm.py
# class CoordinateConvertor:
#     projection = default_projection
# 
#     @staticmethod
#     def convert(latitude: float, longitude: float) -> Tuple[float, float]:
#         return wgs84_to_utm(latitude, longitude, CoordinateConvertor.projection)


import os.path
import networkx.algorithms.shortest_paths
import roadmaptools.utm
import roadmaptools.geometry
import roadmaptools.shp
import roadmaptools.inout
import roadmaptools.plotting
from typing import Dict, Union, Optional, List, Callable, Tuple
from networkx import DiGraph
from shapely.geometry import Point
from scipy.spatial.kdtree import KDTree
from geojson import FeatureCollection
from tqdm import tqdm
from roadmaptools.printer import print_info
from roadmaptools.road_structures import LinestringEdge, Node
from roadmaptools.utm import CoordinateConvertor
            print_info("Creating networkx graph from geojson")
            for item in tqdm(geojson['features'], desc="processing features"):
                if item["geometry"]["type"] == "LineString":
                    coords = item['geometry']['coordinates']
                    coord_from = roadmaptools.utm.wgs84_to_utm(coords[0][1], coords[0][0], self.projection)
                    coord_to = roadmaptools.utm.wgs84_to_utm(coords[-1][1], coords[-1][0], self.projection)

                    node_from = self._get_node(coord_from[0], coord_from[1])
                    node_to = self._get_node(coord_to[0], coord_to[1])

                    edge = LinestringEdge(item, CoordinateConvertor.convert, node_from, node_to)

                    # TODO legacy, remove after moving id from properties to id attribute
                    edge_id = item['properties']['id'] if "id" in item['properties'] else item['id']
                    length = item['properties']['length'] if 'length' in item['properties'] \
                        else roadmaptools.geometry.get_distance(coord_from, coord_to)

                    if node_from in self.graph and node_to in self.graph[node_from]:
                        a = 1

                    self.graph.add_edge(node_from, node_to, id=edge_id, length=length, edge=edge)

                    edge_counter += 1

            if edge_counter != len(self.graph.edges):
                a = 1

            if self.use_cache:
                networkx.write_gpickle(self.graph, self.cache_filepath)


# Path: roadmaptools/printer.py
# def print_info(info, file=sys.stdout, end="\n"):
#     print("[{0}]: {1}".format(datetime.now().strftime('%H:%M:%S'), info), file=file, end=end)
# 
# Path: roadmaptools/road_structures.py
# class LinestringEdge:
# 
# 	def __init__(self, geojson_linestring: geojson.geometry.LineString,
# 				 coordinate_convertor: Callable[[float, float], Tuple[float, float]], node_from: Node, node_to: Node):
# 		self.geojson_linestring = geojson_linestring
# 		self.linestring = roadmaptools.geojson_shp.geojson_linestring_to_shp_linestring(geojson_linestring,
# 																							coordinate_convertor)
# 		self.node_from = node_from
# 		self.node_to = node_to
# 		self.id = get_edge_id(node_from.id, node_to.id)
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# class Node:
# 	def __init__(self, x: float, y: float, id: int):
# 		self.id = id
# 		self.x = x
# 		self.y = y
# 		self._point = None
# 
# 	def get_point(self) -> Point:
# 		if not self._point:
# 			self._point = Point(self.x, self.y)
# 
# 		return self._point
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# Path: roadmaptools/utm.py
# class CoordinateConvertor:
#     projection = default_projection
# 
#     @staticmethod
#     def convert(latitude: float, longitude: float) -> Tuple[float, float]:
#         return wgs84_to_utm(latitude, longitude, CoordinateConvertor.projection)


# Path: roadmaptools/graph.py
import os.path
import networkx.algorithms.shortest_paths
import roadmaptools.utm
import roadmaptools.geometry
import roadmaptools.shp
import roadmaptools.inout
import roadmaptools.plotting
from typing import Dict, Union, Optional, List, Callable, Tuple
from networkx import DiGraph
from shapely.geometry import Point
from scipy.spatial.kdtree import KDTree
from geojson import FeatureCollection
from tqdm import tqdm
from roadmaptools.printer import print_info
from roadmaptools.road_structures import LinestringEdge, Node
from roadmaptools.utm import CoordinateConvertor

            print_info("Creating networkx graph from geojson")
            for item in tqdm(geojson['features'], desc="processing features"):
                if item["geometry"]["type"] == "LineString":
                    coords = item['geometry']['coordinates']
                    coord_from = roadmaptools.utm.wgs84_to_utm(coords[0][1], coords[0][0], self.projection)
                    coord_to = roadmaptools.utm.wgs84_to_utm(coords[-1][1], coords[-1][0], self.projection)

                    node_from = self._get_node(coord_from[0], coord_from[1])
                    node_to = self._get_node(coord_to[0], coord_to[1])

                    edge = LinestringEdge(item, CoordinateConvertor.convert, node_from, node_to)

                    # TODO legacy, remove after moving id from properties to id attribute
                    edge_id = item['properties']['id'] if "id" in item['properties'] else item['id']
                    length = item['properties']['length'] if 'length' in item['properties'] \
                        else roadmaptools.geometry.get_distance(coord_from, coord_to)

                    if node_from in self.graph and node_to in self.graph[node_from]:
                        a = 1

                    self.graph.add_edge(node_from, node_to, id=edge_id, length=length, edge=edge)

                    edge_counter += 1

            if edge_counter != len(self.graph.edges):
                a = 1

            if self.use_cache:
                networkx.write_gpickle(self.graph, self.cache_filepath)


    def get_precise_path_length(self, edge_from: LinestringEdge, edge_to: LinestringEdge,