So I want to make a program to find the shortest path between 2 train stations. What would you suggest is the best way to represent the train lines, where they intersect and search for this? My current thoughts are Adjacency Matrix or List however, I'm not sure as not all adjacent points are linked.
Eg.
The train lines would look like this:
Grey Line stations - Waterloo, Southwark, London Bridge
Black Line stations - Kennington, Oval, Borough, London Bridge
Black line 2 Stations - Kennington, Waterloo, Embankment
Brown Line Stations - Elephant & Castle, Waterloo, Embankment.
if I wanted to to from Oval to Southwark for example, I would go:
Oval to Kennington on Black Line (then switch the Blank line 2)
Kennington to Waterloo (Then switch to Grey line)
Waterloo to Southwark.
This is a shortest paths problem. Since you're interested in shortest time, then just use the durations in place of distances. Dijkstra's algorithm is a common approach for solving these types of problems. It is well documented on the Internet. If you intend to generate a timetable of all trips, then you should look into the Floyd-Warshall algorithm since it can generate solutions for all pairs of stations.
Both of these methods will require you to model the rail system as a graph. The edge weights will be the times to travel between stations. For stations with multiple lines, you could use multiple nodes and edges with a weight of 4 between them.
This is similar to the travelling salesman problem, for which there is no known closed solution, other than trying all possible paths. Note that the number of such paths increases exponentially with the number of stations, so it becomes computationally very expensive quite rapidly.
Also, you have to decide whether you want the shortest distance between the stations, or the shortest travel time between them.
Related
In my application I work with OpenGL and large arrays of data.
One of the things I need to do is I receive multiple "simple" polygons that can be either convex or concave. By simply I mean geometrical definition - polygons without holes and intersecting edges.
I receive this poligons in the form of linked loop of points (vertices), where each Vi is connected to Vi-1 and Vi+1 points and nothing else. The last point is also connected to the first, giving us a loop as a result.
I will say right now that I figured out polygon triangulation, and it works like a charm (I used ear-clipping method for now).
But, I need to build LOTS of those polygons, millions of them. To minimize the load I decided to split my world into "chunks", squares like in Minecraft. I then use frustum culling and other optimizations methods to either render or discard/simplify these chunks and meshes in them.
So, what I want to do is: if the polygon I received lies in several different chunks - then I want to split it into meshes for each of those chunks. Basically, I want to create multiple polygons that are divided on chunk borders, and THEN triangulate them and create meshes for rendering.
As a result I want to have one (or several) contours that I can then triangulate.
here's a picture of my task:
I made an algorythm for splitting it myself that I thought would work, but I found that it only works if the contour in any given chunk doesn't break up, like you see in the example (in other words if there's only one figure in any given chunk).
I thought to ask here if anyone knows any good algorythms for that task? I'll probably come up with something myself, but practice shows that there's almost always a better and simpler ready-made solution out there. I'd really appreciated it if someone could give me a useful link or an article, if not with a solution itself, then something that could give ideas.
I'm not at work at the moment, because it's weekend, so I'll be trying/testing the things on Monday.
What I came up with at the moment, however, is a very simple solution.
test all points in the contour.
If point i and point i+1 don't belong to the same chunk (which I can test easily):
then find an intersection between chunk border and the line made by these two points.
add this new point to the contour between the original two points.
When every edge of the polygon was tested like that - triangulate it.
because we have points on the edges of the chunks - then during triangulation the triangles will fit exactly into chunk borders
for each triangle, decide which chunk it belongs to and generate the mesh in THAT chunk.
I won't go into details of some optimization ideas - like not needing to evaluate resulting triangles if the entire figure fits within the same chunk.
This is a stab in the dark at writing some pseudo code that may work. Feel free to implement it and select your own answer with the actual code if it works.
First, convert your vertex array to a double linked list that loops from the last element to the first element. Or it may be better to model it as an undirected graph instead, because a point may have missing neighbours.
Then apply the algorithm below for each quadrant, starting with the full polygon each time. You can cut down the size of that polygon by culling vertices that are outside of the quadrant and at least 1-neighbour away from edges that cross the cutting lines.
// We need to keep track of the points that we insert on the cutting lines
let LIX = List of X-Cut-Line Intersection Points
let LIY = List of Y-Cut-Line Intersection Points
foreach Edge AB in Poly where A is inside the quadrant, B outside
// Insert points into the polygon that intersect the X-Cut-Line
if AB Intersects X-Cut-Line
let Ix = Intersection Point
Insert Ix between AB so that A<->B becomes A<->Ix
B can be removed from the polygon now
Add Ix to LIX
// Insert points into the polygon that intersect the Y-Cut-Line
if AB.Intersects Y-Cut-Line
let Iy = Intersection Point
Insert Iy between AB so that A<->B becomes A<->Iy
B can be removed from the polygon now
Add Iy to LIY
// Then iterate pairs of points along each cutting line to join them
sort LIX by X Ascending
while (LIX.Length > 0)
let P0 = LIX[0]
let P1 = LIX[1]
Link P0 and P1
Remove P0 and P1 from LIX
sort LIY by Y Ascending
while (LIY.Length > 0)
let P0 = LIY[0]
let P1 = LIY[1]
Link P0 and P1
Remove P0 and P1 from LIY
Finally, you can look for cycles in the resulting linked list/graph to find the new polygons. Each cycle should in theory not contain points from the other cycles already detected so it is an individual polygon.
Good morning/afternoon/evening.
So our data structures course gave us an assignment to segment a grayscale image in java using the following algorithm:
Input: A gray-scale image with P pixels and number R
Output: An image segmented into R regions
1. Map the image onto a primal weighted graph.
2. Find an MST of the graph.
3. Cut the MST at the R – 1 most costly edges.
4. Assign the average tree vertex weight to each vertex in each tree in the forest
5. Map the partition onto a segmentation image
The thing is, they just threw us in the dark. They gave us the jgraph package which we had absolutely no experience with (we never studied it) practically saying "go teach yourselves". Nothing new there.
The way I'm going about doing this is by making a class for vertix objects that contains the coordinates of the pixel in addition to its value so that I can add each one both to the graph and a 2D array. Afterwards, I used the array to add weighted edges between adjacent vertices because java can't tell where in the graph a vertix actually is without edges.
Afterwards, I used Kruskal's packaged method for minimum spanning trees and an arraylist to get around the protected status of edge weights in the tree like so:
ArrayList<WeightedEdge> edgeList = new ArrayList<>(height*width*3);
KruskalMinimumSpanningTree mst4 = new KruskalMinimumSpanningTree(map4);
Set<DefaultWeightedEdge> edges = mst4.getSpanningTree().getEdges();
for (DefaultWeightedEdge edge : edges) {
edgeList.add(new WeightedEdge(edge, map4.getEdgeWeight(edge)));
}
edgeList.sort(null);
for (int i = 0; i < n; i++) {
map4.removeEdge(edgeList.get(edgeList.size()-1).getEdge());
}
So now that I cut the (R-1) most costly edges in the graph, I should be left with a forest. And that's where I hit another dead end. How do I get the program to traverse each tree? The way I'm understanding this, I need a general traversal algorithm to visit every tree and assign the average value to each vertix. The problem? There isn't a general traversal algorithm in the package. And there isn't a way to identify individual trees either.
The idea is easy to understand and implement on paper, really. The problems only lie in actually coding all of this in java.
Sorry if this was messy or too long, but I'm just at my wit's end and physical limits. Thank you in advance.
I am a big fan of JGraphT and honestly I think it is pretty good that you're given it for your task assignment. It takes a bit of time to get started, but then it proves to be a very good tool. But you also need to understand the CS behind implemented algorithms, using JGraphT without knowing the theory is somewhat difficult.
From your task assignment I don't really understand step 1 (building the primal weighted graph). The rest should work with JGraphT quite well.
You did step 2 with KruskalMinimumSpanningTree. Now you can sort the edges by weight and remove R-1 top edges from the graph.
I would, however, suggest that you first build a new graph which would represent the calculated MST. And then remove remove R-1 top edges from that graph. Effectively truning it into a forest.
How do I get the program to traverse each tree?
With the forest from the previous step you can use the ConnectivityInspector to get a list of sets of connected vertices. Each set will contain vertices from one of the trees of the forest. Sets of vertices are easy to work with, you don't need any traversal, just iterate over the set.
I am currently making a map generator using Java. I am using arrays to store coordinates, which are then used to draw land. So I also have cities, and I want to draw the most direct path from city a to city b without crossing the water, AKA, only using the coordinates that are stored as land. How can I do this? I have tried many algorithms a;ready, like solving systems to make sure things do not overlap (which takes too long, as i have 75,000 points) and also finding the nearest city that does not have any water in between the two, found by drawing a best fit line and solving just one systems (extremely inaccurate and probably just wrong). Thanks for all the help in advance!
I'm calculating shortest path of a robot on a plane with polygonal obstacles. Everything works well and fast, no problems there. But, how to smoothen the path so it becomes curvy ?
Below is a picture of a path connecting vertices with a straight line.
P.S
Robot is just a circle.
This paper might be useful. It looks like it's a non-trivial problem. Abstract:
Automatic graph drawers need to compute paths among ver- tices of a simple polygon which besides remaining in the interior need to exhibit certain aesthetic properties. Some of these require the incorpo- ration of some information about the polygonal shape without being too far from the actual shortest path. We present an algorithm to compute a locally convex region that “contains” the shortest Euclidean path among two vertices of a simple polygon. The region has a boundary shape that “follows” the shortest path shape. A cubic Bezier spline in the region in- terior provides a “short and smooth” collision free curve between the two given vertices. The obtained results appear to be aesthetically pleasant and the methods used may be of independent interest. They are elemen- tary and implementable. Figure 7 is a sample output produced by our current implementation.
I used to play with path calculation techniques a lot when trying to make realistic flying sequences to be rendered in Teragen. I initially tried using Bézier Curves.
But discovered that (for flying at least) they aren't that useful. The reason is that the curvature between curves is discontinuous, and so cannot be used to calculate a continuous correct banking angle for a fly-by. Also, it's hard to be sure that the curve doesn't intersect an mountain.
I digress. The way I eventually settled on was a simple mass-spring based path, and relax it into submission.
Subdivide the path into lots of little segments, the more the merrier. For each point, move it a little bit in a direction so as to reduce the angle between it and its neighbours, and way from the obstacles. Repeat many times until the path has settled down.
k = 0.01 // Adjust the values of k and j to your liking.
j = 0.01 // Small values take longer to settle. Larger values are unstable.
For each point P
normal_vector = vector_to_previous_point + vector_to_next_point
obstacle_vector = vector_to_nearest_obstacle
obstacle_distance = magnitude(obstacle_vector)
obstacle_vector *= obstacle_distance^2
P += (normal_vector * k) - (obstacle_vector * j)
The benefit of these kind of finite element relaxation techniques is that you can program all kinds of constraints into it, and the path will settle on some compromise between them, depending on the weights (j and k in this case).
If you're into robotics, why not come and join the Robotics Proposal?
Can't you just make the path curvy in the actual execution of the path following algorithm? If you leave the path as is (i.e. connected straight lines), implementing a look ahead distance of ~1 meter (this value will depend on the speed of your robot and the amount you've padded the configuration space to avoid obstacles) in the control algorithm that calculates the velocity of each wheel will automatically smooth out the path without any need for preprocessing.
Here's a quick images of what I mean...the red dotted-line is the path that is actually executed by the robot when you control to a point based on a lookahead distance. A lookahead distance just computes a point further down the path by some arbitrary distance.
Again, the only thing you have to worry about is how much you're padding obstacles to make sure you avoid hitting them. Normally I believe the area of an obstacle is padded by half the robot's radius, but if you're controlling to a lookahead distance you may have to make this slightly larger.
In the case of a robot we can't know the future. We have to draw each point knowing only the location of the robot and the obstacles. The usual method for making curved paths of minimum length is to model the robot with a circle and move the circle so it remains in contact with the obstacles. Just keep one radius away and the turns will be curves.
If you want curves and NOT minimum distance try making the above radius proportional to the distance you are from a polygon vertex.
The Bezier curves idea only works to make the path curved in retrospect. It changes where the robot ha been. Usually with robots changing the past is called "cheating". One way to avoid having to change the path you've already walked is to look ahead. But can the robot see around corners? You have to specify the rules better.
My question is, will the code given in http://pietschsoft.com/post/2008/07/Virtual-Earth-Polygon-Search-Is-Point-Within-Polygon.aspx work to find a point in one of areas mentioned in
below file (page 7-9):
http://www.weather.gov/directives/sym/pd01008006curr.pdf
looking forward,
A point-in-polygon algorithm usually just counts the number of times it crosses a line by "drawing" one out in any particular direction. It would then know if it's in the polygon or not by knowing how many times it crossed that line (even number it was outside, odd number it is inside). The code on that site looks like it just flips a boolean instead of adding to a counter but it's the same thing.
I must confess I have not read the PDF you linked too (too long!) but I've not come across an instance where the algorithm fails.
One tip might be to draw a rough square around the outermost extremeties of the polygon first and check whether it falls within that to avoid having to test each point).
I believe it will fail in some cases. The algorithm you linked to, which is correct for planar geometry, is incorrect for spherical geometry. Consider the rectangles which cross the 180th meridian, e.g. the rectangle labelled "M". The algorithm would consider that rectangle as covering the americas, Africa, and Europe, but not Asia or the Pacific.