I have an arbitrary number of polygons (hexes in this case) that are arranged randomly, but they are all touching another hex.
Each individual hex has 6 x,y vertices. The vertex's are known for all the hexes.
Can anyone point me in the direction of an algorithm that will combine all the hexes into a single polygon? Essentially I'm just looking for a function that spits out an array of vertex locations that are ordered in a way that when drawing lines from one to the next, it forms the polygon.
This is my method so far:
Create array of all the vertices for all the hexes.
Determine the number of times a vertex occurs in the array
If vertex is in the array 3+ times, delete the vertices from the array.
If vertex is in the array 2 times, delete one of them.
The next step is tricky though. I'm using canvas to draw out these polygons, which essentially involves drawing a line from one vertex to the next. So the order of the vertices in the final array is important. It can't be sorted arbitrarily.
Also, I'm not looking for a "convex hull" algorithm, as that would not draw the polygon correctly.
Are there any functions out there that do something like this? Am I on the right track or is there a better more efficient way?
I would do something like this:
List all the sides. A side is defined by two pairs of coordinates.
If any side shows up more than once remove all instances of that side.
Pick an arbitrary side, and from that side choose one of its points.
Place that point in an array.
Follow the current side and put the other point in the array.
Delete the side you just followed.
Then find the other side that has a point that is the same as the last point in the array. There will be only one such side. If there is none, you're done.
Go back to step 5.
You should now have an array of points that make up, in order, the shape you want.
Just be aware that this won't handle holes. The shape must be defineable by a single path.
without keeping track of the coordinate pairs that make up the lines, it would be impossible to determine the outer border of the shape
if you know the coordinate pairs that make up the lines, THEN
Create 2 lists, one of vertexs (list 1), one of the lines (list 2)
Remove all duplicate vertexes from the vertex list
Make a new list (list 3) of all the vertexes that have 3 lines attached to them
Using list 3, remove all the lines that have 2 vertexes from list 3 as their two coordinate pairs
It's time to traverse the shape, the list of lines remaining should form the shape you want
just start with an arbitrary coordinate and then
for each coordinate
for all lines
if (x1,y1) = current coordinate then add (x2,y2) to stack and remove that line from list
break
elseif (x2,y2) = current coordinate then add (x1,y1) to stack and remove that line from list
break
For each hex you have a list of 6 vertices. Sort the list, if necessary, so that the the vertices are ordered in counter-clockwise order (that's the mathematical convention).
Now you have a set of polygons (initially hexagons). The idea is to combine polygons until there is only one (or as few as can be).
Pick an edge of a polygon, and look for that same edge (i.e. that same pair of vertices) among the other polygons. If there are two instances, combine the two polygons at that edge, e.g. (a, b, c, d, e, f) + (g, h, d, c, i, j) => (a, b, c, i, j, g, h, d, e, f). (If the two vertices are in the same order in both polygons, or if there are three or more instances of the edge, report an error and abort.) Iterate through all edges. If the hexes really formed a contiguous group, there will be only one polygon left.
The polygon may have duplicated edges. If an edge occurs more than once, eliminate it by splitting the list in two, e.g. (a, b, c, d, b, a, e, f, g) => (b, c, d) + (a, e, f, g). Or if the the edges are adjacent, remove them: (a, b, c, b, d, e) => (a, b, d, e). Or if that list has only that edge, remove the list: (a,b) => nothing.
Once you've eliminated duplicate edges, there'll be one list for the counter-clockwise outer edge of the polygon, and perhaps one or more lists for the clockwise interior edges of holes.
Related
This is a 2 part problem that I have given some thought on.
Problem Statement:
In a m by n rectangular field there is a robber R and two cops C1 and C2. Each of the
three start off at some intial square, and at the beginning of the chase, R, C1, C2 all
know each other's positions.
R makes the first move, then C1 and C2. They can only move up, down, left or right. Some
squares are inaccessible because there is an obstacle present. If C1 or C2 reach a square
that R is on then they catch R.
In order to escape, R must reach a square X on the perimeter of the grid. If R reaches the square X before it's caught by C1 or C2, then R successfully escapes. Else, R is unable to escape.
As input we are provided: Values of m (number of rows) and n (number of columns), initial coordinates for R, C1, C2, and a list of inaccessible squares.
I) Using the input provided, how can you use an adjacency list to construct a graph to solve the problem. Analyze the runtime of graph creation.
I was actually thinking of using a adjacency matrix because of the grid representation, but we are asked to use and adjacency list. As a result, I'm confused on what should be considered a vertex and edge in this problem. I was think that every square in the grid will be a vertex and its edges will be all of its neighboring squares, at least the ones it can reach, 4 squares being the maximum. So should my adjacency list store ALL m by n pairs and then for every pair maintain a linked list of neighbors, i.e. squares reachable? If I went with this route there will be (m * n) vertices, and then for each of those I would have to check which squares are reachable (up, down, left, right) and whether that square is inaccessible, so I would have to scan through the inaccessible list provided as input which would take O(n) time. So I guess that would put me up to O(m*n) running time for graph creation. Can I do better than this?
II) Given the graph you create in part (I) describe an algorithm to check if R can escape.
*Assumption: The strategy that R, C1 and C2 is negligible. It doesn't matter if R,C1,C2 move in the "smart" way or completely random.
Since R declares its destination before the chase begins I think it's just a matter of whether there exists a path from where R starts at to its destination square. So can I get away with running DFS and check if R can reach its destination? But, I don't know R will be able to avoid C1 and C2.
Guidance is appreciated.
Sounds like you pretty much know how to build the graph, but it's better to give each vertex a number instead of maintaining (m,n) tuples.
Allocate an array of N * M lists. Each position (x,y) on the grid will correspond to slot x+n*y in that array. That slot will contain a list of adjacent accessible numbers or null if its an obstacle.
For now, initialize the array with an empty list at every position
For each obstacle, set its corresponding array slot to null.
For grid position (x,y), if its a vertex (array[x+n*y]!=null), then check its neighbors to fill out its adjacency list. If array[x+1+n*y]!=null, for example, then the list at [x+n*y] would include [x+1+n*y].
The resulting representation is pretty compact and good for many purposes. Since the vertexes have degree <= 4, an adjacency list is much more efficient than an adjacency matrix.
The remaining part of your program will be greatly simplified as well, since it doesn't have to deal with coordinates or know anything about the original grid.
Unfortunately, the "*Assumption" takes all the fun out of the second part.
If I have x and y coordinates for triangle corners A, B, and C, I want to know which of the six orderings of {A, B, C} put the shortest side of the triangle between the first two vertices in the ordering, and the second shortest side between the last two. I know how to solve this, but not in a way that isn't clumsy and inelegant and all around ugly. My favorite language is Ruby, but I respect all of them.
As the third side of a triangle cannot be deduced from the other two, you must compute the three distances.
As the three points may require to be permuted in one of six ways, you cannot work this out with a decision tree that has less than three levels (two levels can distinguish at most four cases).
Hence, compute the three distances and sort them increasingly using the same optimal decision tree as here: https://stackoverflow.com/a/22112521/1196549 (obviously their A, B, C correspond to your distances). For every leaf of the tree, determine what permutation of your points you must apply.
For instance, if you determine |AB|<|CA|<|BC|, you must swap A and B. Solve all six cases similarly.
Doing this you will obtain maximally efficient code.
If you are completely paranoid like I am, you can organize the decision tree in such a way that the cases that require a heavier permutation effort are detected in two tests rather than three.
Here's how I would do it: let's take a triangle with sides x, y, and z, such that l(x) <= l(y) <= l(z). Then, let x', y', and z' be the vertices opposite to x, y, and z, respectively.
Your output will be y', z', x' (if you draw out your triangle, you'll see that this is the order which achieves your requirement). So, the pseudocode looks like:
For points a, b, c each with some coordinates (x, y), calculate the length of the segment opposite to each point (e.g. for a this is segment bc)
Order a, b, c by the length of their opposing segment in the order of [2nd longest, longest, shortest]
Return
Does this make sense? The real work is mapping to the euclidean distance between the opposing points. If you get stuck, update your question with your code and I'm happy to help you work it out.
Given a mesh consisting of a list of vertices (2D coordinates) and edges (as vertex pairs), like so:
So the edges are defined like this:
a: 2,3
b: 3,4
c: 4,8
d: 5,8
e: 6,7
etc..
Edges are orientation-neutral, i.e. the order of any two vertices that define an edge is random (edges are not clockwise or counter clockwise).
Polygons may be convex or concave, but they never overlap or self-intersect (edges never cross eachother).
Question: how do I generate a list of all polygons?
More specifically, in the above example I would need 4 polygons, like so:
(a,b,c,d,i)
(d,g,h)
(f,i,j,k)
(e,h,k)
The polygons have no orientation either, clockwise or counterclockwise does not apply, and in fact the order of the edges that define a polygon may be random as well. For example (a,i,d,b,c) for the 5-sided one would be fine as well.
Instead of defining polygons as a list of edges, it could also be a list of connected vertices, like so:
(2,3,4,8,5)
(6,5,8)
(2,5,7,1)
(7,6,5)
In this case, the order of the vertices cannot be random (the list of vertices should be a circular sequence) but orientation (clockwise or counterclockwise) is still irrelevant. So the 4-sided polygon could also be (5,2,1,7) or (1,7,5,2) et cetera.
What is an efficient (fast) way to construct a list of polygons, defined in either edges or vertices?
For each edge vw, generate two half-edges v->w and w->v. Partition these by head (the head of x->y is y). Within each partition, sort by angle (if you use a comparison sort, then there's a way to avoid trig).
For your sample graph, the result is
7->1, 2->1
1->2, 5->2, 3->2
2->3, 4->3
8->4, 3->4
7->5, 6->5, 8->5, 2->5
8->6, 5->6, 7->6
6->7, 5->7, 1->7
5->8, 6->8, 4->8
. Now, define a permutation where v->w maps to the half-edge following w->v in the list containing w->v (wrapping around if necessary). The cycles of this permutation are the polygons.
For example, 5->8 maps to 2->5 (after 8->5) maps to 3->2 (after 5->2) maps to 4->3 (after 2->3) maps to 8->4 (after 3->4) maps to 5->8 (after 4->8).
I have an array of triangle vertices (faces of the polygon), something like
[[[a, b, c], [d, e, f], [g, h, i]], ...]
I have a line segment, represented by 2 3D vertices, let's say [[j, k, l], [m, n, o]].
And I have a point [p, q, r].
What I want to do is, project the point on the polygon, through the line segment, and check if it completely slices the polygon (I think 4 points of contact should be enough? I could be wrong). And if it does, I need all the points of intersection which lie on the edges and vertices.
I'm completely lost here. Any pointers would be appreciated.
We can assume without loss of generality that the triangle formed by the point & line segment (henceforth T) lies in the x-y plane. (Otherwise, rotate everything appropriately).
We loop through the triangle faces, for any pair of vertices of a face where their y-coordinates have different signs (i.e. for any edge that cuts the x-y plane), we check the intersection of the edge with the x-y plane and make sure it's within T.
It holds that T "completely slices the polygon" if and only if all such checks are true.
Running time is O(number of faces).
All the operations described are pretty simple. E.g. Checking that something is in the bounds of T is simply checking two inequalities with the equations of the two lines that define T (i.e. from the point to the end points of the line segment).
All POI with the edges (and thus vertices) can be calculated within the loop - it's simply the POI of the edge with the x-y plane.
I have a list a vertices and a list of triangles. I'd like to split this single mesh into, say 5, randomly shaped meshes. When the 5 randomly shaped meshes are in place the sphere should all line up and look like 1 solid mesh.
I need a algorithm to do this programmatically, not a tool to do it form me. Any pointers would be great!
Similar to Svante's proposal but a slightly different approach:
Select five random vertices, mark these vertices as "visited" with the number 1 to 5
From each of the visited vertices, go to all adjacent vertices. Store the same number there as well.
If you visit a vertex which already has a number assigned, stop there
Stop, if all vertices are visited. All vertices marked with the same number end up in the same piece
This appears to me to be the simplest to implement, while still resulting in nice puzzle pieces. For added random-ness, you could add a probability, of visiting each adjacent vertex.
Nevertheless, any "too random" approach might result in heavily concave pieces, like very long pieces consisting only of a long strip of single triangles; and pieces with deep ugly thin cuts into them. You should possibly specify another question on how to make nice puzzle pieces (and what nice puzzle pieces are!) if you care for that.
You could make a crack by walking a random walk across the edges, until the number of pieces you want is achieved. If you want to have mostly big pieces, you could modify the randomness of the walk by reducing the attractiveness of edges that are close to an existing crack.
Select 3 random points and split along that plane. What is the problem?
When you split a triangle along a plane you end up in one of two situations: either the plane doesn't intersect either line segments in the triangle or it intersects exactly two line segments. Only triangles that are intersected are interesting.
If you have triangle (A, B, C), with A, B and C being vertices.
Assume that the plane intersects the line segments (A, B) and (A, C) in the points D and E.
Define a vertex, F, between B and C (for example B + (C - B) / 2), but any vertex on the line segment between B and C will do).
Your new triangles are then the following
(A, D, E), (B, D, F), (D, E, F) and (C, E, F)