I'm currently trying to implement a path finding algorithm in Go. I'm currently committed to get Dijkstra working since that's supposed to be one of the simpler algorithms regarding path findinig. However I have a hard time getting it right. Most of my tests results in infinite loops.
For my tests I'm currently using a ESRI Shapefile as a source and build a graph with it that consists of Vertexes and Edge's (or Node's and Arcs, whatever suits you). This seems to work great, but it's a little memory hungry at the moment.
I started building on this question which seems to work according to the example. But once I adjusted it for my needs, which are real-world coordinates and no id's in the vertex, something seems wrong...
Relevant code that I'm suffering with (part of a gist):
const MAX_LENGTH = 1000000
type MinDistanceFromSource map[*Vertex]float64
func (G *Graph) Dijkstra(source, destination *Vertex) MinDistanceFromSource {
D := make(MinDistanceFromSource)
for _, vertex := range G.Vertexes {
D[vertex] = MAX_LENGTH
}
D[source] = 0
for edge := range source.GetAdjacentEdges() {
D[edge.Destination] = edge.Length
}
// calculateDistance(source, destination, D) // Fix me...?
for _, vertex := range G.Vertexes {
vertex.visited = false // fixme
}
return D
}
The main thing I'm asking myself is if I'm doing this right or am I just off by miles? And how can I make this work? Or am I better of trying to implement something like A*?
Also; the relevant Shapefile that I'm trying this with: NWB_01-01-2015 (100MB zip)
Related
I read on the GitHub repository description that "several algorithms are implemented for different scenarios", and they mentioned Dijkstra, A*, and Contraction Hierarchies. I also found several classes for different algorithms such as Dijkstra (with the class actually named Dykstra), Contracted Hierarchies and so on, in the official docs.
However I cannot seem to find an explanation about when and how Itinero uses each of this algorithms. Can anybody throw some light in this respect? Also, is it possible to configure which algorithm should Itinero use for a given route resolving problem?
Here is my code, obtained from the official docs. I would like to have control over the resolving algorithm and perhaphs even customize my own algorithm...
public Itinero.Route CalcularRutaOptima(Coordinate ini, Coordinate fin)
{
var routerDb = new RouterDb();
using (var stream = new FileInfo(#"mapaAreaReducida2_01.pbf").OpenRead())
{
routerDb.LoadOsmData(stream, Vehicle.Car);
}
// create a router.
var router = new Router(routerDb);
// get a profile.
var profile = Vehicle.Car.Shortest();
// create a routerpoint from a location.
// snaps the given location to the nearest routable edge.
var start = router.Resolve(profile, ini);
var end = router.Resolve(profile, fin);
// calculate a route.
Itinero.Route route = router.Calculate(profile, start, end);
return route;
}
Thanks!
I want to implement a method that takes the starting and ending locations on a map and returns a path that navigates the map from start to end. (This path must not contain any impassable tiles (Wall tiles) and must be as short as possible.)
So for this implementation, I'm only allowed to use BFS. My first step would be to convert the maze into a graph but I'm not sure how to even start with that. Then I would have to run BFS on the tile containing the maze runner. Lastly, I would have to backtrack from the goal tile to build the path. There's so many steps I feel like I really need some help processing over this.
class GridLocation(val x: Int, val y: Int){
override def toString = s"($x, $y)"
override def equals(that: Any): Boolean = {
that match {
case other: GridLocation =>
this.x == other.x && this.y == other.y
case _ => false
}
}
}
object MapTile {
def generateRow(row: String): List[MapTile] = {
row.map((ch: Char) => MapTile(ch.toString)).toList
}
def apply(tileType: String): MapTile = {
tileType match {
case "-" => new MapTile("ground", true)
case "G" => new MapTile("goal", true)
case "O" => new MapTile("wall", false)
}
}
}
class MapTile(val tileType: String, val passable: Boolean) {
}
def findPath(start: GridLocation, end: GridLocation, map: List[List[MapTile]]): List[GridLocation] = {
//code starts here
}
Rather than explicitly building a graph, you can just keep the graph implicit by trying, at each cell, to move in each of the four cardinal directions [y+1,x],[y-1,x],[y,x+1],[y,x-1] and only add the new cell to the queue if it fulfills the following:
The new cell is within the grid and isn't a wall block.
The new cell hasn't been previously visited.
To keep track of visited cells, you can use an auxiliary array the size of the grid and mark visited cells off as 1 and unvisited as 0. Furthermore, to store the path, you can keep another auxiliary array that stores, for each cell, the "parent cell" that led directly to this cell, and upon finishing the BFS you can backtrack parents starting from the end cell all the way back to the start cell.
For clarity, the "parent cell" of cell x is the cell that was being considered when x was added to the queue.
I recommend you to look at A* algorithm, or an other "pathfinding" algorithm.
I think that the Youtube Channel "Coding train" had made a video on that.
Good afternoon.
I'm developing a game that involves a number of Sprite Arrays and I want to detect collisions between them and specify functions depending on which etc.
So say I have an array of 16 balls ballArray[I] and 16 blocks blockaArray[I] which I can easily iterate through using the index number I.
I have given the balls a Physics Category - Balls and similar to for Blocks. Then I have 16 ID Physics categories say ID1, ID2, ID3, ID4
So I can detect a collision, know that is was a Ball hitting a Block but I then need to know which ball and which block.
What the best or easiest way to do this? I'm reading about enumerateChildNodes(withName) function but have not used it. Or can I create array of PhysicsCategories which I could iterate through along with the SpriteArray to compare and identify.
EDIT:
Thanks Everyone for the help. I have finally cracked it. Surprisingly in the end the code a lot simpler than I first thought. Still not fully understanding where the bits are sitting in my categories but have it working .
I'll try to post my final working code - you may have suggestions to improve. Many thanks again and apologies for my poor StackFlow etiquette - I am new here :-)
So my Physics Categories were defined.
struct PhysicsCategories {
static let BoxCategoryMask = UInt32(1<<7)
static let BallCategoryMask = UInt32(1<<8)
}
and then in my function to build an array of Sprites
boxBloqArray[i].physicsBody?.categoryBitMask = PhysicsCategories.BoxCategoryMask | UInt32(i)
boxBloqArray[i].physicsBody!.contactTestBitMask = PhysicsCategories.BallCategoryMask
and the same for the ball array but just the categoryBitMask
ballBloqArray[i].physicsBody?.categoryBitMask = PhysicsCategories.BallCategoryMask | UInt32(i)
I'm still not really sure why it has to be this way round but that was the final problem this evening that I had the two bodies the wrong way round in the && comparison in the final working detection code:
var body1 = SKPhysicsBody()
var body2 = SKPhysicsBody()
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
body1 = contact.bodyA
body2 = contact.bodyB
}
else {
body1 = contact.bodyB
body2 = contact.bodyA
}
// Check node collisions
for n in 0...15 {
for i in 0...15 {
if body2.categoryBitMask == PhysicsCategories.BallCategoryMask | UInt32(n) && body1.categoryBitMask == PhysicsCategories.BoxCategoryMask | UInt32(i) {
//if body1.node != nil {
print("Ball\(n) hit Box\(i)")
//}
}
}
}
and that is now printing the correct collisions.... lovely!... onwards to
the next step... thanks again
Once you have the two nodes involved in the collision as discussed in the answer by #Luca Angeletti, you can turn those into an index in various ways.
If you've made each type of node a specialized subclass and you have the appropriate indexes stored as class members, then you can convert to the appropriate class and look at the index fields, e.g.,
if let block = nodeA as? BlockNode, let ball = nodeB as? BallNode {
print("block \(block.blockIndex) hit ball \(ball.ballIndex)")
}
Nodes are hashable, so you can have dictionaries to map them back to indexes:
if let blockIndex = blockIndexes[nodeA], let ballIndex = ballIndexes[nodeB] {
print("block \(blockIndex) hit ball \(ballIndex)")
}
You can use the userData property of nodes to store whatever you like, including the indexes. The mucking around with NS things gets kind of ugly though.
https://developer.apple.com/documentation/spritekit/sknode/1483121-userdata
You can do the linear scan through each array.
if let blockIndex = blocks.firstIndex(of: nodeA), let ballIndex = balls.firstIndex(of: nodeB) {
print("block \(blockIndex) hit ball \(ballIndex)")
}
It sounds like from your question that you might have a separate category bit mask for each individual block and each individual ball. Or if you don't, that is possible if there are at most 16 of each. Anyway, if that's the case, then you can do some bit flicking to take the categoryBitMask from the physics bodies, shift the ball/block one by 16 bits (whichever is using the high bits gets shifted), and then take log2 of the bit masks to get your indexes. You can find various bit flicking techniques for log2 here:
https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
Given 16 things of each type, I'd say just do #4. If you already have subclass nodes, #1 is fine. Number 2 is spreading state around a bit, so I'm not such a fan of that. Number 3 I would not really recommend because of the NS stuff. Number 5 is too cute for its own good.
Edit: Now that I read again, it sounds like maybe you've got separate ID's for categories 1...16, so your block category bit masks are like:
blockCategoryMask | ID1, blockCategoryMask | ID2, etc. That can also work (basically a variant of #5). If you're going down that route though, you may as well just stick the index directly into the category masks:
let blockCategoryMask = UInt32(1<<4)
let ballCategoryMask = UInt32(1<<5)
Then the physics body for a block gets mask blockCategoryMask | UInt32(index), and similarly for a ball. In that case the index extraction is just categoryBitMask & UInt32(0xf). Or if you put the block and ball categories in bits 0 and 1 and the indexes in bits 2-5, then right shift by 2 to get the index.
Edit in response to comment:
OK, so let's take the case of 6 distinct categories of objects, and each object can fall into one of 16 distinct subcategories. To be able to control which contacts are reported, you'd assign a bit mask to each of the 6 main categories:
enum Category: UInt32 {
// Basic categories
case block = 0b000001
case ball = 0b000010
case shot = 0b000100
case obstacle = 0b001000
case wizard = 0b010000
case food = 0b100000
}
Since you've used 6 bits for the main category, you have 26 bits remaining. To encode the 16 subcategories needs 4 bits. You can put those in the category bit mask above the main 6 bits. Example manipulations:
func encodeObject(category: Category, subcategory: Int) -> UInt32 {
return category.rawValue | (UInt32(subcategory) << 6)
}
func nodeIsA(node: SKNode, category: Category) -> Bool {
guard let body = node.physicsBody else { return false }
return (body.categoryBitMask & category.rawValue) != 0
}
func subcategory(node: SKNode) -> Int {
guard let body = node.physicsBody else { fatalError("missing physicsbody") }
return Int(body.categoryBitMask >> 6)
}
Note that the subcategories are just sort of tagging along for the ride; all your contactBitMasks would deal only to the main categories.
Essentially you're using the fact that you've got some extra bits in the physics body category bit masks to just store random information. I've done that before with simple sprites. But if the information needed is going to get any more complex that a simple number or index, I'd recommend making subclasses of nodes rather than trying to squirrel stuff away in the unused bits.
Using contact.bodyA.node and contact.bodyB.node you can get the SKNode(s) which are involved in the contact
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
switch (contact.bodyA.node, contact.bodyB.node) {
case (let ball as Ball, let block as Block):
didBeginContactBetween(ball: ball, andBlock: block)
case (let block as Block, let ball as Ball):
didBeginContactBetween(ball: ball, andBlock: block)
default:
break
}
}
func didBeginContactBetween(ball: Ball, andBlock block: Block) {
// TODO: put your code here
}
}
I am working on drawing graphs on the terminal itself from inside a go code.I found this (https://github.com/gizak/termui) in golang. And used this(https://github.com/gizak/termui/blob/master/_example/gauge.go) to draw graph in my code.
Problem is this , as we can see in the code( https://github.com/gizak/termui/blob/master/_example/gauge.go ), they are passing g0,g1,g2,g3 all together in the end "termui.Render(g0, g1, g2, g3, g4)".
In my case I don't know how many gauges to draw before hand so I used a list to store gauge objects and then tried to pass list to render.
termui.Render(chartList...)
But it creates only one gauge.
This is how I am appending elements in the list.
for i := 0; i < 5; i++ {
g0 := termui.NewGauge()
g0.Percent = i
g0.Width = 50
g0.Height = 3
g0.BorderLabel = "Slim Gauge"
chartList = append(chartList, g0)
}
what I am getting is a gauge for i=4 only. when I am doing termui.Render(chartList...)
Am I doing something wrong?
PS - I have modified question based on the answer I got in this question.
Here is a good read on Variadic Functions
Take a look at the function signature of Render, https://github.com/gizak/termui/blob/master/render.go#L161
func Render(bs ...Bufferer) {
All you need to do is
termui.Render(chatList...)
assuming chartList is a []Bufferer
Edit
You are only seeing one because they are stacking on top of one-another. To see this add
g0.Height = 3
g0.Y = i * g0.Height // <-- add this line
g0.BorderLabel = "Slim Gauge"
From a quick review of the project, it appears there are ways for auto-arranging that have to do with creating rows (and probably columns). So you might want to explore that, or you will need to manually position your elements.
I'm trying to implement Jarvis' algorithm for finding the convex hull of a set of points, but for some reason it doesn't work. This is my implementation:
procedure TPointList.ConvexHull(aHull : TPointList); //Return the convex hull of a set of 2D points
var
vPointOnHull : TPoint2D;
vEndpoint : TPoint2D;
I : integer;
begin
aHull.Clear;
if Count < 3 then exit;
vPointOnHull := Self.LeftMostPoint;
repeat
aHull.Add(vPointOnHull);
vEndpoint := Self.Point[0];
for I := 1 to Self.Count-1 do
if Orientation(vPointOnHull,vEndpoint,Self.Point[I]) = LeftHandSide then
vEndpoint := Self.Point[I];
vPointOnHull := vEndpoint;
until vEndpoint = aHull.Point[0];
end;
TPointList is a simple list of points.
Orientation is a function from Arash Partow's library "FastGEO"
The implementation is lifted more or less directly from the Wikipedia article on the algorithm
What happens is that the method starts adding the same point to aHull over and over. In one test case I send in the points (200;200) (300;100) (200;50) and (100;100), and the algorithm starts by adding (100;100) to aHull which is correct, but then it starts adding (200;200) over and over again.
Obviously I've done something wrong in my implementation, but for the life of me I can't see what.
UPDATE:
Jonathan Dursi put me on the right track. This line
if Orientation(vPointOnHull,vEndpoint,Self.Point[I]) = LeftHandSide then
should be replaced with this
if (vPointOnHull = vEndpoint) or (Orientation(vPointOnHull,vEndpoint,Self.Point[I]) = LeftHandSide) then
Works like a charm :-)
It's probably not a conicidence that (200;200) is point 0.
It looks like you're not excluding the current point (vPointOnHull) from being the end point (vEndPoint), and your implementation of Orientation doesn't reject that case; presumably it returns LHS if the cross-product is positive, and if vPointOnHull == vEndPoint, the cross product is zero, so never LHS. So nothing ever replaces Point 0 once Point 0 is selected, et voila.
You could modify Orientation to return "Degenerate" or something in that case, and also reject the point, or you could exclude the current point from ever being the end point. Note that you don't want to do the obvious thing, filter out current CH points from the point set while marching through, because you need to find that the end point is the first point to close the loop.
Update: Looking around a bit at the FastGEO stuff, probably updating Orientation isn't the way to go (although a bit more thought should go into the colinear points case in this algorithm; if there are collinear points on the hull, you really want the closest one first, so you'd like an else if Orientation = Collinear then.. update vEndpoint if new point is closer clause after that if statement).
Easiest might just be to add a couple lines keeping track of the current indicies so you can easily test for equality: something a bit like
iPointOnHull := Self.IndexOfLeftMostPoint;
vPointOnHull := Self.LeftMostPoint
...
vEndpoint := Self.Point[0];
iEndPoint := 0;
if (iPointOnHull = 0) then
begin
vEndPoint := Self.Point[1];
iEndPoint := 1;
end
...
vPointOnHull := vEndPoint;
iPointOnHull := iEndPoint;
The loop adds using this line of code:
aHull.Add(vPointOnHull);
vPointOnHull is only assigned in these lines:
vPointOnHull := Self.LeftMostPoint;
vPointOnHull := vEndpoint;
You already explained that LeftMostPoint is added correctly, so the repeat must come from vEndPoint, which is assigned in these lines:
vEndpoint := Self.Point[0];
vEndpoint := Self.Point[I];
So I guess the last assignment (which is in the below if statement), is never reached.
if Orientation(vPointOnHull,vEndpoint,Self.Point[I]) = LeftHandSide then
vEndpoint := Self.Point[I];
--jeroen