Polygon border algorithm? - algorithm

I have an array set of (x,y) values that define a polygon. The polygon is drawn based on the point's position * a pencil size. The thing is that i want to draw the border of such shape, ignoring the inner vertexes. See this example, the BLACK vertex are the ones i'm interested in, i want to get rid of the YELLOW ones.
I'd like to get the X in another array, ordered clockwise. Been thinking about evaluating every point to see if has a neighbor and where (north, south, east, west) but seems like too much crunching to check in every vertex and i believe must be another proven and more elegant algorithm.
Any tip?

Since your "points" are just little squares, it sounds like your inner points (those which don't contribute to the border of the shape) are just those where (x-1,y), (x+1,y), (x,y-1), and (x,y+1) are also all points.
You can do that test quickly by putting all of your points in a hashtable (or one of many other indexed structures).
Ordering clockwise just requires walking the border. You have to decide what you'd like to do about holes, if there are any.

Normally, a polygon is defined by an outline. That's an unfortunate format you have to deal with there.
If they're laid out like that (in rows with the same y coord) then you can just sort the array, first by x and then by y, then take the first point, the two points around any change in y, and the last point to form your outline.
If the real state of things is a little messier, then you might want to look into 'alpha shapes'. Some links: http://biogeometry.duke.edu/software/alphashapes/, http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/alpha.html

Make sprite borders, place it same position every square and sorting oderlayout behind

Related

How to represent a sphere surface in computer memory?

As the title suggest my problem lies in some representation of a sphere surface in computer memory. For simplicity, let's say we are making a chess game where the board is on a sphere. If the board was a classic flat board, then the solution is simple: use a 2D table.
But I don't know what kind of a memory structure I should chose for a sphere. Namely, what I want from this representation are:
If I move a pawn stubbornly in one direction, then I should return to the point where I started,
During such "journey" I should cross a point directly on the other side of the sphere (I mean to avoid a common "error" in a 2D game where moving pass an edge of a board will move an object to the opposite edge, thus making the board a torus, not a real sphere)
the area of one board cell should be approximately equal to any other cell
a cell should have got an associated longitude-latitude coordinates (I wrote "associated" because I want from the representation to only have got some way to obtain these coordinates from the position of a cell, not to be eg. a table with lat-long indexes)
There's no simple geometric solution to this. The crux of the problem is that, say you have n columns at the equator, and you're currently near the north poll, and heading north. Then the combination of the direction and the column number from the top row (and second from top row) must be able to uniquely identify which one of the n positions at the equator that path is going to cross. Therefore, direction could not be an integer unless you have n columns in the top (or second to top) row. Notice that if the polygons have more than three sides, then they must have common edges (and triangles won't work for other reasons). So now you have a grid, but if you have more than three rows (i.e. a cube, or other regular prism), then moving sideways on the second-to-top row will not navigate you to the southern hemisphere.
The best bet might be to create a regular polyhedron, and keep the point and direction as floating point vectors/points, and calculate the actual position when you move, and figure out which polygon you land in (note, you would have the possibility of moving to non-adjacent polygons with this method, and you might have issues if you land exactly on an edge/vertex, etc).

given N disjoint triangles in 2D space, discover which one contains a given point without iterating through everyone

Pretty straightforward: given N triangles T1, ... ,Tn and a point P, what is the best approach to find an i such that P is inside Ti?
PS: Don't know if this is important, but the triangles are disposed as if they were part of the map of a country (for example, get any country and draw it only with triangles, thats how the given triangles should be placed like).
If preprocessing is an option, you can consider inserting your triangles in an R-tree.
https://en.wikipedia.org/wiki/R-tree
Update:
If there is a single point, there is no shortcut. Exhaustive comparison is mandated. Otherwise the algorithm could "guess" the position of some triangles without even looking at them.
Make use of Sweepline algorithm. You need to order triangles from their left to right co-ordinates.
Make a Minpriority queue and put all triangles(co-ordinates , left and right, so each trinangle will be inserted twice, the first point is begin point(x-min) and the second point is end point(x-max)) in priotity queue and the co-ordinates of point also.
Remove the first co-ordinate:
if it is left point then put it in binary search tree along witht triangle whose co-ordinate is this.
If it is right co-ordinate then remove the triangle from the binarysearchtree.
If it is co-ordinates of point then the your point must lie in only those triangles who are in binarysearchtree.

Getting the boundary of a hole in a 3d plane

I have a set of 3d points that lie in a plane. Somewhere on the plane, there will be a hole (which is represented by the lack of points), as in this picture:
I am trying to find the contour of this hole. Other solutions out there involve finding convex/concave hulls but those apply to the outer boundaries, rather than an inner one.
Is there an algorithm that does this?
If you know the plane (which you could determine by PCA), you can project all points into this plane and continue with the 2D coordinates. Thus, your problem reduces to finding boundary points in a 2D data set.
Your data looks as if it might be uniformly sampled (independently per axis). Then, a very simple check might be sufficient: Calculate the centroid of the - let's say 30 - nearest neighbors of a point. If the centroid is very far away from the original point, you are very likely on a boundary.
A second approach might be recording the directions in which you have neighbors. I.e. keep something like a bit field for the discretized directions (e.g. angles in 10° steps, which will give you 36 entries). Then, for every neighbor, calculate its direction and mark that direction, including a few of the adjacent directions, as occupied. E.g. if your neighbor is in the direction of 27.4°, you could mark the direction bits 1, 2, and 3 as occupied. This additional surrounding space will influence how fine-grained the result will be. You might also want to make it depend on the distance of the neighbor (i.e. treat the neighbors as circles and find the angular range that is spanned by the circle). Finally, check if all directions are occupied. If not, you are on a boundary.
Alpha shapes can give you both the inner and outer boundaries.
convert to 2D by projecting the points onto your plane
see related QA dealing with this:
C++ plane interpolation from a set of points
find holes in 2D point set
simply apply this related QA:
Finding holes in 2d point sets?
project found holes back to 3D
again see the link in #1
Sorry for almost link only answer but booth links are here on SO/SE and deals exactly with your issue when combined. I was struggling first to flag your question as duplicate and leave this in a comment but this is more readable.

Closest distance to border of shape

I have a shape (in black below) and a point inside the shape (red below). What's the algorithm to find the closest distance between my red point and the border of the shape (which is the green point on the graph) ?
The shape border is not a series of lines but a randomly drawn shape.
Thanks.
So your shape is defined as bitmap and you can access the pixels.
You could scan ever growing squares around your point for border pixels. First, check the pixel itself. Then check a square of width 2 that covers the point's eight adjacent pixels. Next, width 4 for the next 16 pixels and so on. When you find a border pixel, record its distance and check against the minimum distance found. You can stop searching when half the width of the square is greater than the current minimum distance.
An alternative is to draw Bresenham circles of growing radius around the point. The method is similar to the square method, but you can stop immediately when you have a hit, because all points are supposed to have the same distance to your point. The drawback is that this method is somewhat inaccurate, because the circle is only an approximation. You will also miss some pixels along the disgonals, because Bresenham circles have artefacts.
(Both methods are still quite brute-force and in the worst case of a fully black bitmap will visit every node.)
You need a criterion for a pixel on the border. Your shape is antialiassed, so that pixels on the border are smoothed by making them a shade of grey. If your criterion is a pixel that isn't black, you will chose a point a bit inside the shape. If you cose pure white, you'll land a bit outside. Perhaps it's best to chose a pixel with a grey value greater than 0.5 as border.
If you have to find the closest border point to many points for the same shape, you can preprocess the data and use other methods of [nearest-neighbour serach].
As always, it depends on the data, in this case, what your shapes are like and any useful information about your starting point (will it often be close to a border, will it often be near the center of mass, etc).
If they are similar to what you show, I'd probably test the border points individually against the start. Now the problem is how you find the border without having to edge detect the entire shape.
The problem is it appears you can have sharply concave borders (think of a circle with a tiny spike-like sliver jutting into it). In this case you just need to edge detect the shape and test every point.
I think these will work, but don't hold me to it. Computational geometry seems to be very well understood, so you can probably find a pro at this somewhere:
Method One
If the shape is well behaved or you don't mind being wrong try this:
1- Draw 4 lines (diving the shape into four quandrants). And check the distance to each border. What i mean by draw is keep going north until you hit a white pixel, then go south, west, and east.
2- Take the two lines you have drawn so far that have the closest intersection points, bisect the angle they create and add the new line to your set.
3- keep repeating step two until are you to a tolerance you can be happy with.
Actually you can stop before this and on a small enough interval just trace the border between two close points checking each point between them to refine the final answer.
Method Two (this wil work with the poorly behaved shapes and plays well with anti-aliasing):
1- draw a line in any direction until he hit the border (black to white). This will be your starting distance.
2- draw a circle at this distance noting everytime you go from black to white or white to black. These are your intersection points.
As long as you have more than two points, divide the radius in half and try again.
If you have no points increase your radius by 50% and try again (basically binary search until you get to two points - if you get one, you got lucky and found your answer).
3- your closet point lies in the region between your two points. Run along the border checking each one.
If you want to, to reduce the cost of step 3 you can keep doing step 2 until you get a small enough range to brute force in step 3.
Also to prevent a very unlucky start, draw four initial lines (also east, south, and west) and start with the smallest distance. Those are easy to draw and greatly reduce your chance of picking the exact longest distance and accidentally thinking that single pixel is the answer.
Edit: one last optimization: because of the symmetry, you only need to calculate the circle points (those points that make up the border of the circle) for the first quadrant, then mirror them. Should greatly cut down on computation time.
If you define the distance in terms of 'the minimum number of steps that need to be taken to reach from the start pixel to any pixel on the margin', then this problem can be solved using any shortest path search algorithm like bread first search or even better if you use A* search algorithm.

Converting vector-contoured regions (borders) to a raster map (pixel grid)

I have a map that is cut up into a number of regions by borders (contours) like countries on a world map. Each region has a certain surface-cover class S (e.g. 0 for water, 0.03 for grass...). The borders are defined by:
what value of S is on either side of it (0.03 on one side, 0.0 on the other, in the example below)
how many points the border is made of (n=7 in example below), and
n coordinate pairs (x, y).
This is one example.
0.0300 0.0000 7
2660607.5 6332685.5 2660565.0 6332690.5 2660541.5 6332794.5
2660621.7 6332860.5 2660673.8 6332770.5 2660669.0 6332709.5
2660607.5 6332685.5
I want to make a raster map in which each pixel has the value of S corresponding to the region in which the center of the pixel falls.
Note that the borders represent step changes in S. The various values of S represent discrete classes (e.g. grass or water), and are not values that can be averaged (i.e. no wet grass!).
Also note that not all borders are closed loops like the example above. This is a bit like country borders: e.g. the US-Canada border isn't a closed loop, but rather a line joining up at each end with two other borders: the Canada-ocean and the US-ocean "borders". (Closed-loop borders do exist nevertheless!)
Can anyone point me to an algorithm that can do this? I don't want to reinvent the wheel!
The general case for processing this sort of geometry in vector form can be quite difficult, especially since nothing about the structure you describe requires the geometry to be consistent. However, since you just want to rasterize it, then treating the problem as a Voronoi diagram of line segments can be more robust.
Approximating the Voronoi diagram can be done graphically in OpenGL by drawing each line segment as a pair of quads making a tent shape. The z-buffer is used to make the closest quad take precedence, and thus color the pixel based on whichever line is closest. The difference here is that you will want to color the polygons based on which side of the line they are on, instead of which line they represent. A good paper discussing a similar algorithm is Hoff et al's Fast Computation of Generalized Voronoi Diagrams Using Graphics Hardware
The 3d geometry will look something like this sketch with 3 red/yellow segments and 1 blue/green segment:
This procedure doesn't require you to convert anything into a closed loop, and doesn't require any fancy geometry libraries. Everything is handled by the z-buffer, and should be fast enough to run in real time on any modern graphics card. A refinement would be to use homogeneous coordinates to make the bases project to infinity.
I implemented this algorithm in a Python script at http://www.pasteall.org/9062/python. One interesting caveat is that using cones to cap the ends of the lines didn't work without distorting the shape of the cone, because the cones representing the end points of the segments were z-fighting. For the sample geometry you provided, the output looks like this:
I'd recommend you to use a geometry algorithm library like CGAL. Especially the second example in the "2D Polygons" page of the reference manual should provide you what you need. You can define each "border" as a polygon and check if certain points are inside the polygons. So basically it would be something like
for every y in raster grid
for every x in raster grid
for each defined polygon p
if point(x,y) is inside polygon p
pixel[X][Y] = inside_color[p]
I'm not so sure about what to do with the outside_color because the outside regions will overlap, won't they? Anyway, looking at your example, every outside region could be water, so you just could do a final
if pixel[X][Y] still undefined then pixel[X][Y] = water_value
(or as an alternative, set pixel[X][Y] to water_value before iterating through the polygon list)
first, convert all your borders into closed loops (possibly including the edges of your map), and indentify the inside colour. this has to be possible, otherwise you have an inconsistency in your data
use bresenham's algorithm to draw all the border lines on your map, in a single unused colour
store a list of all the "border pixels" as you do this
then for each border
triangulate it (delaunay)
iterate through the triangles till you find one whose centre is inside your border (point-in-polygon test)
floodfill your map at that point in the border's interior colour
once you have filled in all the interior regions, iterate through the list of border pixels, seeing which colour each one should be
choose two unused colors as markers "empty" and "border"
fill all area with "empty" color
draw all region borders by "border" color
iterate through points to find first one with "empty" color
determine which region it belongs to (google "point inside polygon", probably you will need to make your borders closed as Martin DeMello suggested)
perform flood-fill algorithm from this point with color of the region
go to next "empty" point (no need to restart search - just continue)
and so on till no "empty" points will remain
The way I've solved this is as follows:
March along each segment; stop at regular intervals L.
At each stop, place a tracer point immediately to the left and to the right of the segment (at a certain small distance d from the segment). The tracer points are attributed the left and right S-value, respectively.
Do a nearest-neighbour interpolation. Each point on the raster grid is attributed the S of the nearest tracer point.
This works even when there are non-closed lines, e.g. at the edge of the map.
This is not a "perfect" analytical algorithm. There are two parameters: L and d. The algorithm works beautifully as long as d << L. Otherwise you can get inaccuracies (usually single-pixel) near segment junctions, especially those with acute angles.

Resources