I have been using networkX to compute the shortest path distance between two points A and B in a graph thanks to Dijkstra's algorithm.
The edges of my graph represent road segments, and the nodes the connections between segments. The weight function is the segment length, so that the returned path distance is the actual geographical distance.
However, the calculated paths are sometimes unrealistic for my use. More specifically, I would like to prevent the algorithm from using paths implying very sharp turns between two successive edges. This implies that the weight of a particular edge is a function of the edge itself, but also of its precedessor in the path (so that the turn angle can be computed and sharp turns dismissed).
As a (simplistic) example, let's consider the below graph (assuming that the nodes and represented according to their actual geographical position). For the sake of simplicity, each edge has a weight (or distance) equal to 1.
The shortest path from A to B is shown in green, and the corresponding distance is 2.
Shortest path without "sharp turn" constraint
However, the proposed path involve a sharp turn at node C (which can be detected based on the geographical coordinates of nodes A, B and C). This kind of turn should be forbidden, such that the proposed shortest path becomes the one described below.
Shortest path with "sharp turn" constraint
The distance is now 6, but the path avoids the transition A-B-C which involved a sharp turn.
What do you think are my options to implement such requirement?
I have done something similar by making it a multi edge graph. Such as there is more than one edge between any two nodes. The 2nd edge in your case could be a numerical value identifying the orientation of the edge(road).
Considering south to north as 0, you could assign -180 to 180 to each orientation and then your algorithm need only compute the difference between the two weights of these edges to figure out if the node is sharp turn and thus eliminate it.
Look up “multgraph” or “multidigraph” in networkx api for implementation
One edge has to be distance other has to be orientation, encoding both orientation and distance to a single weight will require trignometric coding from a central (0) point
Related
I am making game in Unity engine, where car is moving along the bezier curve by percentage of bezier curve legth.
On this image you can see curve with 8 stop points (yellow spheres). Between each stop point is 20% gap of total distance.
On the image above everything is working correctly, but when I move handles, that the handles have different length problem occurs.
As you can see on image above, distances between stop points are not equal. It is because of my algorithm, because I am finding point of segment by multiplying segment length by interpolation (t). In short problem is that: if t=0.5 it is not in the 50% percent of the segment. As you can see on first image, stop points are in half of segment, but in the second image it is not in half of segment. This problem will be fixed, if there is some mathematical formula, how to find distance middle point.
As you can see on the image above, there are two mid points. T param mid point can be found by setting t to 0.5 (it is what i am doing now), but it is not half of the distance.
How can I find distance mid point (for cubic bezier curve, that have handles in different distance)?
You have correctly observed that the parameter value t=0.5 is generally not the point in the middle of the length. That is a good start but the difficulty lies in the mathematics beneath.
Denoting the components of your parametric curve by x(t) and y(t), the length of the curve
between t=0 (the beginning) and a chosen parameter value t = u is equal to
What you are trying to do is to find u such that l(u) is one half of l(1). This is sometimes possible but often difficult or impossible. So what can you do?
One possibility is to approximate the point you want. A straightforward way is to approximate your Bezier curve by a piecewise linear curve (simply by choosing many parameter values 0 = t_0 < t_1 < ... < t_n = 1 and connecting the values in these parameters by line segments). Now it is easy to compute the entire length (Pythagoras Theorem is your friend) as well as the middle point (walk along the piecewise linear curve the prescribed length). The more points you sample, the more precise you will be and the more time your computation will take, so there is a trade-off. Of course, you can use a more complicated numerical scheme for the approximation but that is beyond the scope of the answer.
The second possibility is to restrict yourself to a subclass of Bezier curves that will let you do what you want. These are called Pythagorean-Hodograph (shortly PH) curves. They have the extremely useful property that there exists a polynomial sigma(t) such that
This means that you can compute the integral above and search for the correct value of u. However, everything comes at a price and the price here is that you will have less freedom, where to put the control points (for me as a mathematician, a cubic Bézier curve has four control points; computer graphics people often speak of "handles" so you might have to translate into your terminology). For the cubic case you can find the conditions on slide 15 of this seminar talk by Vito Vitrih.
Denote:
the control points,
;
then the Bézier curve is a PH curve if and only if
.
It is up to you to figure out, if you can enforce this condition in your situation or if it is too restrictive for your application.
Is there known way of assigning natural numbers (ordering) of Mandelbrot fractal edge points? Obviously there is an infinite number of such points, but at certain level of detail we can count them and order them. I'd like to order them in such way so they form a continuous path without any intersections.
Edge points can be ordered with external angles, as the landing point of external rays. External angles are measured in turns, usually binary
Here is the image by Claude
I am reviewing some MATLAB code that is publicly available at the following location:
https://github.com/mattools/matGeom/blob/master/matGeom/geom2d/orientedBox.m
This is an implementation of the rotating calipers algorithm on the convex hull of a set of points in order to compute an oriented bounding box. My review was to understand intuitively how the algorithm works however I seek clarification on certain lines within the file which I am confused on.
On line 44: hull = bsxfun(#minus, hull, center);. This appears to translate all the points within the convex hull set so the calculated centroid is at (0,0). Is there any particular reason why this is performed? My only guess would be that it allows straightforward rotational transforms later on in the code, as rotating about the real origin would cause significant problems.
On line 71 and 74: indA2 = mod(indA, nV) + 1; , indB2 = mod(indB, nV) + 1;. Is this a trick in order to prevent the access index going out of bounds? My guess is to prevent out of bounds access, it will roll the index over upon reaching the end.
On line 125: y2 = - x * sit + y * cot;. This is the correct transformation as the code behaves properly, but I am not sure why this is actually used and different from the other rotational transforms done later and also prior (with the calls to rotateVector). My best guess is that I am simply not visualizing what rotation needs to be done in my head correctly.
Side note: The external function calls vectorAngle, rotateVector, createLine, and distancePointLine can all be found under the same repository, in files named after the function name (as per MATLAB standard). They are relatively uninteresting and do what you would expect aside from the fact that there is normalization of vector angles going on.
I'm the author of the above piece of code, so I can give some explanations about it:
First of all, the algorithm is indeed a rotating caliper algorithm. In the current implementation, only the width of the algorithm is tested (I did not check the west and est vertice). Actually, it seems the two results correspond most of the time.
Line 44 -> the goal of translating to origin was to improve numerical accuracy. When a polygon is located far away from the origin, coordinates may be large, and close together. Many computation involve products of coordinates. By translating the polygon around the origin, the coordinates are smaller, and the precision of the resulting products are expected to be improved. Well, to be honest, I did not evidenced this effect directly, this is more a careful way of coding than a fix…
Line 71-74! Yes. The idea is to find the index of the next vertex along the polygon. If the current vertex is the last vertex of the polygon, then the next vertex index should be 1. The use of modulo rescale between 0 and N-1. The two lines ensure correct iteration.
Line 125: There are several transformations involved. Using the rotateVector() function, one simply computes the minimal with for a given edge. On line 125, one rotate the points (of the convex hull) to align with the “best” direction (the one that minimizes the width). The last change of coordinates (lines 132->140) is due to the fact that the center of the oriented box is different from the centroid of the polygon. Then we add a shift, which is corrected by the rotation.
I did not really look at the code, this is an explanation of how the rotating calipers work.
A fundamental property is that the tightest bounding box is such that one of its sides overlaps an edge of the hull. So what you do is essentially
try every edge in turn;
for a given edge, seen as being horizontal, south, find the farthest vertices north, west and east;
evaluate the area or the perimeter of the rectangle that they define;
remember the best area.
It is important to note that when you switch from an edge to the next, the N/W/E vertices can only move forward, and are readily found by finding the next decrease of the relevant coordinate. This is how the total processing time is linear in the number of edges (the search for the initial N/E/W vertices takes 3(N-3) comparisons, then the updates take 3(N-1)+Nn+Nw+Ne comparisons, where Nn, Nw, Ne are the number of moves from a vertex to the next; obviously Nn+Nw+Ne = 3N in total).
The modulos are there to implement the cyclic indexing of the edges and vertices.
I have a set of origin-destination coordinates that I want to calculate the shortest paths between them.
My origin-destination coordinates are sometimes located in the middle of a long straight-line road. However, the shortest path calculated by OSMnx/networkx will not consider that mid-edge to nearest-node path.
Is there any ready function in OSMnx or networkx that I can use to find shortest path that originates/ends in the middle of the road?
If there is no such function, I am thinking of using the following steps.
Get nearest edges of origin and destination
Get nodes of those nearest edges: let's say (a,b) for origin, and (c,d) for destination
Calculate distance of 4 possible combinations: a->c, a->d, b->c, b->d
Project origin/destination onto their nearest edges: let's call them o1 and e1
Calculate distance o1->a, o1->b, e1->c, e1->d
Add (5) distance to (3): to get
o1->a->c->e1
o1->a->d->e1
o1->b->c->e1
o1->b->d->e1
Select path with smallest distance
OSMnx produces a networkx graph object for routing/analysis. As you note, networkx shortest path calculation takes an origin and a destination node, so trying to calculate a shortest graph path from an edge midpoint won't work.
A couple things you could try:
try to set simplify=False when you create the graph to retain as many nodes in the middle of streets as possible.
if that doesn't work, you could try to subdivide edges (with greater than some threshold length) into 50 meter chunks or somesuch to discretize them with more nodes.
See also: https://stackoverflow.com/a/55601732/7321942
I'm working with MATLAB and I have a finite element mesh, of which I am interested in analysing specific nodes. I have information about the position of each point, how the points are connected to each other, and I know what points belong to which elements.
I need to calculate the approximate distance between a given point and the edge of the mesh in a specific direction (assume I shoot an arrow from a point in a direction, I want to know how much it travels before it exits the whole mesh). It does not need to be exact: for instance, it would be enough to know the distance between the point and the closest node to where the edge is crossed.
I do not have information about which nodes/edges/elements are at the boundary or inside the mesh.
I was thinking of this strategy:
a) incrementing the components of the vector of the direction by ∂x
∂y ∂z, , starting from the node of interest.
b) at every step check whether there is a node in a given radius (the
density of the nodes is relatively high).
c) if there isn't, then the edge of the mesh is probably somewhere
between this step and the one before. If there is, keep going.
This should work, however I have ~1000 nodes to take into consideration with ~50+ directions, and it seems it would be very time consuming.
As I mentioned, it does NOT need to be an exact value. I want to know how much "mass" there is between a node and the end of the mesh in a direction, but for what I'm analysing small differences do not matter.
Thanks!