~ihabunek/triglav

211b57c1cf59aff5e469e8ccff4f3020ae0a9401 — Ivan Habunek 1 year, 7 months ago c799db7 distances
WIP
2 files changed, 60 insertions(+), 8 deletions(-)

M lib/triglav/osm/router.ex
M lib/triglav/zet/validator.ex
M lib/triglav/osm/router.ex => lib/triglav/osm/router.ex +1 -1
@@ 46,7 46,7 @@ defmodule Triglav.Osm.Router do
        |> Enum.concat()
        |> Enum.dedup()

      {:ok, %Geo.LineString{coordinates: coordinates}}
      {:ok, %Geo.LineString{coordinates: coordinates, srid: 4326}}
    end
  end


M lib/triglav/zet/validator.ex => lib/triglav/zet/validator.ex +59 -7
@@ 8,6 8,8 @@ defmodule Triglav.Zet.Validator do
  alias Triglav.Schemas.Zet.Route
  alias Triglav.Zet.Gtfs
  alias Triglav.Zet.Osmosis
  alias Triglav.Repo
  import Ecto.Query

  @spec validate_all_routes() :: [Error.t()]
  def validate_all_routes() do


@@ 16,27 18,36 @@ defmodule Triglav.Zet.Validator do
    relation_stop_ids = relations |> Enum.map(& &1.id) |> Osmosis.list_gtfs_stop_ids()
    ways = Osmosis.list_ways(relations) |> Map.new(&{&1.id, &1})

    platforms =
      relations
      |> Enum.map(& &1.id)
      |> Osmosis.list_platform_members()
      |> Enum.group_by(& &1.relation_id)

    for route <- routes do
      route_relations = Enum.filter(relations, &(Relation.ref(&1) == route.id))
      validate_route(route, route_relations, ways, relation_stop_ids)
      validate_route(route, route_relations, ways, relation_stop_ids, platforms)
    end
    |> List.flatten()
  end

  @type platform :: Way.t() | Node.t()

  @spec validate_route(
          Route.t(),
          [Relation.t()],
          %{integer() => Way.t()},
          %{integer() => [integer()]}
          %{integer() => [integer()]},
          %{integer() => [platform()]}
        ) :: [Error.t()]
  def validate_route(route, relations, ways, relation_stop_ids) do
  def validate_route(route, relations, ways, relation_stop_ids, platforms) do
    [
      validate_has_relations(route, relations),
      validate_has_route_master(route, relations),
      validate_routes_are_contained_in_route_master(route, relations),
      validate_routes_master_route_has_no_unknown_members(route, relations),
      Enum.map(relations, &validate_route_master_relation(route, &1)),
      Enum.map(relations, &validate_route_relation(route, &1, ways, relation_stop_ids))
      Enum.map(relations, &validate_route_relation(route, &1, ways, relation_stop_ids, platforms))
    ]
    |> List.flatten()
    |> Enum.filter(& &1)


@@ 127,7 138,8 @@ defmodule Triglav.Zet.Validator do
         %Route{} = route,
         %Relation{tags: %{"type" => "route"}} = relation,
         ways,
         relation_stop_ids
         relation_stop_ids,
         platforms
       ) do
    ordered_ways =
      relation.members


@@ 136,6 148,12 @@ defmodule Triglav.Zet.Validator do

    router_result = Triglav.Osm.Router.route_ways(ordered_ways)

    linestring =
      case router_result do
        {:ok, ls} -> ls
        _ -> nil
      end

    required_tags = ["type", "route", "ref", "operator", "from", "to", "name"]

    allowed_tags =


@@ 147,6 165,8 @@ defmodule Triglav.Zet.Validator do
      "ref" => route.id
    }

    relation_platforms = Map.get(platforms, relation.id, [])

    [
      validate_is_ptv2(route, relation),
      validate_route_naming(route, relation),


@@ 155,11 175,12 @@ defmodule Triglav.Zet.Validator do
      validate_tag_values(route, relation, expected_tags),
      validate_continuous_ways(route, relation, router_result),
      validate_has_gtfs_stop_ids(route, relation, relation_stop_ids),
      validate_member_roles(route, relation)
      validate_member_roles(route, relation),
      validate_platforms(route, relation, relation_platforms, linestring)
    ]
  end

  defp validate_route_relation(_, _, _, _), do: nil
  defp validate_route_relation(_, _, _, _, _), do: nil

  defp validate_is_ptv2(route, relation) do
    if !Relation.is_ptv2(relation) do


@@ 273,6 294,37 @@ defmodule Triglav.Zet.Validator do
    end
  end

  defp validate_platforms(route, relation, platforms, linestring) do
    Enum.map(platforms, &validate_platform_distance_from_route(route, relation, &1, linestring))
  end

  defp validate_platform_distance_from_route(route, relation, platform, route_geometry) do
    platform_geometry =
      case platform.member_type do
        "N" -> platform.member.geom
        "W" -> platform.member.linestring
      end

    platform = Geo.WKT.encode!(platform_geometry)
    route = Geo.WKT.encode!(route_geometry)

    # Repo.query!("SELECT st_distance(($1)::geography, ($2)::geography)", [
    #   Geo.WKT.encode!(platform_geometry),
    #   Geo.WKT.encode!(route_geometry)
    # ])

    distance =
      Repo.query!("SELECT st_distance('#{platform}'::geography, '#{route}'::geography)", [])
      |> Map.get(:rows)
      |> List.first()
      |> List.first()
      |> Float.round()

    if distance > 20 do
      IO.puts("Distance: #{distance}")
    end
  end

  #
  # Util fns
  #