prochitecture / blosm

GNU General Public License v3.0
11 stars 3 forks source link

Workflow and data structure for streets #72

Open vvoovv opened 11 months ago

vvoovv commented 11 months ago

(1) Create instances of the class Section (currently StreetSection). The attributes start and end are set to either a neighbor Section or an intersection or None (in the case of a dead-end).

Street sections are grouped into roadways. A street may have one, two or more roadways. If a street contains two or more roadways, then they are grouped into a cluster.

The class Street should have an attribute roadways. It's a Python tuple with a single element in the case of a single roadway and a Python list in the case of two or more roadways.

The class Roadway should have an attribute start. It is the reference to the first street section (an instance of the class Section) in the roadway. The other street sections in the roadway can be accessed with the related linked list (the attributes start and end of the class Section).

vvoovv commented 11 months ago

(2) A PML style is set for the instance of the class Street using the function getStyle supplied to the class StreetGenerator. The categories of street sections and the number of roadways will be used to assign a PML style to an instance of the class Street.

vvoovv commented 11 months ago

(3) A PML style should contain a style block street with the @setup directive where the default attributes are set:

@setup
street {
    numLanes: random_weighted( (2, 70), (4, 30) );
    numLanesOneway: random_weighted( (1, 75), (2, 25) );
}

Those style blocks with the @setup directive are evaluated immediately after assigning the PML style. The evaluated attributes numLanes and numLanesOneway and other, if provided, will be used if the number of lanes is not given in the OSM data for a street section.

vvoovv commented 11 months ago

(4) Perform the initialization like in the current method createWaySections(): setting the number of lanes, calculating widths, etc,

vvoovv commented 11 months ago

(5) Crosswalks should be extracted from the OSM data.

An OSM node representing a crosswalk is tagged with crossing=*. I suggest using the attribute crosswalkNodeIndices in the class Section to store a Python list of node indices of the cropped centerline where a sidewalk is located.

An OSM node with a crosswalk may be in the cropped part. In that case case the index of the node with the crosswalk will be 0 or N-1, where N is the number of nodes in the cropped centerline.

polarkernel commented 11 months ago

(1) Create instances of the class Section (currently StreetSection). The attributes start and end are set to either a neighbor Section or an intersection or None (in the case of a dead-end).

Intersection areas do not yet exist at this stage. Perhaps, the positions of the intersection nodes (currently of mathutils Vector class) could be used as keys to a container, that will later be filled by instances of theIntersectionArea class that belong to these nodes. Later in the process, the start and end attributes will need to be adjusted, when intersections are merged or clustered.

Besides neighbor sections, intersections and dead-ends, instances of a TransitionSymLane class or a TransitionSideLane class should also be considered as contents of the start and end attributes. But there we have the same problem as above, they do not exist yet at this time.

Street sections are grouped into roadways. A street may have one, two or more roadways. If a street contains two or more roadways, then they are grouped into a cluster.

I am not sure if I understand this correctly. Does the Roadway class group also include streets that are separated by instances of a TransitionSymLane class or a TransitionSideLane class, as shown here, or is Roadway somehow a replacement for what we had with the WayCluster class? Note that clusters do not yet exist at this stage.

The class Roadway should have an attribute start. It is the reference to the first street section (an instance of the class Section) in the roadway. The other street sections in the roadway can be accessed with the related linked list (the attributes start and end of the class Section).

This will work fine for linear cases, like those with the TransitionSymLane class or a TransitionSideLane class, as described above. But it will not work for clusters, because multiple way-sections may start from the same (clustered) intersection. Then, the start attribute will have to be a list.

polarkernel commented 11 months ago

The evaluated attributes numLanes and numLanesOneway and other, if provided, will be used if the number of lanes is not given in the OSM data for a street section.

I still do not understand this idea. The only case I know of where the number of lanes is not specified in OSM is when there is no lanes tag. Then, as far as I know, OSM assumes one lane for one-way streets and two lanes for the others. Would it make sense to change this using random numbers from the PML attributes?

EDITED: It seems that I am wrong. We even defined a default number of lanes in our default way properties wayCategoryProps in _wayproperties.py. I don't know to what extent this was justified. However, maybe the question is whether this table should be moved to PML eventually, as these numbers may have some locale aspect.

polarkernel commented 11 months ago

(5) Crosswalks should be extracted from the OSM data. An OSM node representing a crosswalk is tagged with crossing=*. I suggest using the attribute crosswalkNodeIndices in the class Section to store a Python list of node indices of the cropped centerline where a sidewalk is located.

This is now new to me. I searched for OSM objects tagged as crossing=* using overpass turbo and got something like this:

The result seem to be footways. What do you mean by "node indices of the cropped centerline where a sidewalk is located"? Are these the nodes of the trimmed centerline, between them a crossing footway intersects the centerline? Or are you talking about objects that are marked as sidewalk?

vvoovv commented 11 months ago

Intersection areas do not yet exist at this stage.

How about using an empty Intersection class? It can be later filled with values.

Besides neighbor sections, intersections and dead-ends, instances of a TransitionSymLane class or a TransitionSideLane class should also be considered as contents of the start and end attributes. But there we have the same problem as above, they do not exist yet at this time.

Linked lists allow inserting and removing items easily. So a TransitionSymLane or a TransitionSideLane can be inserted later once the numbers of lanes are set and the calculations are performed. Similarly, a future Footprint class or a PtStop class (for a public transport stop) can be inserted into a linked list that forms a Roadway class. I will write about those classes later.

I am not sure if I understand this correctly. Does the Roadway class group also include streets that are separated by instances of a TransitionSymLane class or a TransitionSideLane class, as shown here, or is Roadway somehow a replacement for what we had with the WayCluster class? Note that clusters do not yet exist at this stage.

A class Roadway holds a reference to a linked list that is made of instances of the classes Section, TransitionSideLane, TransitionSymLane, Footway, PtStop, etc. In the majority of cases it contains just a single instance of Section.

The class Street can be considered as a replacement of the class WayCluster. However in the majority of cases it contains just a single instance of the class Roadway.

It would be highly desirable to do clustering before assigning a PML style to an instance of the class Street, since a double-roadway street looks differently than a single roadway street.

This will work fine for linear cases, like those with the TransitionSymLane class or a TransitionSideLane class, as described above. But it will not work for clusters, because multiple way-sections may start from the same (clustered) intersection. Then, the start attribute will have to be a list.

Do you mean something like on the image below? The intersections at the start and at the end of an instance of the class Street are shown with the blue color.

image

vvoovv commented 11 months ago

However, maybe the question is whether this table should be moved to PML eventually, as these numbers may have some locale aspect.

Yes, that table should be moved to PML.

Using the function random_weighted to set the number of lanes and other attributes does make sense. All street categories have the most probable value of the number of lanes. But there are always exceptions. Other values of the number of lanes can also happen with a smaller probability.

vvoovv commented 11 months ago

This is now new to me. I searched for OSM objects tagged as crossing=* using overpass turbo and got something like this:

The tag crossing=* is applied only to nodes.

The result seem to be footways. What do you mean by "node indices of the cropped centerline where a sidewalk is located"? Are these the nodes of the trimmed centerline, between them a crossing footway intersects the centerline? Or are you talking about objects that are marked as sidewalk?

Let's consider the following intersection:

image

Suppose that the OSM way on the right starts in the center of the intersection. A node with the sidewalk marked with the red color has the index 2 in the OSM way. After generating the intersection, nodes with the indices 0 and 1 will be cropped. A new node with the index 0 will placed at the border with the the intersection. The node with the crosswalk will have the index 1 after cropping.

vvoovv commented 11 months ago

I suggest introducing a new data element Bundle for complex cases like on the image below:

image

An instance of the class Street is always composed of a chain of items represented by a chained list. For the above example: Section | SplitMerge | Bundle

An instance of the class Bundle defines parallel chains or threads or items. I don't know yet what is the proper name for that. In the example above a bundle would have: Section in the lower roadway and another Section in the upper roadway.

Consider a more complex example: image

Abbreviations used in the image: (S) - Section (C) - Crosswalk (PT) - PtStop (SM) - SplitMerge

The chained list for this case: Section | Crosswalk | Section | PtStop | Section | SplitMerge | Bundle

The chained list for the lower roadway of the Bundle: Section | Crosswalk | Section

The chained list for the upper roadway of the Bundle: Section | Crosswalk | Section | PtStop | Section

A Bundle can have another Bundle in its roadway.

Note that the class Roadway is not used anywhere in the examples. At the moment I am not sure if it is needed at all.

polarkernel commented 11 months ago

The tag crossing=* is applied only to nodes.

You are right, I did a mismatch in my overpass turbo query. We will need a new method in the WayManager class to query for these crossing nodes, similar to getAllVehicleWays().

I suggest using the attribute crosswalkNodeIndices in the class Section to store a Python list of node indices of the cropped centerline where a sidewalk is located. An OSM node with a crosswalk may be in the cropped part. In that case the index of the node with the crosswalk will be 0 or N-1, where N is the number of nodes in the cropped centerline.

It will be easy to derive this number from the trim parameter of the way-section's polyline.

polarkernel commented 11 months ago

How about using an empty Intersection class? It can be later filled with values.

Yes, this will be the solution.

Linked lists allow inserting and removing items easily. So a TransitionSymLane or a TransitionSideLane can be inserted later once the numbers of lanes are set and the calculations are performed. A class Roadway holds a reference to a linked list that is made of instances of the classes Section, TransitionSideLane, TransitionSymLane, Footway, PtStop, etc.

I assume you mean a linear, doubly linked list. But that requires that the position of all these objects (TransitionSymLane, TransitionSideLane, Footprint or a PtStop) has to be detected before this list is constructed. Otherwise, we risk, that a Section has to be split by one of these objects later:

| -------- Section --------|        =>        | ---- Section ----| --PtStop--| ---- Section ----|

It would be highly desirable to do clustering before assigning a PML style to an instance of the class Street, since a double-roadway street looks differently than a single roadway street.

In principle, the complete 2D topology has to be known before PML styles get assigned. This is possible, I think, but it is a major redesign.

Do you mean something like on the image below? The intersections at the start and at the end of an instance of the class Street are shown with the blue color.

Yes. You wrote:

The class Roadway should have an attribute start. It is the reference to the first street section (an instance of the class Section) in the roadway. The other street sections in the roadway can be accessed with the related linked list (the attributes start and end of the class Section).

On the right side of the drawing, there are two starts.

polarkernel commented 11 months ago

I suggest introducing a new data element Bundle for complex cases like on the image below:

I like this idea, and I also think the term Bundle fits the underlying structure well.

What I still don't really like is the special importance of an intersection. If I put an additional one to one of the arms of the bundle, a situation that occurs frequently, the structure gets split somehow, it is no more linear. While the Crosswalk in your illustration appears on both parallel ways of the bundle, an intersection can't do that:

However, I am afraid I do not have a reasonable suggestion as to how this could be improved.

vvoovv commented 11 months ago

I assume you mean a linear, doubly linked list.

Yes.

Otherwise, we risk, that a Section has to be split by one of these objects later: | -------- Section --------|        =>        | ---- Section ----| --PtStop--| ---- Section ----|

I don't consider splitting of sections as a risk. I consider splitting as an integral part of the workflow, since it's required to split the related Section to insert an instance of Crosswalk or PtStop. The calculations can be delegated to the Geometry Nodes, but then the trim lengths are needed as the input parameters for the GN-setup.

vvoovv commented 11 months ago

I forgot to describe the case of the lower arm of the bundle. Here we would have: Section | PartialIntersection | Section

polarkernel commented 11 months ago

I don't consider splitting of sections as a risk. I consider splitting as an integral part of the workflow ...

I am somewhat reluctant to use this seemingly simple solution of mapping all routes with linked lists. Let me try to explain my reasons.

The simple splitting of sections (list nodes) within a doubly-linked list is quite simple and well known. A problem arises when it is necessary to find all these sections at once. This is the case when they have to be inserted into a spatial index (for performance reasons). Then you have to search all of them along many linked lists, insert them into the index, and somehow provide a reference to find them backwards, when some of them are given as a result of an index operation (for example, find all neighbors of one of them). If any changes have to be made due to such an operation, the change is not only in the linked list, but also in the reference index. Of course this is possible, but it is quite complicated and prone to errors.

There are several tasks in the whole process, for instance building clusters or merging intersecting areas, where such situations occur. As I said, I had some concerns and therefore did not choose such approaches in my previous solution. But let's give it a try.

vvoovv commented 11 months ago

As I said, I had some concerns and therefore did not choose such approaches in my previous solution. But let's give it a try.

What are the alternatives? Perhaps there is a way to combine two approaches.

polarkernel commented 11 months ago

What are the alternatives? Perhaps there is a way to combine two approaches.

You have studied what it takes to use PML in a meaningful way. This way, I get very concrete requirements for the processes in StreetGenerator, and we establish a more detailed cooperation. Even though it means resetting and redesigning much of the development that has already been done, I like this situation. So let us try to find a solution.

Many of the previous ideas can be reused, perhaps in a slightly different form. I am wondering: Should we start a new branch so that the previous code is preserved even if it is no longer used? I already stored a lot of functions in the code that do not currently have any use.

vvoovv commented 11 months ago

I created the tag dev_before_street_pml pointing to the current version of the branch streets_for_gn. That's another way to preserve the code. Legacy functions can be kept in a dedicated Python module.

polarkernel commented 11 months ago

I like this idea, and I also think the term Bundle fits the underlying structure well.

I would like to take a closer look at the "bundle" concept. When we used clusters, these were constructed more or less together as cluster-way and cluster-intersection. Here are two examples of such cluster intersections, on the left the simple one (East of Karl-Marx-Allee scene) and on the right a more complicated one with four way section ends, two of which go underground (Moscow scene).

    

Intersection areas can only be calculated if the width of all way-sections is known, which is not yet the case when getStyle is called for PML processing. At this point, only for the first, simpler example (left image), it is known that every two paths with their endpoints belong to a Bundle.

    

My suggestion now is that I try to find the intersections that belong to these endpoints and define their center of gravity as the provisional node of a still incomplete intersection (red in the right image). Each of its connectors could then be a list of instances of the Section class, holding the way-section, that start at this (bundle) intersection.

But what to do with the sections marked by green lines? When we were working with clusters, in most cases they had to be deleted at the time when the area was constructed. But I'm not sure whether it would be safe to remove them before the getStyle call. On the other hand, it would be complicated to hold them using the single endpoint intersections in addition to the temporary clustered intersection. I'll have to think about that.

vvoovv commented 11 months ago

What if the largest possible roadway width is used to detect a cluster of roadways?

polarkernel commented 11 months ago

I am currently investigating structures that can be used locally in StreetGenerator, with which I can then create the desired class instances ready for a call to getStyle. In the meanwhile, a few new questions have arisen.

The first ones arise from the question we have already begun to discuss in issue #66. We need to define directions for the linear structures proposed in this thread, they should have a source (src) vertex and a destination (dst) vertex. Instances of the class Section should use the definition given by OSM: Forward is in the direction of the drawing (the order of the nodes) and backward is in the opposite direction. By the way: We should probably not forget the driving_side tag.

The question is, how shall we define the directions of the higher-level structures (Roadway, Bundle)? For Roadway, we could use the direction of the internal Section instances. But the same would not work always for a Bundle (draw direction in red):

If we were to use the x- and y-coordinate rules, the start coordinates of the Roadway instances could sometimes be on opposite sides of the bundle.

polarkernel commented 11 months ago

At the call to getStyle, do the lane attributes of a Section instance already need to be computed?

        self.isOneWay = False       # True if one-way road.
        self.totalLanes = None      # Total number of lanes, includes bothLanes
        self.forwardLanes = None    # Number of forward lanes
        self.backwardLanes = None   # Number of backward lanes
        self.bothLanes = None       # Number of lanes that allow a turn available in both directions (tag lanes:both_ways)
polarkernel commented 11 months ago

I already often flirted with using the library networkx for various network tasks in the blosm addon. But I didn't know how to install the library inside Blender, since pip install is not possible. But now, I found an article here, showing how easy it can be. In principle, it is sufficient to import a specific folder with pure Python code, similar as we did with ANTLR4 for PML, for example. I tested it and it works fine.

So I decided to base the refactoring of the StreetGenerator on this library. Perhaps it would make sense to rewrite some older code later, if it is based on graphs and networks.

vvoovv commented 11 months ago

At the call to getStyle, do the lane attributes of a Section instance already need to be computed?

It's not required.

vvoovv commented 11 months ago

I already often flirted with using the library networkx

I see the packages scipy and pandas in the dependency list. Do the modules of networkx which you used in your tests, import those packages? Can networkx be just copied to blosm folder and used as-is?

Installing external packages for Blender's Python can be very tricky taking into account a broad user base of the addon.

vvoovv commented 11 months ago

The question is, how shall we define the directions of the higher-level structures (Roadway, Bundle)?

At the moment I can't propose for bundles anything else besides the XY-coordinates rule. The details of the calculation can be hidden in a method getDirection or similar. The practice will show which method to determine the direction will be the best.

polarkernel commented 11 months ago

I see the packages scipy and pandas in the dependency list

In my (small and short) tests, using a copy of NetworkX in a local folder worked fine without any problems. I wasn't even aware of these dependencies (so thanks for your check). Somewhere in the NetworkX documentation, I found the text:

There are no dependencies for NetworkX’s core functionality, such as the data structures (Graph, DiGraph, etc.) and common algorithms, but some functionality, e.g. functions found in the networkx.linalg package, are only available if these additional libraries are installed.

I will now spend some time investigating the possibility of creating a core version of this library using only pure Python. Once I see such a possibility, I will see if it is complex enough to solve my problems. If so, I could save a lot of time.

vvoovv commented 11 months ago

Have you compared the performance of NetworkX with your code?

polarkernel commented 11 months ago

Have you compared the performance of NetworkX with your code?

I do not have code of my own yet. What I need is a directed multigraph structure, that can store objects (Intersection, TransitionSymLane, TransitionSideLane, Footprint, PtStop, ...) as nodes and objects of Section as edges. My existing network code does not provide this. NetworkX would provide that "for free", including the base for a "split section" algorithm.

But maybe I'll take some inspiration from the NetworkX code for my own code. The first experiments to create a core version were not very promising.

vvoovv commented 11 months ago

I created the tag dev_before_street_pml pointing to the current version of the branch streets_for_gn. That's another way to preserve the code. Legacy functions can be kept in a dedicated Python module.

The command git pull origin --tags can be used to get the tags from a remote repository.

vvoovv commented 11 months ago

An instance of the class Bundle defines parallel chains or threads or items.

I suggest naming them items. The items are ordered from left to right along the direction of a bundle.

polarkernel commented 11 months ago

But maybe I'll take some inspiration from the NetworkX code for my own code. The first experiments to create a core version were not very promising.

Finally, I was able to create a version of NetworkX that excludes all unwanted dependencies and works fine for my purposes. I renamed it to _blosmnetworkx and added it to our lib folder. The new code, which already constructs a way-map with empty intersections, is committed. All the classes required to hold the new objects are collected in a new folder way/waymap. I will fill them with life, one by oner.

polarkernel commented 11 months ago

So far, we have defined several types of objects, which I have called nodes and which are collected in the way/waymap/nodes folder. To build a map, all these objects have a location attribute, even though they may actually be areas. location is the search-key to finding them in the way-map:

Intersection, PartialIntersection, SideLane, SymLane, Crosswalk, PtStop, DeadEnd

Some of these nodes may have multiple connections, so we need to define something similar to the connectors, that we had before. Then we need three line objects, each with a source attribute src and a destination attribute dst, which are the locations of nodes and together are used as keys in the way-map:

Section, Roadway, Bundle

In most cases, a Roadway will contain only a single section, but it can also contain a sequence of sections. . We defined that the Section class has two attributes start and end, which hold references to the preceding and following objects. Note that these are not the same as the location src and dst attributes. Since these form a doubly linked linear list, I would prefer to call these attributes pred, for predecessor, and succ, for successor.

All nodes, except DeadEnd, usually split their section. The objects Intersection, PartialIntersection, SymLane and Crosswalk become an area, so that their connecting sections must be trimmed. SideLane is just a tool to render turning lanes. I do not know yet if PtStop will split its section.

It is still unclear to me where a Roadway sequence ends when more than one section is used. Is it only at Intersection and PartialIntersection, while the other nodes are included in the Roadway? Let us discuss some of my questions using the following example:

Intersections and partial intersections are blue. I have replaced your SplitMerge object in the middle with an Intersection object, as it was done before for clusters. To the left of this object, my question is now: Should the crosswalk or the bus-stop or both be included in a Roadway object? On the right, can a Bundle be constructed somehow (in the old implementation, without crosswalk and bus-stops, this was a cluster). Where does the Crosswalk belong to?

vvoovv commented 11 months ago

Finally, I was able to create a version of NetworkX that excludes all unwanted dependencies and works fine for my purposes.

It would be good to describe it briefly how to get this version.

a way-map

I suggesting adding the definition of a way-map to our section Definitions.

polarkernel commented 11 months ago

It would be good to describe it briefly how to get this version.

The version of _blosmnetworkx in the lib folder of the blosm addon is based on the latest release 3.2.1 of NetworkX downloaded from its GitHub repository on 12/16/2023. Only the code in its folder networkx is used.

Blender does not support the scipy and pandas packages, which are part of the NetworkX requirements. Therefore, we have reduced our version (_blosmnetworkx) by removing all files in it, that use functions from these packages or derivatives of methods that use them.

In detail, we did:

polarkernel commented 11 months ago

I suggesting adding the definition of a way-map to our section Definitions.

The way-map, as I intend to use it, does not fit into these (by the way very old) definitions. It is just a tool of mine to keep all objects in a single structure. It has two main purposes. First, it should be a factory for any linked lists you want to have. Second, it should allow me to perform operations, such as splitting ways, without needing to find the same object in multiple structures. It should be a solution to the problem mentioned here. At present, its functionality is still rather unclear and experimental.

What about the new definitions Intersection, PartialIntersection, SideLane, SymLane, Crosswalk, PtStop, DeadEnd, Section, Roadway, Bundle?

vvoovv commented 11 months ago

I suggest moving modules from way/waymap/nodes and way/waymap/section to way/items like it's done for buildings.

vvoovv commented 11 months ago

What about the new definitions Intersection, PartialIntersection, SideLane, SymLane, Crosswalk, PtStop, DeadEnd, Section, Roadway, Bundle?

I like them. At the moment I am not sure if the item Roadway will be needed at all.

polarkernel commented 11 months ago

I suggest moving modules from way/waymap/nodes and way/waymap/section to way/items like it's done for buildings.

Done.

polarkernel commented 11 months ago

If you ever get some time: I could use a manager to find the nodes for crosswalks and public transport stops from the OSM data. I think this can't be done using theWayManager, or am I wrong?

vvoovv commented 11 months ago

Some of these nodes may have multiple connections, so we need to define something similar to the connectors, that we had before. Then we need three line objects, each with a source attribute src and a destination attribute dst, which are the locations of nodes and together are used as keys in the way-map: Section, Roadway, Bundle

The existing class Intersection can be used for now. I don't understand what is meant under three line objects.

Note that these are not the same as the location src and dst attributes.

How will the attributes src and dst be used?

I would prefer to call these attributes pred, for predecessor, and succ, for successor.

How about calling them prev and next?

I do not know yet if PtStop will split its section.

A PtStop can split the adjacent sections if it has a special marking on the roadway and/or a bus bay as shown at https://github.com/prochitecture/blosm/issues/76#issue-2042341403

It is still unclear to me where a Roadway sequence ends when more than one section is used. Is it only at Intersection and PartialIntersection

A Roadway can end at Intersection. It can't end at PartialIntersection.

I have replaced your SplitMerge object in the middle with an Intersection object, as it was done before for clusters.

I thought SplitMerge and Intersection are different. A Street can't end at a SplitMerge. A Roadway can be split into a number of items at a SplitMerge or several items of a Bundle can be merged into a single Roadway at the SplitMerge.

Should the crosswalk or the bus-stop or both be included in a Roadway object?

Yes.

On the right, can a Bundle be constructed somehow (in the old implementation, without crosswalk and bus-stops, this was a cluster). Where does the Crosswalk belong to?

A Bundle can be considered as an upgraded version of a Cluster. Without crosswalks and pt-stops we would have:

The Crosswalk belongs to both roadways.

polarkernel commented 11 months ago

The existing class Intersection can be used for now. I don't understand what is meant under three line objects.

I had some trouble with the language. Unlike nodes, which are local objects, Section, Roadway, and Bundle have a length and are similar to a line. So I called them line objects. Linear did not seem correct to me, as it somehow means straight to my understanding. I couldn't find any better term.

How will the attributes src and dst be used?

They will be instances of mathutils.Vector and will only be used as keys in the way-map structure, that inherits from MultiDiGraph, a class of the blosm_networkx.

How about calling them prev and next?

I wanted to avoid that, because next is a Python keyword. Note that in contrast to src and dst, these are references to objects.

A PtStop can split the adjacent sections if it has a special marking on the roadway and/or a bus bay as shown at https://github.com/prochitecture/blosm/issues/76#issue-2042341403

You say "can split", and, in https://github.com/prochitecture/blosm/issues/76#issuecomment-1856469792, "The related Section may be split ...", both ambiguous, therefore my question. What construction with Section should it be, if not split? What are the rules for when to split and when not to split?

A Roadway can end at Intersection. It can't end at PartialIntersection.

I will need a recipe on how a Roadway (and a Bundle) is constructed.

I thought SplitMerge and Intersection are different. A Street can't end at a SplitMerge. A Roadway can be split into a number of items at a SplitMerge or several items of a Bundle can be merged into a single Roadway at the SplitMerge.

We never had a SpliMerge until now, this term is new. I can't imagine a situation, where a Bundle gets merged into a single Roadway. What we had until now was a SymLane, which connected two way-sections with different width, using an area (-> split), or an IntersectionCluster, which was the intersection at the end of a cluster. Something like this:

vvoovv commented 11 months ago

So I called them line objects.

A pt-stop is also a line object, it may have a noticeable length. It's another reason why I proposed to move all of them to the directory items.

I would prefer to call these attributes pred, for predecessor, and succ, for successor.

Ok, let's use the names pred and succ.

What construction with Section should it be, if not split? What are the rules for when to split and when not to split?

A PtStop splits its section if there is a special marking on the roadway and/or a bus bay. There is no need to split the section if a pt-stop is only marked with a pole on the sidewalk. That will be defined in the PML style.

I will need a recipe on how a Roadway (and a Bundle) is constructed.

The construction of Roadways can skipped for now. I suggest considering ambiguous cases for the constructions of Bundles.

We never had a SpliMerge until now, this term is new.

An example of a possible class SplitMerge can be found at _berlin_karl_marxallee.osm on Strasse der Pariser Kommune. The image below was rotated.

image

vvoovv commented 11 months ago

If you ever get some time: I could use a manager to find the nodes for crosswalks and public transport stops from the OSM data. I think this can't be done using theWayManager, or am I wrong?

The code to detect and process crosswalks and pt-stops must be developed. I suggesting discussing that in #73 and #76.

polarkernel commented 11 months ago

An example of a possible class SpliMerge can be found at berlin_karl_marx_allee.osm on Strasse der Pariser Kommune. The image below was rotated.

OK, we can introduce the additional class SplitMerge. The problem for the example at the Strasse der Pariser Kommune is the distance between the end of the Bundle and the position of the intersection of the OSM-ways, here shown as a result of the old implementation using clusters:

The cluster (green area) ends where the ways are no more parallel (red dots). From there, the intersection of the OSM-ways (yellow dot) is more than 30 m away. It is now a matter of heuristics whether such a long distance is accepted as a single area connected to the cluster or not.

The SplitMerge class will have an area polygon and three connector-like records as attributes, just like an Intersection. It could be defined as a special intersection, that merges two one-way Sectionsof opposite directions within a Bundle into a two-way Section. Some kind of maximum size for such a structure will have to be defined.

vvoovv commented 11 months ago

Below is the example of a pure N-to-1 merge at Tijuana border crossing. There is also a pure 1-to-N split next to this spot.

image

vvoovv commented 11 months ago

Nevertheless, the class still can be named as SplitMerge.