Skip to content

Improve stop area generation#262

Merged
Robbendebiene merged 4 commits intomasterfrom
improve-stop-area-query
May 27, 2024
Merged

Improve stop area generation#262
Robbendebiene merged 4 commits intomasterfrom
improve-stop-area-query

Conversation

@Robbendebiene
Copy link
Copy Markdown
Member

@Robbendebiene Robbendebiene commented May 15, 2024

What changed:

  • internally converts stop areas from circles to bboxes
  • elements are no longer filtered based on their centroid lying within the stop area, instead it is enough if their bbox intersects with the stop area. This helps to include platforms which centroid could previously lie outside but especially other elements that do not span the stop area like parking spaces or footways.
  • stop area creation (merging of nearby stops) is completely done on the server side (via special Overpass query)
  • the merging now works differently and should avoid the creation of super large stop areas (grouping more than 100 stops) as it could happen previously
  • the merging should also be more accurate for geometries other than nodes. Previously it only looked around the centroid in a specific radius, now it looks around the entire geometry for ways.
  • the stop are is now named after the lexicographically first stop name

Decisions

It was decided against additionally using public_transport=stop_area inside the query.
While it has benefits like:

  • performance improvement (as the elements do not have to be manually grouped by distance)
  • the name (if existing) better describes the stop area than a name derived from the individual stops (as the stop name can contain things like "Platform B" or "West")
  • correctly groups stops that are too far away from each other to be grouped by distance

The downside is that in reality stop areas overlap or are incomplete (wherefore a new stop area is created through grouping). This can lead to overlapping stop areas (bboxes) thus having multiple requests for the same region + overlapping loading indicators.

Ideal solution would be a merging/grouping by geometry of the existing stop areas wit the remaining platforms.

Query with stop areas (faster but overlapping bboxes):

[bbox:{{bbox}}];

// get all platforms
nwr[public_transport=platform]->.platforms;
// get all stop_areas
rel[public_transport=stop_area]->.stop_areas;
// get all stop_area members
nwr(r.stop_areas)->.stop_area_members;
// all platforms not part of a stop_area
(.platforms; - .stop_area_members;)->.remaining_platforms;

// for each stop area
foreach.stop_areas {
  // recurse relation fully down (select all ancestors)
  // required to construct the full geometry for relations that contain other relations
  >>;
  // convert all stop_areas to custom zone element
  make zone
    name=min(t["name"]),
    // group geometries into one
    ::geom=gcat(geom());
  out bb;
}

// return all bboxes of stop aras and platforms not part of stop areas
// loop over every single platform element
foreach.remaining_platforms {
  // make intersection of current platform (default set ._) and .remaining_platforms
  // therefore only if the current platform is in remaining_platforms count will be 1
  // otherwise it has already been merged and therefore removed from remaining_platforms
  nwr._.remaining_platforms;
  if (count(nwr) > 0) {
    // get any nearby platforms
    // this loops for every newly found platform untill no new platforms are found
    // 10 is the max number of iterations
    complete(10) -> .grouped {
      nwr.remaining_platforms(around:75);
    }
    // delete .grouped platforms from .remaining_platfroms set
    (.remaining_platforms; - .grouped;) -> .remaining_platforms;
    // write to default set because make always reads from default set
    .grouped -> ._;
    // build the target areas
    make zone 
      name=min(t["name"]),
    // uncomment the following line to get the source remaining_platforms
    // source=set("{"+type()+" "+id()+"}"),
    // group geometries into one
    ::geom=gcat(geom());
    // output bbox only
    out bb;
  }
}

Query with stop areas, but merge stop areas with remaining platforms and other stop areas (sometimes slightly better bboxes, not faster, but for wrong stop areas we get large bboxes https://www.openstreetmap.org/relation/7646731/history/4)

[bbox:{{bbox}}];

// get all platforms
nwr[public_transport=platform]->.platforms;
// get all stop_areas
rel[public_transport=stop_area]->.stop_areas;
// get all stop_area members
nwr(r.stop_areas)->.stop_area_members;
// all platforms not part of a stop_area
(.platforms; - .stop_area_members;)->.remaining_platforms;

(.stop_areas; .remaining_platforms;)->.remaining_platforms;

// return all bboxes of stop aras and platforms not part of stop areas
// loop over every single platform element
foreach.remaining_platforms {
  // make intersection of current platform (default set ._) and .remaining_platforms
  // therefore only if the current platform is in remaining_platforms count will be 1
  // otherwise it has already been merged and therefore removed from remaining_platforms
  nwr._.remaining_platforms;
  if (count(nwr) > 0) {
    // get any nearby platforms
    // this loops for every newly found platform untill no new platforms are found
    // 20 is the max number of iterations
    complete(20) -> .grouped {
      nwr.remaining_platforms(around:100);
    }
    // delete .grouped platforms from .remaining_platfroms set
    (.remaining_platforms; - .grouped;) -> .remaining_platforms;
    // recurse relation fully down (select all ancestors)
    // required to construct the full geometry for relations that contain other relations
    // write to default set because make always reads from default set
    (.grouped; .grouped >>;);
    // build the target areas
    make zone
      name=min(t["name"]),
    // uncomment the following line to get the source remaining_platforms
    // source=set("{"+type()+" "+id()+"}"),
    // group geometries into one
    ::geom=gcat(geom());
    // output bbox only
    out bb;
  }
}

Replaces old stop area query api, stop class and stop area generator.
Internally changes stop areas from circles to bounding boxes.
@Robbendebiene Robbendebiene force-pushed the improve-stop-area-query branch from f30aad1 to 9a2cc7c Compare May 16, 2024 08:17
@Robbendebiene Robbendebiene requested a review from 7h30n3 May 23, 2024 12:40
@Robbendebiene Robbendebiene force-pushed the improve-stop-area-query branch from 81fc82f to 381a747 Compare May 23, 2024 13:11
static String _buildQuery (int mergeRadius) =>
// get all platforms
'nwr[public_transport=platform]->.remaining_platforms;'
// return all bboxes of stop aras and platforms not part of stop areas
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// return all bboxes of stop aras and platforms not part of stop areas
// return all bboxes of stop areas and platforms not part of stop areas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants