summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/src/api.cpp93
-rw-r--r--server/src/api.cppm5
-rw-r--r--server/src/geo.cppm2
-rw-r--r--server/src/main.cpp2
4 files changed, 65 insertions, 37 deletions
diff --git a/server/src/api.cpp b/server/src/api.cpp
index 18fbc91..9953675 100644
--- a/server/src/api.cpp
+++ b/server/src/api.cpp
@@ -100,9 +100,36 @@ auto tag_invoke(json::value_from_tag, json::value& jv, sysinfo const& info)
100handler::handler(log::logger const& l, datex2::situation_publication pub) 100handler::handler(log::logger const& l, datex2::situation_publication pub)
101 : l_{l.sub("handler")}, pub_{std::move(pub)} 101 : l_{l.sub("handler")}, pub_{std::move(pub)}
102{ 102{
103 l_.info("Building indices"); 103 auto const nsit = pub_.situations.size();
104 auto progress_percent =
105 [nsit](decltype(pub_.situations)::difference_type i) -> int
106 {
107 return static_cast<int>(
108 static_cast<float>(i) / static_cast<float>(nsit) * 100.0f);
109 };
110
111 l_.info("Building indices for {} situations", nsit);
112
113 auto const buffer_distance = min_distance_;
114 auto const points_per_circle = 8;
115 // Note: thomas strategy does not work for geographic_join_round;
116 // need to use andoyer for that.
117 using formula = bgeo::strategy::andoyer;
118 bgeo::strategy::buffer::distance_symmetric<double> distance_strategy{
119 buffer_distance
120 };
121 bgeo::strategy::buffer::geographic_join_round<formula> join_strategy{
122 points_per_circle
123 };
124 bgeo::strategy::buffer::geographic_end_round<formula> end_strategy{4};
125 bgeo::strategy::buffer::geographic_point_circle<formula> circle_strategy{
126 points_per_circle
127 };
128 bgeo::strategy::buffer::geographic_side_straight<formula> side_strategy;
129
130 l_.info("Progress: 0%");
104 auto const before_build = chrono::steady_clock::now(); 131 auto const before_build = chrono::steady_clock::now();
105 for (auto const& sit : pub_.situations) 132 for (auto const& [i, sit] : pub_.situations | std::views::enumerate)
106 { 133 {
107 for (auto const& rc : sit->road_closures) 134 for (auto const& rc : sit->road_closures)
108 { 135 {
@@ -110,18 +137,30 @@ handler::handler(log::logger const& l, datex2::situation_publication pub)
110 { 137 {
111 auto box = geo::box{}; 138 auto box = geo::box{};
112 bgeo::envelope(*ls, box); 139 bgeo::envelope(*ls, box);
113 lse_index_.insert(std::make_tuple(box, ls, rc)); 140 auto buffered_ls = geo::multi_polygon{};
141 bgeo::buffer(
142 *ls, buffered_ls, distance_strategy, side_strategy, join_strategy,
143 end_strategy, circle_strategy);
144 lse_index_.insert(std::make_tuple(box, buffered_ls, rc));
114 } 145 }
115 for (auto p : rc->relevant_points) 146 for (auto p : rc->relevant_points)
116 { 147 {
117 p_index_.insert(std::make_pair(p, rc)); 148 p_index_.insert(std::make_pair(p, rc));
118 } 149 }
119 } 150 }
151
152 auto prev_prog = progress_percent(i);
153 auto cur_prog = progress_percent(i + 1);
154 if (cur_prog > prev_prog && cur_prog % 5 == 0 && cur_prog != 100)
155 {
156 l_.info("Progress: {}%", cur_prog);
157 }
120 } 158 }
159 l_.info("Progress: 100%");
160
121 auto const after_build = chrono::steady_clock::now(); 161 auto const after_build = chrono::steady_clock::now();
122 auto const dur_build = 162 auto const dur_build_s = chrono::duration<double>{after_build - before_build};
123 chrono::duration_cast<chrono::milliseconds>(after_build - before_build); 163 l_.info("Indices built in {}", dur_build_s);
124 l_.info("Indices built in {}", dur_build);
125 l_.info("LSE index size: {}", lse_index_.size()); 164 l_.info("LSE index size: {}", lse_index_.size());
126 l_.info("Point index size: {}", p_index_.size()); 165 l_.info("Point index size: {}", p_index_.size());
127} 166}
@@ -129,8 +168,6 @@ handler::handler(log::logger const& l, datex2::situation_publication pub)
129auto handler::process_gpx(gpx::file&& gpx_file) 168auto handler::process_gpx(gpx::file&& gpx_file)
130 -> std::optional<process_gpx_result> 169 -> std::optional<process_gpx_result>
131{ 170{
132 const auto min_distance = 5.0;
133
134 auto const now = chrono::utc_clock::now(); 171 auto const now = chrono::utc_clock::now();
135 auto const relevant = std::initializer_list<time::period>{ 172 auto const relevant = std::initializer_list<time::period>{
136 time::period{now - chrono::days(7), now + chrono::days(7)} 173 time::period{now - chrono::days(7), now + chrono::days(7)}
@@ -149,26 +186,6 @@ auto handler::process_gpx(gpx::file&& gpx_file)
149 186
150 auto vincenty_strategy = geo::vincenty_strategy{}; 187 auto vincenty_strategy = geo::vincenty_strategy{};
151 188
152 const auto buffer_distance = min_distance;
153 const auto points_per_circle = 8;
154 // Note: thomas strategy does not work for geographic_join_round;
155 // need to use andoyer for that.
156 using formula = bgeo::strategy::thomas;
157 bgeo::strategy::buffer::distance_symmetric<double> distance_strategy{
158 buffer_distance
159 };
160 bgeo::strategy::buffer::geographic_join_miter<formula> join_strategy{
161 buffer_distance
162 };
163 bgeo::strategy::buffer::geographic_end_round<formula> end_strategy{4};
164 bgeo::strategy::buffer::geographic_point_circle<formula> circle_strategy{
165 points_per_circle
166 };
167 bgeo::strategy::buffer::geographic_side_straight<formula> side_strategy;
168
169 using polygon = bgeo::model::polygon<geo::point>;
170 auto buffered_ls = bgeo::model::multi_polygon<polygon>{};
171
172 l_.debug("Querying for relevant situations"); 189 l_.debug("Querying for relevant situations");
173 auto relevant_road_closures = 190 auto relevant_road_closures =
174 std::unordered_set<std::shared_ptr<datex2::road_closure>>{}; 191 std::unordered_set<std::shared_ptr<datex2::road_closure>>{};
@@ -179,7 +196,7 @@ auto handler::process_gpx(gpx::file&& gpx_file)
179 { 196 {
180 l_.debug("Checking part [{}/{}]", ++i, splits_with_overlap_segments.size()); 197 l_.debug("Checking part [{}/{}]", ++i, splits_with_overlap_segments.size());
181 198
182 // TODO: consider buffering with min_distance 199 // TODO: consider buffering with min_distance_
183 auto part_box = geo::box{}; 200 auto part_box = geo::box{};
184 bgeo::envelope(part, part_box); 201 bgeo::envelope(part, part_box);
185 202
@@ -193,16 +210,24 @@ auto handler::process_gpx(gpx::file&& gpx_file)
193 // boost::geometry::model::linestring<geo::point> is part of the 210 // boost::geometry::model::linestring<geo::point> is part of the
194 // whole tuple type (lse_index_value) that is the value_type of the 211 // whole tuple type (lse_index_value) that is the value_type of the
195 // iterator. 212 // iterator.
196 std::shared_ptr<geo::linestring> const& ls = std::get<1>(*it); 213
214 // geo::box const& lse = std::get<0>(*it);
215 geo::multi_polygon const& buffered_ls = std::get<1>(*it);
197 std::shared_ptr<datex2::road_closure> const& rc = std::get<2>(*it); 216 std::shared_ptr<datex2::road_closure> const& rc = std::get<2>(*it);
198 if (rc->validity 217 if (rc->validity
199 && rc->validity->intersect(check_periods).periods().empty()) 218 && rc->validity->intersect(check_periods).periods().empty())
200 continue; 219 continue;
201 bgeo::buffer( 220
202 *ls, buffered_ls, distance_strategy, side_strategy, join_strategy, 221 // auto small_parts = bgeo::model::multi_linestring<geo::linestring>{};
203 end_strategy, circle_strategy); 222 // bgeo::intersection(part, lse, small_parts);
223
204 if (bgeo::intersects(buffered_ls, part)) 224 if (bgeo::intersects(buffered_ls, part))
205 relevant_road_closures.emplace(rc); 225 relevant_road_closures.emplace(rc);
226
227 // if (!bgeo::is_empty(small_parts))
228 // if (bgeo::distance(*ls, small_parts, vincenty_strategy) <
229 // min_distance_)
230 // relevant_road_closures.emplace(rc);
206 ls_checked++; 231 ls_checked++;
207 } 232 }
208 for (auto it = p_index_.qbegin(bgeo::index::intersects(part_box)); 233 for (auto it = p_index_.qbegin(bgeo::index::intersects(part_box));
@@ -214,7 +239,7 @@ auto handler::process_gpx(gpx::file&& gpx_file)
214 if (rc->validity 239 if (rc->validity
215 && rc->validity->intersect(check_periods).periods().empty()) 240 && rc->validity->intersect(check_periods).periods().empty())
216 continue; 241 continue;
217 if (bgeo::distance(p, part, vincenty_strategy) < min_distance) 242 if (bgeo::distance(p, part, vincenty_strategy) < min_distance_)
218 relevant_road_closures.emplace(rc); 243 relevant_road_closures.emplace(rc);
219 p_checked++; 244 p_checked++;
220 } 245 }
diff --git a/server/src/api.cppm b/server/src/api.cppm
index 8f639fd..6f301c4 100644
--- a/server/src/api.cppm
+++ b/server/src/api.cppm
@@ -77,9 +77,10 @@ auto tag_invoke(json::value_from_tag, json::value& jv, sysinfo const& info)
77 77
78class handler 78class handler
79{ 79{
80 constexpr static auto const min_distance_ = 5.0;
81
80 using lse_index_value = std::tuple< 82 using lse_index_value = std::tuple<
81 geo::box, std::shared_ptr<geo::linestring>, 83 geo::box, geo::multi_polygon, std::shared_ptr<datex2::road_closure>
82 std::shared_ptr<datex2::road_closure>
83 >; 84 >;
84 using p_index_value = 85 using p_index_value =
85 std::pair<geo::point, std::shared_ptr<datex2::road_closure>>; 86 std::pair<geo::point, std::shared_ptr<datex2::road_closure>>;
diff --git a/server/src/geo.cppm b/server/src/geo.cppm
index ae0d3cc..b3513c8 100644
--- a/server/src/geo.cppm
+++ b/server/src/geo.cppm
@@ -11,6 +11,8 @@ export namespace routemon::geo {
11using point = bgeo::model::point<double, 2, bgeo::cs::geographic<bgeo::degree>>; 11using point = bgeo::model::point<double, 2, bgeo::cs::geographic<bgeo::degree>>;
12using linestring = bgeo::model::linestring<point>; 12using linestring = bgeo::model::linestring<point>;
13using box = bgeo::model::box<point>; 13using box = bgeo::model::box<point>;
14using polygon = bgeo::model::polygon<geo::point>;
15using multi_polygon = bgeo::model::multi_polygon<polygon>;
14using stype = bgeo::srs::spheroid<double>; 16using stype = bgeo::srs::spheroid<double>;
15using vincenty_strategy = bgeo::strategy::distance::vincenty<stype>; 17using vincenty_strategy = bgeo::strategy::distance::vincenty<stype>;
16 18
diff --git a/server/src/main.cpp b/server/src/main.cpp
index b0a9938..99f19da 100644
--- a/server/src/main.cpp
+++ b/server/src/main.cpp
@@ -84,7 +84,7 @@ auto real_main(std::span<char const*> args) -> exit_status
84 { 84 {
85 auto const& warns = d2loader.warnings(); 85 auto const& warns = d2loader.warnings();
86 l.warn( 86 l.warn(
87 "Encountered {} unique warnings while loading DATEX II situations " 87 "Encountered {} unique warning(s) while loading DATEX II situations "
88 "publication", 88 "publication",
89 warns.size()); 89 warns.size());
90 auto i = 0uz; 90 auto i = 0uz;