-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bundles, descriptions and issues #80
Comments
I don't understand this case. If the short candidate is perpendicular to the template and completely or always completely within the buffer polygon, then there is no intersection or only one intersection of the short candidate with the buffer polygon. So both |
On a separate note. To construct the buffering polygon, the original curve must be offsetted. Do you check for self-intersections when offsetting the curve? Do you process the self-intersections? I need this feature to render roadways and sidewalks correctly. |
No, not completely. Self-intersections are only processed between adjacent line segments. For the equidistant line detection application, this is not important because lines that are too curved are already excluded from the static spatial index. In addition, I successfully replaced corners with a Some time ago, I made an attempt to use a different algorithm that gave better results, as far as I can remember. I will try to find it and let you know if I do. |
Could you please paste the code to generate the image above. I'd like to know the API calls to generate an offset for a curve with processing of self-intersections. |
The code was: from mathutils import Vector
import matplotlib.pyplot as plt
from lib.CompGeom.PolyLine import PolyLine
line = [
Vector((1.8,3)),
Vector((1,1.8)),
Vector((0.2,1)),
Vector((0,0)),
Vector((0.2,-1)),
Vector((0.5,-2)),
Vector((0.8,-3))
]
polyline = PolyLine(line)
polyline.plot('k',2)
for d in range(20):
dist = 0.2*(d+1)
offsetPoly = polyline.buffer(dist,dist)
x = [n[0] for n in offsetPoly] + [offsetPoly[0][0]]
y = [n[1] for n in offsetPoly] + [offsetPoly[0][1]]
plt.plot(x[:-1],y[:-1],'r',linewidth=0.5)
plt.plot(x[:-1],y[:-1],'b.',markersize=2)
plt.gca().axis('equal')
plt.show() |
Well, for now just a patch: In module lib/CompGeom/OffsetGenerator.py, replace line 91 fillet = self.constructFillet(p2,seg[1],p3,abs(self.distance)) by fillet = None #self.constructFillet(p2,seg[1],p3,abs(self.distance)) Should you like to use this feature permanently, we will have to introduce some function argument. |
I found this old code. It implements a totally different algorithm. It has a function for lines and a function for polygons. As far as I remember, there were some minor floating-point accuracy issues (see red arrow), but it actually works on a much larger parameter range than the one that is in the addon. It is also capable of creating holes, as shown in the examples below, which is not the case with the current one. I am convinced that I would be able to finish it and make it robust and reliable if needed. |
Did I understand the problem correctly that it's not possible to join the adjacent bundles for perpendicular way-sections since the buffering polygons do not intersect in that case? Adjacent way-sections of the bundle can be checked if they are collinear with the way-sections of the bundle and that they also form a bundle. |
I made a first attempt to find clustered intersections. It is quite simple and works as follows:
The result looks already quite promising: Looking at the images of the intersection between Karl-Marx-Allee and Straße der Pariser Kommune in berlin_karl_marx_allee.osm (left) and of the intersection in the middle part of rotterdam_01.osm (right), you can notice a problem, that will have to be discussed (the dotted polygon is the convex hull of all point detected as one group): In both cases, all intersections belonging to this cluster have been detected, including those between pedestrian and bicycle ways. The question now is, where do the bundles ( Filtering out all these details is a major task that now awaits us. Not all crossings are as classically shaped as these two examples above: |
What if intersections with footways and cycleways are ignored? Will the intersections have a more classical shape? |
Originally I thought that a crosswalk is a part of a The crosswalks are located on the filets on the intersection below: I'll think what to do with the filets in that context. |
Yes. It should also be simple to detect them. I have more concerns about their assignment, as you also noted:
Locating fillets on bundles can be ambiguous. For example, the one at the top right might belong to the upward or to the right-hand bundle. |
I also suggest drawing a convex hull for "roadway" intersections (primary, secondary, tertiary, residential, etc). |
This is already done. The major road intersections have a round dot and their convex hull is darker (or more saturated, large I made this version for visualization purposes only, so we can discuss issues using real-world examples. |
I meant crossing nodes where ALL ways are not minor roads ( |
To be more precise, a crossing node can be shared by minor ways, but it must be shared by at least 3 major ways. |
OK, committed version adapted. |
Sorry. That sentence was not formulated precisely again. I meant at least 3 major way-segments instead of at least 3 major ways. |
To be precise, here are the rules of the current implementation. For each node that is an intersection, the sum The following intersection types are assigned according to the number of different categories:
|
Did you mean way-segments or ways? If a node is located at the middle of a way and there are no other ways that share the node, then |
I mean way-sections. I have never used the concept of ways that go through an intersection, because it can be ambiguous. If there are multiple way-sections at an intersection, it is not always clear, which ones belong to the same way. |
Created #83 |
An intersection is created by finding the intersection points of the roadway borders. So a crosswalk is a part of the roadway. But there is a notable exception: a diagonal crossing or a pedestrian scramble : It's a part of a intersection and painted right on it. I suggest ignoring the minor ways (footways, crossways) when generating the intersections. Then the footways located within the intersection polygon can be filtered out. I added the new OSM file streets/tokyo_shibuya.osm which contains the famous Shibuya Crossing. |
Another reason of having Bundles is the generation of sidewalks. Without a Bundle the sidewalks are generated along both sides of a Section or another item. If a Bundle is present, the sidewalks are generated along both sides of the Bundle (or the top Bundle if there is a hierarchy of Bundles), rather than the sides of each member of the Bundle. |
I see three different approaches:
|
I'd prefer to start from the intersections. What are the obstacles now to get clustered intersections? |
Clustered intersections require not only the definition and construction of clusters, but also those of bundles. This will be a huge and demanding development step. See also the discussion starting here. To get illustrations, you can run the code in script mode, using |
What if |
Then |
Ok.
Another possible solution is to use a separate class for the connectors and to get rid of the connector indices all together. class IntConnector:
def __init__(self, intersection):
# the intersection, to which the connector belongs to
self.intersection = intersection
# the item, to which the connector is connected to
self.item = None
# the preceding connector in the intersection (for, example, when considered counterclockwise)
self.pred = None
# the succeeding connector in the intersection (for, example, when considered counterclockwise)
self.succ = None
|
This is a great idea, I like it. A circular doubly-linked list of instances of class IntConnector:
def __init__(self, intersection):
# the intersection, to which the connector belongs to
self.intersection = intersection
# the first index of the connector in the area polygon of Intersection
self.index = None
# the item, to which the connector is connected to
self.item = None
# the direction of the item, to which the connector is connected to
self.fwd = None
# the preceding connector in the intersection (in clockwise direction)
self.pred = None
# the succeeding connector in the intersection (in counter-clockwise direction)
self.succ = None OK for you?
You mean Once all the items are set up by the |
Is a list of connectors? I suggest having an attribute with the name
Yes, with the notes above and below.
Yes.
Doesn't |
I think everything is agreed now. Looking forward to the intersections in the street renderer. |
All this is already implemented in the current version. Most of the intersections already look as desired, when executed in script mode: but there are overlaps, because we do not yet have any clustering, which can produce some "salad" like this There also seem to be some minor bugs in the construction of the intersections. However, the structures should already be correct (though not yet thoroughly tested), so you might want to do some initial checks. |
Would it be possible to enable trimming of centerlines due to the intersections? |
Committed. It is a very temporary solution, implemented only for your checks. It will be solved elsewhere, once I finalize the code. Note: |
If a |
Also, I'd like to have all |
For now, yes. This is only a temporary solution, because I cannot handle all problems with short sections at the moment. Later, invalid sections will be removed, and the links will be adjusted somehow.
I assumed that when I asked for "how you want to access them". I will provide that as soon as possible. Currently, only intersections with three or more leaving sections are processed. Later, the others will become |
Committed. |
I'll take some time to develop the code. I'd suggest including |
OK, I intend to implement them as a linked instance between two |
I meant exactly that. |
A first version has been committed. I think the new classes For A In the current version, sections are not yet split by |
Sorry, I forgot to remove some code that uses connectors in |
I committed a version with code for experimental intersection clustering. This is only for backup reasons, the code itself is not called. |
The first task in the search for objects of the class
Bundle
is the search for equidistant path segments. For a better understanding of the concept and its problems, I will first explain how the algorithm works.First, all way-sections that exceed a minimal length and are not too curved are entered into a static spatial index. This index uses bounding boxes around the sections to find neighbor sections. Way-sections, whose bounding boxes overlap, are candidates as neighbors. For every section (template) in this index, its neighbors are searched and tested, whether they are equidistant to the template section. This is done as follows:
The black line is the centerline of the template section. A buffering polygon is constructed around this line, spaced according to the category of the section (red dotted polygon). Assume that the cyan line is the centerline of the neighbor candidate. A clipping algorithm first determines the length
inLineLength
of the candidate within the buffer polygon. In this example, this is the length betweenp1
andp2
. This length must at least be 10 % of the total length of the candidate.However, a short candidate line could be perpendicular to the template, but almost completely within the buffer polygon. So we need an additional condition: The distances
d1
andd2
between the entry and exit pointsp1
andp2
and the template are computed. Then, some kind of slope relative to the template is determined from the difference between these distances and the lengthinLineLength
of the candidate within the buffer polygon to asslope = abs(d1-d2)/inLineLength
. Demanding a small value forslope
rules such cases out.This algorithm has the advantage, that overlapping way-sections continue the equidistant parts, as long as only one side is interrupted. For instance these three way-sections (black lines with red dotted surrounding buffer polygon) would be considered to belong to the same group (
Bundle
):However, there is a disadvantage, when the intersections are almost perpendicular, so that this effect does not work anymore. In the image below on the left (middle part in rotterdam_01.osm) this effect is clearly visible. Overlapping sections result in parallel ways through the intersection (all the same color). In the image on the right (intersection between Karl-Marx-Allee and Straße der Pariser Kommune in berlin_karl_marx_allee.osm), the ways are almost perpendicular, and the groups always contain only the short parallel parts (same color is same group).
The text was updated successfully, but these errors were encountered: