prochitecture / blosm

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

[GN][streets] First steps towards streets and intersections using GN #44

Open polarkernel opened 2 years ago

polarkernel commented 2 years ago

The results from the construction of trimmed way-sections and intersection polygons have to be adapted for the use with objects based on geometry nodes. Let's discuss here the details of this task.

vvoovv commented 2 years ago

I'll take a look into this issue.

vvoovv commented 2 years ago

I was unable to reproduce the issue. I commented out footway, cycleway, path in roadwayIntersectionCategories. Perhaps you can commit your changes.

polarkernel commented 2 years ago

I was unable to reproduce the issue. I commented out footway, cycleway, path in roadwayIntersectionCategories. Perhaps you can commit your changes.

I reverted to the committed version and then the error has gone. It seems that I changed something unintentionally. Sorry for the inconvenience.

Something else: Today I fixed an old bug in the way-network, where in rare cases way-segments were not inserted into the net. I also corrected this in the branch _streetsintersections. But it was not possible for the branch dev, as I never updated this branch since the creation of the newer branches and the network class is different there. However, all command line arguments of dev work in the newer branches. Will it be required to update dev?

vvoovv commented 2 years ago

I'll merge the branch streets_for_gn into dev once the the work is done.

On another note. I added the attribute self.railway to the class Way in the branch streets_for_gn.

polarkernel commented 2 years ago

On another note. I added the attribute self.railway to the class Way in the branch streets_for_gn.

Thanks!

vvoovv commented 2 years ago

I have a concern about partial intersections when a way-segment intersects only some of the way-sections in a way-cluster.

image

In this case I suggest to extend the intersection to all way-segments in the way-cluster. Do distinguish it from the full intersection, a separate class (for example PartialIntersection) can be used for that case.

vvoovv commented 2 years ago

Another concern is the case with a big distance between the carriageways due to a separator. Extruded way-sections won't overlap here.

image

polarkernel commented 2 years ago

In this case I suggest to extend the intersection to all way-segments in the way-cluster. Do distinguish it from the full intersection, a separate class (for example PartialIntersection) can be used for that case.

You are right, I didn't think on such cases. Maybe, we may even have to define some kind of intersection templates, should there be more cases different to this one.

polarkernel commented 2 years ago

Another concern is the case with a big distance between the carriageways due to a separator. Extruded way-sections won't overlap here.

I don't know yet. Eventually, the width of the expansion should be related to the category and the number of lanes of the ways. My main concern that led me to clusters were overlapping ways. Is it in such cases required to have clusters?

vvoovv commented 2 years ago

Is it in such cases required to have clusters?

The carriageways in that example (Karl-Marx-Allee) form a cluster in the reality.

If the cluster is formed in the code, than it's easy to understand that the space between the carriageways must be filled in with something (e.g. grass). A check of the difference between the whole width of the cluster and the sum of the widths of the carriageways would be enough for that. So a cluster would be highly desirable.

If a cluster wasn't created, then a boolean difference operation would be required between the area of the graph-cycle and the areas of the carriageways.

polarkernel commented 2 years ago

If the cluster is formed in the code, than it's easy to understand that the space between the carriageways must be filled in with something (e.g. grass).

I see. Then let's aim that. Most often, such cases are one-way roads. Maybe then, the algorithm could explicitly search for a way in the counter direction.

polarkernel commented 2 years ago

I have currently another concern. Do you know an algorithm that is able to clip a polyline by a concave polygon? All algorithms I already have implemented, or that I know else, work only for convex polygons, but in the curved case, the extruded polygon is concave.

vvoovv commented 2 years ago

Do you know an algorithm that is able to clip a polyline by a concave polygon?

If this concave polygon is created by extruding a polyline, then I suggest to divide this extruded polyline into convex segments. Each segment represent the related way-segment.

polarkernel commented 2 years ago

I'm sorry, but there is a delay again. The algorithm that expands way-segments sometimes produces spikes in the order of a few micrometers:

So far, these bugs have not been noticeable anywhere because they are so small. For clipping, however, they are now massively disturbing. I will first have to debug the expansion algorithm. Maybe once again a floating point precision problem.

polarkernel commented 2 years ago

The "micro-spike" bug is fixed and committed. As expected, it was a floating point precision problem.

Btw., I wrote my own version of a polyline clipper that works with any (except self-intersection) type of polygon as clipping window. A further search for alternatives is no longer required, it works quite efficient for all the small polygons produced by expansion of way-segments.

polarkernel commented 2 years ago

Just a teaser, still far from applicable and light-years from being finished, but it's the best we ever had.

vvoovv commented 2 years ago

It looks encouraging. However glitches area also visible.

I added the file _streets/piestanynorth.osm to test some interesting cases.

polarkernel commented 2 years ago

However glitches area also visible.

I know, many more rules will be required. For instance, the two glitches in _berlin_karl_marxallee.osm were service ways that were in the search range of a secondary road. There will be definitions on which categories can cluster with others and on what distances. However, I am convinced that a quite reliable solution will be possible using this new method. Too bad I didn't have the idea much earlier.

I'm doing interim reports more often now, even on unfinished states, so that we have a chance to coordinate, and so that you can control the development according to your requirements.

When neighbored parallel ways are grouped to a cluster, we get cluster-sections, which will replace the individual ways:

Some of the emerging clusters look quite nice, and also curved ones are easily possible (I rotated some images so that the clusters are horizontal, to save space):

One of the tasks to be solved now will be to order the insides of the clusters. They will need a direction (begin and end), a center line, and a list of the way-section categories, for instance from left to right. Additionally, there will be partial intersections to be defined, as you already proposed. One-way roads will need a direction relative to the cluster direction. The dots in the image below belong to intersecting ways of low category (currently, I only used "drivable categories").

I am also convinced that it will be possible to construct clustered intersections. At the moment, however, I do not yet know how. To construct them, the width of the cluster on both ends must be defined, so that the connectors of the intersection areas can be constructed. Here are some examples:

Some will need a special treatment:

Before I go any further, I would like to coordinate with you on some problems. There are two main issues: Inner structures and changing widths. Inner structures are details within the cluster, that are not represented by the structure I described above. An example:

How do we want to handle them? Ignore them and limit ourselves in terms of reality? What do you think about these?

The second issues are changing widths of the cluster:

The second example could possibly be solved by not making a cluster there. But what for the first one?

And a final question: How shall bridge and tunnels be handled?

vvoovv commented 2 years ago

Too bad I didn't have the idea much earlier.

Yes, simple and reliable solutions are coming at the end. I think this method can also cluster dead end and isolated ways.

How do we want to handle them? Ignore them and limit ourselves in terms of reality? What do you think about these?

Let's ignore the inner structures for now and return to them later.

The second issues are changing widths of the cluster:

Just thinking aloud. Detect somehow that the distance between the neighbor ways in the cluster has changed.

And a final question: How shall bridge and tunnels be handled?

I suggest to ignore them for now and return to them later.

polarkernel commented 2 years ago

Thanks for the feedback. I need some more:

How do we want to handle them? Ignore them and limit ourselves in terms of reality? Let's ignore the inner structures for now and return to them later.

OK, then I will search for all the ways that lead from one end to the other and ignore the others. In my example, four ways would remain.

The second issues are changing widths of the cluster: Just thinking aloud. Detect somehow that the distance between the neighbor ways in the cluster has changed.

As usual, things are quite complicated. The detection is no problem. The top case is one, where heavy overlap occurs:

In such a case, it would be favorable to keep the required width over all the length. But then, we risk having collisions with buildings or something else.

For the lower case (the transition to the roundabout), I have ideas on how to solve that using a special intersection area that connects the cluster with the two single ways. We would just need to synchronize the distances between the ways in the cluster (determined by the renderer) and outside (see also below).

And a final question: How shall bridge and tunnels be handled? I suggest to ignore them for now and return to them later.

What would you prefer for now, ignore them completely or compute the intersections. Here two examples, on the left with computed intersection and on the right when bridge and tunnels are ignored:

Finally, a new aspect came up when thinking about the creation of intersection areas between way-clusters or transitions between way-clusters and single way-sections. To define the connectors, the width of the connector and the way-cluster must be identical. For transitions between clusters and single ways, even their positions must be synchronized. However, the layout of the ways for a way-cluster will be defined by the renderer. Don't know yet how we can coordinate that. Would it eventually be possible to define a common function or algorithm, that can be accessed from both?

vvoovv commented 2 years ago

OK, then I will search for all the ways that lead from one end to the other and ignore the others.

However an inner way may be a part of an intersection.

In such a case, it would be favorable to keep the required width over all the length. But then, we risk having collisions with buildings or something else.

We can start from keeping the constant width along the whole way-cluster.

What would you prefer for now, ignore them completely or compute the intersections.

Let's ignore them completely for now.

Finally, a new aspect came up when thinking about the creation of intersection areas between way-clusters or transitions between way-clusters and single way-sections.

Could you make a drawing to illustrate this problem?

polarkernel commented 2 years ago

However an inner way may be a part of an intersection.

I agree.

Could you make a drawing to illustrate this problem?

Let me try to explain this using the example of the ways immediately before the roundabout in _berlin_karl_marxallee.osm. The ways on the right (red) are detected as cluster, while on the left (black) the ways need to be separated because of large distance changes between them:

Within the cluster (orange area below), the renderer will distribute the ways (green) around the cluster's centerline (dashed), so that it can construct a grass strip in the middle at the same time. On the left, the way-positions (blue) are given by their centerlines from OSM. The problem is now to fit both in the transition area, which here will become an intersection area. Some coordination will be required between the renderer and the constructor for the intersection area, so that the connectors to the right are on the correct place.

The problem becomes even more difficult, when cycle ways and footways are also part of the cluster (which would be possible with the new method), as was once originally anticipated. In general, it has to be solved on all cluster ends, except when they can be connected to other clusters.

This can also cause problems for the construction of intersections within the cluster. Either these are described by the intersection with the centerline of the cluster (left in image below) and the renderer takes care of the correct position, or the constructor of the intersection area needs to know where the way is positioned within the cluster:

vvoovv commented 2 years ago

Finally, a new aspect came up when thinking about the creation of intersection areas between way-clusters or transitions between way-clusters and single way-sections.

For now I suggest to go without any adjustments between the neighboring clusters.

vvoovv commented 2 years ago

I'd like to post some thoughts about the related data structures.

A WayCluster class should contain:

A split (or join) event can happen with a way-cluster as you describe in your previous message. The way cluster can be split into 2 or more way-clusters or separate way-sections. It may be required to adjust the way-sections that enter the way-cluster, with the way-sections in that way-cluster.

polarkernel commented 2 years ago

A list of the tuples for each way-segment (way-segment, the width of the way-segment, distance of the way-segment's centerline from the left border of the cluster).

The distance of the way-segment's centerline from the left border would possibly keep overlaps, if there are in the original map. Will the renderer take care of them and adapt the widths?

A split (or join) event can happen with a way-cluster as you describe in your previous message. The way cluster can be split into 2 or more way-clusters or separate way-sections. It may be required to adjust the way-sections that enter the way-cluster, with the way-sections in that way-cluster.

I am not yet sure if we are on a good track with these clusters. Let me explain using the (extreme) example of one of the clusters in _moscow_leningradskiprospekt.osm. The (larger) red dots show positions, where ways from the side produce T-intersections with the outermost ways in the cluster. Below the satellite image to have the realistic sight for comparison (not exactly adjusted).

 

The outermost ways will therefore consist of many short way-sections, while the inner ways are single way-sections over the whole length of the cluster. When we split the cluster at all the positions of the T-intersections, we get cluster parts that are sometimes less than 10 m long, also for the inner roads. Is this your idea? Could those T-intersections possibly be constructed as GN-intersections, like streetlights?

By the way, currently I try to construct the centerlines of the ways in the clusters, what has turned out to be quite a challenging task. It will take a while until I will have a solution.

vvoovv commented 2 years ago

The distance of the way-segment's centerline from the left border would possibly keep overlaps, if there are in the original map. Will the renderer take care of them and adapt the widths?

Yes, it will.

Is this your idea? Could those T-intersections possibly be constructed as GN-intersections, like streetlights?

No. I meant spits/joins with the Y-shape like in your example above.

At the moment I can't propose anything else besides extending partial intersections to full intersection and dividing the cluster into a number of smaller clusters which can be less than 10 meter long.

polarkernel commented 2 years ago

At the moment I can't propose anything else besides extending partial intersections to full intersection and dividing the cluster into a number of smaller clusters which can be less than 10 meter long.

OK, let me try to reach at least that. Then we see further.

polarkernel commented 2 years ago

I committed a lot of code around cluster construction, just to have a backup and avoid risk to lose it. Its usage is currently inhibited, only those functions work, that already existed before. I hope that I didn't forget matplotlib statements anywhere.

polarkernel commented 2 years ago

The time is running, but the progress remains small, here is another intermediate report. Again, also the new method is more complicated than I first thought. It's just hard when my eye can see the solution in a fraction of a second, but the code absolutely won't do it. It is a tradeoff between filtering the outliers and keeping the important parts. After an extensive tuning of the process, the clusters can be found correctly in many cases:

The red dots are either intersections or positions, where the number of lanes changes, often as a combination of the start of a turn lane and the subsequent Y-intersection. At all these positions, the cluster will have to be split. The clusters, where the ends are not aligned at the same distance, are a problem:

Sometimes, there are gaps in the ways, that need to be connected:

While other gaps are due to clustered intersections:

I have not yet found a way to filter outliers, e.g. in the example above there is a short path on the right side that needs to be removed. Often there are ways that run parallel for a long time and then turn away or do not follow the other paths. Others connect at end points. How can those be detected, any idea?

I didn't yet care about intersections of clusters. There too will be a great variety of issues to be solved, like overlapping cluster roads, or clusters, that "blow up" at the intersection:

      

vvoovv commented 2 years ago

Sometimes, there are gaps in the ways, that need to be connected:

What is located in those gaps?

polarkernel commented 2 years ago

What is located in those gaps?

In the upper example a way that was too short to be selected, in the lower example a nest of short ways and intersections, that belong to an intersection cluster. For the first case, a post-processing is required to find the connection.

vvoovv commented 2 years ago

Why is it required to filter out the short ways?

polarkernel commented 2 years ago

Why is it required to filter out the short ways?

They produce a lot of false alarms in the region of intersection clusters. Inserting them in rare cases like shown produces lower cost than filtering the false alarms, which are numerous.

polarkernel commented 1 year ago

While working on the way clusters, I came across a problem that we need to discuss. In the scene _berlin_karl_marxallee.osm, there is a curved way-cluster (indicated by the red arrow in the left image below) whose width changes along the cluster. The right image shows the extracted way sections (black) and their cluster centerline (red).

   

The question is now, how do we like to treat such clusters? I see four possibilities:

vvoovv commented 1 year ago

By the way, the width of the way-cluster changes again in the straight part of this street.

image

vvoovv commented 1 year ago

Could you please illustrate the options 2 and 3?

Is the following option feasible? We split a cluster with the variable width into a number of clusters with constant width and create the transitions for those sub-clusters.

vvoovv commented 1 year ago

The right image shows the extracted way sections (black) and their cluster centerline (red).

How is the centerline calculated? Or was it drawn manually?

polarkernel commented 1 year ago

Could you please illustrate the options 2 and 3?

Let me try. My illustration depends on your proposition on the structure of the class WayCluster. Below, in the left images, I have illustrated the situation for a "standard" cluster of equal width, as I understand it now. The orange plane illustrates the cluster area, given by its center line (red) and the distances of the centerlines of the ways, given at the cluster start and measured from the left border of the cluster. Note that the centerline may be curvy (examples see here), I was just not able to draw that in reasonable time. The way I thought of it, the addon calculates the curves that follow the curvy center line from this data, and from these curves, the roads are generated.

The idea to option 2 is illustrated at the right. The distances to the ways are not only given at the start of the cluster, but also at the end, where they are different. The addon then should create curves that follow the cluster centerline in an increasing distance and reach finally the distances at the end of the cluster.

In option 3, the whole original polylines of the ways are given as a base for the curves.

Is the following option feasible? We split a cluster with the variable width into a number of clusters with constant width and create the transitions for those sub-clusters.

This is feasible. Don't know how realistic this would look like. We would have to define a maximum step width limit between the split clusters. Note that almost none of the clusters have really a constant width, it depends on the accuracy the operator applied when he drew them, but below this step width, it will not be perceptible.

polarkernel commented 1 year ago

How is the centerline calculated? Or was it drawn manually?

The centerlines are computed using a Delaunay triangulation.

vvoovv commented 1 year ago

I'd prefer to have a transitions between street parts with different width. Later I can experiment with different methods to represent the transition in Blender.

A threshold for the cluster width change should be used to detect a transition.

By the way, how do you detect the width change of a cluster?

polarkernel commented 1 year ago

I'd prefer to have a transitions between street parts with different width. A threshold for the cluster width change should be used to detect a transition.

OK, I will implement this.

By the way, how do you detect the width change of a cluster?

I did not yet implement that. I think I will use distances along lines perpendicular to the centerline of the cluster.

polarkernel commented 1 year ago

Some first impressions of the stepwise width change of a cluster. Let me assume that the width difference between the ends of the cluster is ΔW and the length of the cluster is L. When we allow a maximal width change of dW per step, the number of steps Ns becomes Ns = ceil(abs(ΔW/dW)). The length of the Ns+1 cluster segments between these steps is then L/(Ns+1). The change in width per step becomes sW = ΔW/Ns. It needs a certain transition length tL, which I set to tL = 4*sW so that the transition is not abrupt.

The construction of the transition area is depicted in the image below. The centerline of the cluster is split at the step position and trimmed back by tL/2 on both sides (red parts). The widths of the two cluster segments are set to w1 and w2, so that the difference w2-w1 = sW is the step width. The transition area is now defined by the lines perpendicular to the centerline at the trimmed ends of the cluster (green area).

As examples, here are the results for the curved cluster from _berlin_karl_marxallee.osm for step widths dW of 0.5, 0.75 and 1.0 m (from left to right):

The wobbling of the directions comes from the slopes of the segments of the centerline. Although the method of computation is quite good, errors on the drawing of the OSM segments are transferred to the centerline. However, I propose to keep this described method for now.

vvoovv commented 1 year ago

As examples, here are the results for the curved cluster from _berlin_karl_marxallee.osm

How would it look like for the cluster width change on a straight segment? There is one right to the south from that curved segment.

polarkernel commented 1 year ago

How would it look like for the cluster width change on a straight segment? There is one right to the south from that curved segment.

I can show this only for the upper way-section of this cluster, because for the lower, the number of lanes is changing, thi case is not a split and is not yet implemented. From left to right, for the step widths dW of 0.5 and 0.75 m, it looks like depicted below, for dW as 1 m, there is again only one step.

polarkernel commented 1 year ago

I am currently implementing cluster splits at the ends of way-sections within a cluster. These occur, when there is an intersection with only one way from the side of a cluster, or, as it is the case for the lower cluster of the last post, at changes of only one's way width, maybe due to altering the number of lanes. For both, there are two ways to solve this.

For single intersections, the centerline of the cluster is split and trimmed to both sides. The intermediate space may (upper image) then be filled with an intersection area (bluish) and a connector to the intersecting way, or an ordinary intersection, as for single ways is created (lower image), while the second way is connected by a short piece of a way (blue):

Similar, changes of widths of a single way may be filled with a complete transition area (upper image) or, similar to the intersection, a transition area is constructed and a short piece of a way (lower image):

Which version would you prefer?

vvoovv commented 1 year ago

Which version would you prefer?

Both :). It should be defined by an input parameter to the method or class constructor.

The configuration below is also possible. Again, the resulting configuration can be defined by an input parameter.

image

vvoovv commented 1 year ago

What are the reasons to use stepwise transition instead of a single transition?

polarkernel commented 1 year ago

Both :). It should be defined by an input parameter to the method or class constructor.

OK, let your wish be my command :)

The configuration below is also possible.

OK, but in this case, the centerline of the wider way will no more be on the OSM centerline.

polarkernel commented 1 year ago

What are the reasons to use stepwise transition instead of a single transition?

It seems that I misunderstood your proposition:

A threshold for the cluster width change should be used to detect a transition.

I understood the threshold value as maximum. It is naturally possible to create a single transition, preferably at the wider end, to minimize the risk of collisions with other objects. For the example object at _berlin_karl_marxallee.osm, the width change is little more than 4 m. For a length of four times of this change (to make the transition not too steep), a transition area with a length of more than 16 m would result, directly followed by the cluster intersection area on the top end of the cluster. This total area might look overly large, but perhaps better than the stepwise transitions.

vvoovv commented 1 year ago

This total area might look overly large, but perhaps better than the stepwise transitions.

It would be interesting to see how this total area looked like.