prochitecture / blosm

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

T-shape intersections #103

Open vvoovv opened 4 months ago

vvoovv commented 4 months ago

I have to process T-shape intersections in Geometry Nodes.

What are tricky points in processing them?

How do you treat the case if the widths of two collinear street sections at a T-shape intersection are different?

polarkernel commented 4 months ago

What are tricky points in processing them?

There are many tricky points in this task. Let me illustrate the main idea I introduced. The process starts by computing the intersection of the boundaries of two adjacent ways (I didn't distinguish between T-shape and general intersections). This is done by the function offsetIntersection() (_lib/CompGeom/offsetintersection.py).

Let me illustrate the method:

Two segments of two ways are given as leaving edge vectors e0 and e1. These vectors are each given a tuple (v0,v1) of their end positions. It is not assumed that these are the first segments of the way's polyline, it's a general method. The values w0 and w1 are half the widths of the ways.

The construction of the buffer intersection is inspired by the motion vector in a weighted straight skeleton algorithm. The computation is adapted from the master thesis of Gerhild Grinschgl, 2016, page 39ff (it's in German). I don't explain the details here, we can do that later. The intersection point is accepted as "valid", if it is inside the normals (red lines) at the top of the edges, otherwise it is classified as "out".

Using this computation, the function offsetPolylineIntersection() (also _lib/CompGeom/offsetintersection.py) constructs the "best" intersection point for the polylines of two leaving ways of an intersection.

A next step is the construction of the connectors. This is also done for a general intersection with an arbitrary number of leaving ways. It is done in the method processIntersection() of the class Intersection (way/item/intersection.py). It takes any three adjacent ways as left (blue), center (green), and right (red) way:

The three characteristic points of the connector are computed as follows. The intersection of the boundaries of the right and the center way, computed by the method described above, gives the point p1. The intersection of the left and the center way gives the point p3. These are both projected onto the center line of the center way (red arrows). The one with the farthest projection is projected onto the other side of the way (blue arrow) and gives p2. The triangle p1-p2-p3 forms the connector for the center way. This procedure is repeated for each way as center way and finally forms the intersection area.

How do you treat the case if the widths of two collinear street sections at a T-shape intersection are different?

This case is detected by offsetPolylineIntersection(). The computation of p1 or p3 is changed in this case. From the difference of the widths w0 and w1 and a transition slope (currently 0.3 m/m), a transition width is computed and the point p1, for the depicted example, is set at this distance:

The transition width is limited to minimal 1 m and a maximum of half of the polyline length og the center way. The point 'p' in this image is an intersection point p2 or p3, that is computed when the right way becomes a center way.

vvoovv commented 4 months ago

The intersection point is accepted as "valid", if it is inside the normals (red lines) at the top of the edges, otherwise it is classified as "out".

But the normals to the blue and red centerlines in the second image above, do not intersect!

polarkernel commented 4 months ago

But the normals to the blue and red centerlines in the second image above, do not intersect!

This is not necessary. The intersection, computed from the red and green centerlines, gives p1, and the one computed from the green and the blue centerlines results in p3. In both cases, the normals intersect. Note that the centerlines are given by polylines and can consist of several segments and be curved. The method described in the first image is applied to two segments of them. The computation for polylines starts with the first segments of the intersection and continues through all combinations of segments, until a good intersection is found. In most cases, this will be the first intersection.

vvoovv commented 3 months ago

image

How is the the intersection polygon generated for the bottom part marked with the red color?

vvoovv commented 3 months ago

image

How would you treat the case when offset centerlines do not intersect? After offsetting: 1 -> 1' 2 -> 2' 1' and 2' do not intersect

It's an intersection of Koppenstraße and Friedenstraße in _berlin_karl_marxallee.osm. image

polarkernel commented 3 months ago

How is the the intersection polygon generated for the bottom part marked with the red color?

It works exactly the same. Although the original idea comes from straight skeleton algorithms, I adapted the code to find the intersections correctly on the inside. The side of the intersection is determined by the order of the edge vectors (right to left). I have created a simple demo code (zip file) where you can experiment with this function. The current demo data corresponds roughly to the intersection you marked in red.

polarkernel commented 3 months ago

How would you treat the case when offset centerlines do not intersect?

As far as I understand it, this should work similarly with my function. You can check it by adapting the demo code. The restriction to intersect within the normals only holds at the outer ends of the edges. The idea is that there may be a next segment along the polyline that gives a better intersection.

vvoovv commented 3 months ago

a simple demo code

By the way, is there a specific reason for the negated assignment in the following line?

e0u, e1u = -ev0/ev0.length, ev1/ev1.length
vvoovv commented 3 months ago

By the way, is there a specific reason for the negated assignment in the following line?

Sorry, I revoke the last question. The negation is needed to have normals pointing in the same side.