Getting outline of a graph as a polygon in PyGame - python

I have a feeling that this is impossible (or at least very complicated), but I currently have a generated graph that looks something like this (excuse my terrible paint skills):
Now, I'd like to be able to create a polygon of the outline, I have the coordnates of all the nodes, but not the intersections. The best I can manage so far is the Gift Wrapping algorithm, which gives more of a rough outline of the polygon than anything else.
Does anyone have any ideas as to how I could go about this?
(I'm currently using PyGame)

You're going to want to figure out where intersections happen and make new nodes there.
Then you want to find an edge that's on the outer polygon. I suggest running a random ray in from infinity until it strikes an edge.
Then imagine yourself walking along that edge, keeping your left hand on the boundary and your right hand outside. Start walking.
When you hit a node, you turn, such that you don't cross any edge. That is, you begin to traverse the next edge in counterclockwise order. (A simple implementation of this would be to sort them by direction, using atan2().)
It's all basic high school algebra and trigonometry, but it might be a little rough if this is your first time programming anything of this nature. You'll learn a lot, though.

Related

What is causing this unusual cull and how can I fix it?

I am an extreme novice to OpenGL, just trying to hack something together for a personal project. When I enabled GL_CULL_FACE I mostly got what I wanted, except a big triangle chunk is now missing from my cube!
What might be happening here and how can I fix it? I made this cube with 6 GL_QUADS, so I never expected to be missing a triangle like this...
Each polygon has a "front" and "back" side, and when culling is on you only see polygons whose "front" is toward you (the ones for which the normal is pointing toward the camera).
The fact that this face is getting culled from this angle suggests that its normal points inside the cube instead of outside; to flip it around, reverse the order in which you specify the vertices.

Pipeline to create Voronoi Meshes

I would like to implement a Maya plugin (this question is independent from Maya) to create 3D Voronoi patterns, Something like
I just know that I have to start from point sampling (I implemented the adaptive poisson sampling algorithm described in this paper).
I thought that, from those points, I should create the 3D wire of the mesh applying Voronoi but the result was something different from what I expected.
Here are a few example of what I get handling the result i get from scipy.spatial.Voronoi like this (as suggested here):
vor = Voronoi(points)
for vpair in vor.ridge_vertices:
for i in range(len(vpair) - 1):
if all(x >= 0 for x in vpair):
v0 = vor.vertices[vpair[i]]
v1 = vor.vertices[vpair[i+1]]
create_line(v0.tolist(), v1.tolist())
The grey vertices are the sampled points (the original shape was a simple sphere):
Here is a more complex shape (an arm)
I am missing something? Can anyone suggest the proper pipeline and algorithms I have to implement to create such patterns?
I saw your question since you posted it but didn’t have a real answer for you, however as I see you still didn’t get any response I’ll at least write down some ideas from me. Unfortunately it’s still not a full solution for your problem.
For me it seems you’re mixing few separate problems in this question so it would help to break it down to few pieces:
Voronoi diagram:
The diagram is by definition infinite, so when you draw it directly you should expect a similar mess you’ve got on your second image, so this seems fine. I don’t know how the SciPy does that, but the implementation I’ve used flagged some edge ends as ‘infinite’ and provided me the edges direction, so I could clip it at some distance by myself. You’ll need to check the exact data you get from SciPy.
In the 3D world you’ll almost always want to remove such infinite areas to get any meaningful rendering, or at least remove the area that contains your camera.
Points generation:
The Poisson disc is fine as some sample data or for early R&D but it’s also the most boring one :). You’ll need more ways to generate input points.
I tried to imagine the input needed for your ball-like example and I came up with something like this:
Create two spheres of points, with the same center but different radius.
When you create a Voronoi diagram out of it and remove infinite areas you should end up with something like a football ball.
If you created both spheres randomly you’ll get very irregular boundaries of the ‘ball’, but if you scale the points of one sphere, to use for the 2nd one you should get a regular mesh, similar to ball. You can also use similar points, but add some random offset to control the level of surface irregularity.
Get your computed diagram and for each edge create few points along this edge - this will give you small areas building up the edges of bigger areas. Play with random offsets again. Try to ignore edges, that doesn't touch any infinite region to get result similar to your image.
Get the points from both stages and compute the diagram once more.
Mesh generation:
Up to now it didn’t look like your target images. In fact it may be really hard to do it with production quality (for a Maya plugin) but I see some tricks that may help.
What I would try first would be to get all my edges and extrude some circle along them. You may modulate circle size to make it slightly bigger at the ends. Then do Boolean ‘OR’ between all those meshes and some Mesh Smooth at the end.
This way may give you similar results but you’ll need to be careful at mesh intersections, they can get ugly and need some special treatment.

Separating Axis Theorem in Python/Pyglet

I'm trying to make a (sort-of) clone of Asteroids in Python using Pyglet. I figured I'd try to get a little fancy and implement the separating axis theorem to do collision. I got it to work, but the problem is that it's miserably slow. I test collision between bullets that the player shoots and the asteroids on the screen in a double for-loop, which I believe is quadratic time, but the frame rate drops from about 60 to 30 fps by the time there's about 6 asteroids and 6 bullets on the screen, which seems incredibly slow, even for a non-optimized way of detecting collision.
So I ran a profiler to determine where, exactly, in the code the program is getting hung up. It seems to be hung up in the method where I transform shape vertices into world space (I define the shapes around the origin and use OpenGL code to transform to world space for drawing, which I believe is the right way to do it). I grab the transformation matrix from OpenGL, turn it into a NumPy array, and then multiply each vertex by this matrix to get the transformed vertices. It's worth noting that I do this every collision check: I used to use XNA, and when I implemented the SAT in that (I made an asteroids clone there, too), the vertices were also defined around the origin and then you had to transform them using a world matrix.
Is it best to store the vertices around (0, 0) and transform each call, or just store the transformed vertices? I feel like the algorithm shouldn't be THIS slow, so I'm willing to bet I screwed up implementing something. If I was better at profiling (I'm pretty unfamiliar with it) I might be able to get a more complete picture, but I was hoping you guys might have some idea.
Here's a direct link to the file with the Shape class in it, where all the collision logic happens: shape.py. The specific method that the profiler seemed to mark as the bottleneck was __get_transformed_verts. Obviously you can get to the entire repo from there too, but just be aware that there's still a good deal not commented.
As Nico suggests in comments, a quick way to get a good speed-up would be to check simpler geometry first. For an Asteroids clone I guess a circle will be a good fit (or sphere for 3D). If the circles (at least large enough to cover your actual shape) don't overlap, then there is no need to do the more expensive geometry test.
If you have many objects, you will probably want to avoid doing n*n tests every frame. Take a look at space partitioning structures/algorithms. The simplest scheme with a lot of moving objects in 2D would be a grid. Then you only need to test objects belonging to the same - or neighbouring - grid cells for collision.
Another thing I noticed: You generate the transformed vertices every time you test for collision. It would be quicker to generate them only once per timestep (frame) for each object that fails the circle-circle test.

Region Growing Algorithm

Hey everyone. I'm really struggling to figure out the logic with this one and was hoping you could help me out. Before I continue I just want to let you know that I am amateur programmer and a beginner at that, with no formal Computer Science training of any sort, so please bear with me. :D Also, I'm using Python, but I could use Java or something similar.
Anywho, I am looking to implement a Region Growing for use in a rudimentary Drawbot.
Here is an article on region growing: http://en.wikipedia.org/wiki/Region_growing
The way I envision it, the image the draw is based upon will meet the following criteria:
The image will be at most 3x3 inches in size at an arbitrary Color Depth
The image will be a black continuous shape on a white background
The shape can be located anywhere on the background.
I've considered the following solutions to this problem. While some work to an extent, each has some considerable flaws in either their performance or feasibility (at least they don't seem feasible to me). Furthermore, because this is a Drawbot, this needs to be done with a single continuous line. This doesn't mean however that I can't backtrack, it only eliminates the possibility of multiple starting points (seeds).
Considered Approaches:
Random Walk:
Solving this problem with a random walk was my first instinct. A random walk program accomplishing this would, I imagine, look something like this:
pseudo python...
Cells To Visit = Number of Black Cells
Cells Visited = 0
MarkColor = red
While Cells Visited < Cells To Visit:
if currentcell is black:
Mark Current Cell As Visited #change pixel to red
Cells Visited +=1
neighbors = Get_Adjacent_Cells() #returns cells either black or red
next cell = random.choose(neighbors)
currentCell = next cell
While I suppose this is feasible, it seems to me to be highly ineffective and doesn't guarantee good results, but in the interest of actually getting something done I may end up trying this... Is my logic in the pseudocode even vaguely correct?
Sweeping Pattern:
This method to me seemed to be the most trivial to implement. My idea here is that I could choose a starting point at one extreme of the shape (e.g. the lowest most left point). From there it would draw to the right, moving only on the x axis until it hit a white pixel. From here it would move up one pixel on the y axis, and then move left on the x axis until it reached a white pixel. If the pixel directly above it happend to be white, backtrack on the x axis until it finds a black pixel above it.
This method upon further inspection has some major short comings.
When faced with a shape such as this:
The result will look like this:
And even if I were to tell it to start sweeping down after awhile, the middle leg would still be overlooked.
4/8 Connected Neighborhood:
http://en.wikipedia.org/wiki/8-connected_neighborhood
This method appears to me to be the most powerful and effective, but at this point I can't figure it out fully, nor can I think of how I would implement it without potentially leaving some overlooked areas
At every cell I would look at the neighboring black cells, devise some method for ranking which one I should visit first, visit all of them, and repeat the process until all cells are covered.
The problems I could see here is first of all dealing with the data structure necessary to accomplish this, and also merely figuring out the logic behind it.
Those are the best solutions I've been able to think of. Thank you for taking the time to read this, I realize it is long, but I thought that I should make it as explicit as possible. Any and all suggestions will be greatly appreciated... Thanks!
Edit:
I also looked into maze generating and solving algorithms, but wasn't sure how to implement that here. My understanding of the maze solving algorithms is that they rely on the passages of the maze to be of equal width. I could of course be wrong about that.
Basic region growing, in pseudocode looks something like:
seed_point // starting point
visited // boolean array/matrix, same size as image
point_queue // empty queue
point_queue.enqueue( seed_point )
visited( seed_point ) = true
while( point_queue is not empty ) {
this_point = point_queue.dequeue()
for each neighbour of this_point {
if not visited( neighbour ) and neighbour is black/red/whatever
point_queue.enqueue( neighbour )
visited( neighbour ) = true
}
}
// we are done. the "visited" matrix tells
// us which pixels are in the region
I don't understand where the ranking that you've mentioned comes into it though. Am I missing something?
I'm confused by the very long question.
Are you sure you aren't just trying to do a flood fill?
Here's a really nice little screencast on writing a recursive maze solver: http://thinkcode.tv/catalog/amazing-python/
I think it might give you some ideas for the problem you are trying to solve.
Also, here's a little recursive maze solving script that I wrote after watching the screencast http://pastie.org/1854582. Equal width passages are not necessary, the only things that are necessary are open space, walls, and some kind of an ending condition, in this case, finding the end of the maze.
If you don't want to go recursive, the other thing you can do is use a "backtracking" method. You can see a little example of it being used in the random generation of mazes on this page:
http://weblog.jamisbuck.org/2011/2/7/maze-generation-algorithm-recap (First example on the page).
Is this sounding relevant? If it is, let me know if you want me to explain anything in more detail.
Edit:
This seems like a really good discussion on doing flood fills in python http://www.daniweb.com/software-development/python/threads/148874
A simple technique that can help with some maze solving problems, of keeping one hand on the wall, might help.
Note however that if you chose a random starting point, you might chose a point that whichever way you travel from there, you block off a portion. i.e. if you were to start in the middle of an hour-glass shape, you would only be able to fill in one half.

Distance by sea calculator, intermediate coordinates?

How do I calculate distance between 2 coordinates by sea? I also want to be able to draw a route between the two coordinates.
Only solution I found so far is to split a map into pixels, identify each pixel as LAND or SEA and then try to find the path using A* algorithm. Then transform pixels to relative coordinates.
There are some software packages I could buy but none have online extensions. A service that calculates distances between sea ports and plots the path on a map is searates.com
Beware of the fact that maps can distort distances. For example, in a Mercator projections segments far away from the equator represent less actual distance than segments near the equator of equal length. If you just assign uniform cost to your pixels/squares/etc, you will end up with non-optimal routing and erroneous distance calculations.
If you project a grid on your map (pixels being just one particular grid out of many possible ones) and search for the optimal path using A*, all you need to do to get the search algorithm to behave properly is set the edge weight according to the real distance along the surface of the sphere (earth) and not the distance on the map.
Beware that simply saying "sea or not-sea" is not enough to determine navigability. There are also issues of depth, traffic routing (e.g. shipping traffic thought the English Channel is split into lanes) and political considerations (territorial waters etc). You also want to add routes manually for channels that are too small to show up on the map (Panama, Suez) and adjust their cost to cover for any overhead incurred.
Pretty much you'll need to split the sea into pixels and do something like A*. You could optimize it a bit by coalescing contiguous pixels into larger areas, but if you keep everything squares it'll probably make the search easier. The search would no longer be Manhattan-style, but if you had large enough squares, the additional connection decision time would be more than made up for.
Alternatively, you could iteratively "grow" polygons from all of your ports, building up convex polygons (so that any point within the polygon is reachable from any other without going outside, you want to avoid the PacMan shape, for instance), although this is a refinement/complication/optimization of the "squares" approach I first mentioned. The key is that you know once you're in an area that you can get to anywhere else in that area.
I don't know if this helps, sorry. It's been a long day. Good luck, though. It sounds like a fun problem!
Edit: Forgot to mention, you could also preprocess your area into a quadtree. That is, take your entire map and split it in half vertically and horizontally (you don't need to do both splits at the same time, and if you want to spend some time making "better" splits, you can do that later), and do that recursively until each node is entirely land or sea. From this you can trivially make a network of connections (just connect neighboring leaves), and the A* should be easy enough to implement from there. This'll probably be the easiest way to implement my first suggestion anyway. :)
I reached a satisfactory solution. It is along the lines of what you suggested and what I had in mind initially but it took me a while to figure out the software and GIS concepts, I am a GIS newbie. If someone bumps into something similar again here's my setup: PostGIS for PostgreSQL, maps from Natural Earth, GIS editing software qGis and OpenJUmp, routing algorithms pgRouting.
The Natural Earth maps needed some processing to be useful, I joined the marine polys and the rivers to be able to get some accurate paths to the most inland points. Then I used the 1 degree graticules to get paths from one continent to another (I need to find a more elegant solution than this because some paths look like chess cubes). All these operations can be done from command line by using PostGIS, I found it easier to use the desktop software (next, next). An alternative to Natural Earth maps might be the OpenStreetMap but the planet.osm dump is aroung 200Gb and that discouraged me.
I think this setup also solves the distance accuracy problem, PostGIS takes into account the Earth's actual form and distances should be pretty accurate.
I still need to do some testing and fine tunings but I can say it can calculate and draw a route from any 2 points on the world's coastlines (no small isolated islands yet) and display the routing points names (channels, seas, rivers, oceans).

Categories