1+ import json
2+ import os
3+
4+ import inro .modeller as _m
5+ from shapely .geometry import shape , Point
6+
7+ class TransitZones (_m .Tool ()):
8+ transit_zones = _m .Attribute (str )
9+
10+ def __init__ (self ):
11+ """Tool with click-button that can be imported in the Modeller GUI.
12+ """
13+ self .tool_run_msg = ""
14+
15+ def page (self ):
16+ pb = _m .ToolPageBuilder (self )
17+ pb .title = "Reassign transit zones"
18+ pb .add_select_file (
19+ "transit_zones" , "directory" , file_filter = "*.json;*.geojson*" , start_path = "" ,
20+ title = "Transit zone area file:"
21+ )
22+ if self .tool_run_msg :
23+ pb .add_html (self .tool_run_msg )
24+ return pb .render ()
25+
26+ def run (self ):
27+ self ()
28+
29+ def __call__ (self ):
30+ """Reassign transit zones for current scenario.
31+ """
32+ scen = _m .Modeller ().scenario
33+ network = scen .get_network ()
34+ if not os .path .exists (self .transit_zones ):
35+ self .write (f"Error: File '{ self .transit_zones } ' does not exist." )
36+ return
37+ try :
38+ with open (self .transit_zones , "r" , encoding = "utf-8" ) as file :
39+ geojson_data = json .load (file )
40+ except json .JSONDecodeError :
41+ self .write (f"Error: File '{ self .transit_zones } ' is not a valid JSON file." )
42+ return
43+ num_features = len (geojson_data ["features" ])
44+ increment = 100 / num_features
45+ self .percent = 0
46+
47+ transit_zone_labels = set ()
48+ processed_nodes = 0
49+ # Access features
50+ try :
51+ for feature in geojson_data ["features" ]:
52+ zone = feature ["properties" ]["zone" ] # Access attributes
53+ transit_zone_labels .add (zone )
54+ geometry = shape (feature ["geometry" ]) # Convert geometry to Shapely object
55+ for node in network .nodes ():
56+ if Point (node .x , node .y ).within (geometry ):
57+ node .label = zone
58+ processed_zones += 1
59+ self .percent += increment
60+ except KeyError :
61+ self .write ("The provided GeoJSON has an invalid format." )
62+ return
63+ _m .Modeller ().scenario .publish_network (network )
64+ msg = f"Transit zones for scenario { scen .id } created successfully. Processed { len (transit_zone_labels )} zones and { processed_nodes } nodes."
65+ self .write (msg )
66+ self .tool_run_msg = _m .PageBuilder .format_info (msg )
67+
68+ def percent_completed (self ):
69+ return (0 , 100 , self .percent )
70+
71+
72+ def write (self , message ):
73+ _m .logbook_write (message )
74+
75+ def flush (self ):
76+ """Flush the logbook (i.e., do nothing)."""
77+ pass
0 commit comments