summaryrefslogtreecommitdiff
path: root/lib/DBInfoscreen/Controller
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DBInfoscreen/Controller')
-rw-r--r--lib/DBInfoscreen/Controller/Map.pm183
1 files changed, 91 insertions, 92 deletions
diff --git a/lib/DBInfoscreen/Controller/Map.pm b/lib/DBInfoscreen/Controller/Map.pm
index 8ff68d7..d618e8c 100644
--- a/lib/DBInfoscreen/Controller/Map.pm
+++ b/lib/DBInfoscreen/Controller/Map.pm
@@ -63,6 +63,80 @@ sub get_hafas_polyline_p {
return $promise;
}
+sub estimate_train_position {
+ my (%opt) = @_;
+
+ my $now = $opt{now};
+
+ my $from_dt = $opt{from}{dep};
+ my $to_dt = $opt{to}{arr};
+ my $from_name = $opt{from}{name};
+ my $to_name = $opt{to}{name};
+ my $features = $opt{features};
+
+ my $route_part_completion_ratio
+ = ( $now->epoch - $from_dt->epoch ) / ( $to_dt->epoch - $from_dt->epoch );
+
+ my $geo = Geo::Distance->new;
+ my ( $from_index, $to_index );
+
+ for my $j ( 0 .. $#{$features} ) {
+ my $this_point = $features->[$j];
+ if ( not defined $from_index
+ and $this_point->{properties}{type}
+ and $this_point->{properties}{type} eq 'stop'
+ and $this_point->{properties}{name} eq $from_name )
+ {
+ $from_index = $j;
+ }
+ elsif ( $this_point->{properties}{type}
+ and $this_point->{properties}{type} eq 'stop'
+ and $this_point->{properties}{name} eq $to_name )
+ {
+ $to_index = $j;
+ last;
+ }
+ }
+ if ( $from_index and $to_index ) {
+ my $total_distance = 0;
+ for my $j ( $from_index + 1 .. $to_index ) {
+ my $prev = $features->[ $j - 1 ]{geometry}{coordinates};
+ my $this = $features->[$j]{geometry}{coordinates};
+ if ( $prev and $this ) {
+ $total_distance += $geo->distance(
+ 'kilometer', $prev->[0], $prev->[1],
+ $this->[0], $this->[1]
+ );
+ }
+ }
+ my $marker_distance = $total_distance * $route_part_completion_ratio;
+ $total_distance = 0;
+ for my $j ( $from_index + 1 .. $to_index ) {
+ my $prev = $features->[ $j - 1 ]{geometry}{coordinates};
+ my $this = $features->[$j]{geometry}{coordinates};
+ if ( $prev and $this ) {
+ $total_distance += $geo->distance(
+ 'kilometer', $prev->[0], $prev->[1],
+ $this->[0], $this->[1]
+ );
+ }
+ if ( $total_distance > $marker_distance ) {
+
+ # return (lat, lon)
+ return ( $this->[1], $this->[0] );
+ }
+ }
+ }
+ else {
+ my $lat = $opt{from}{lat}
+ + ( $opt{to}{lat} - $opt{from}{lat} ) * $route_part_completion_ratio;
+ my $lon = $opt{from}{lon}
+ + ( $opt{to}{lon} - $opt{from}{lon} ) * $route_part_completion_ratio;
+ return ( $lat, $lon );
+ }
+ return ( $opt{to}{lat}, $opt{to}{lon} );
+}
+
sub route {
my ($self) = @_;
my $trip_id = $self->stash('tripid');
@@ -188,107 +262,32 @@ sub route {
and $now > $route[ $i - 1 ]{dep}
and $now < $route[$i]{arr} )
{
- my $from_dt = $route[ $i - 1 ]{dep};
- my $to_dt = $route[$i]{arr};
- my $from_name = $route[ $i - 1 ]{name};
- my $to_name = $route[$i]{name};
-
- my $route_part_completion_ratio
- = ( $now->epoch - $from_dt->epoch )
- / ( $to_dt->epoch - $from_dt->epoch );
my $title = $pl->{name};
if ( $route[$i]{arr_delay} ) {
$title .= sprintf( ' (%+d)', $route[$i]{arr_delay} );
}
- my $geo = Geo::Distance->new;
- my ( $from_index, $to_index );
+ my ( $train_lat, $train_lon ) = estimate_train_position(
+ from => $route[ $i - 1 ],
+ to => $route[$i],
+ now => $now,
+ features => $pl->{raw}{polyline}{features},
+ );
- for my $j ( 0 .. $#{ $pl->{raw}{polyline}{features} } ) {
- my $this_point = $pl->{raw}{polyline}{features}[$j];
- if ( not defined $from_index
- and $this_point->{properties}{type}
- and $this_point->{properties}{type} eq 'stop'
- and $this_point->{properties}{name} eq $from_name )
- {
- $from_index = $j;
- }
- elsif ( $this_point->{properties}{type}
- and $this_point->{properties}{type} eq 'stop'
- and $this_point->{properties}{name} eq $to_name )
+ push(
+ @markers,
{
- $to_index = $j;
- last;
- }
- }
- if ( $from_index and $to_index ) {
- my $total_distance = 0;
- for my $j ( $from_index + 1 .. $to_index ) {
- my $prev = $pl->{raw}{polyline}{features}[ $j - 1 ]
- {geometry}{coordinates};
- my $this
- = $pl->{raw}{polyline}{features}[$j]{geometry}
- {coordinates};
- if ( $prev and $this ) {
- $total_distance += $geo->distance(
- 'kilometer', $prev->[0], $prev->[1],
- $this->[0], $this->[1]
- );
- }
- }
- my $marker_distance
- = $total_distance * $route_part_completion_ratio;
- $total_distance = 0;
- for my $j ( $from_index + 1 .. $to_index ) {
- my $prev = $pl->{raw}{polyline}{features}[ $j - 1 ]
- {geometry}{coordinates};
- my $this
- = $pl->{raw}{polyline}{features}[$j]{geometry}
- {coordinates};
- if ( $prev and $this ) {
- $total_distance += $geo->distance(
- 'kilometer', $prev->[0], $prev->[1],
- $this->[0], $this->[1]
- );
- }
- if ( $total_distance > $marker_distance ) {
- push(
- @markers,
- {
- lon => $this->[0],
- lat => $this->[1],
- title => $title
- }
- );
- $next_stop = {
- type => 'next',
- station => $route[$i],
- };
- last;
- }
+ lat => $train_lat,
+ lon => $train_lon,
+ title => $title
}
- }
- else {
- push(
- @markers,
- {
- lat => $route[ $i - 1 ]{lat} + (
- ( $route[$i]{lat} - $route[ $i - 1 ]{lat} )
- * $route_part_completion_ratio
- ),
- lon => $route[ $i - 1 ]{lon} + (
- ( $route[$i]{lon} - $route[ $i - 1 ]{lon} )
- * $route_part_completion_ratio
- ),
- title => $title
- }
- );
- $next_stop = {
- type => 'next',
- station => $route[$i],
- };
- }
+ );
+
+ $next_stop = {
+ type => 'next',
+ station => $route[$i],
+ };
last;
}
if ( $route[ $i - 1 ]{dep} and $now <= $route[ $i - 1 ]{dep} ) {