I have an array of convex polygons which may share edges (each polygon is represented by an array of its vertices). When some of these polygons share edges, I'd like to create a new polygon from the unique edges, disregarding the shared ones. The output should be an array of (merged) polygons with unique edges. The closest algorithms I can find calculate a convex hull, which is close to what I'm trying to achieve but not quite.
Computing the convex hull of polygons with shared edges does not work, because by definition the result is a convex polygon. While in your case, the result of merging multiple convex polygons with shared edges may not be convex anymore.
I would propose the following approach (it's not trivial, I don't know whether it can be done in a simpler way):
Change the representation of the polygons to arrays of vertex indices (this simplifies some of the later steps)
Traverse all polygons and append all their vertices to a large array of vertices. While iterating over the vertices of a polygon and appending them to the large array, generate a small array of corresponding vertex indices (the new polygon representation). A polygon is now an array of vertex indices referring to the large array of vertices (used by all the polygons).
Identify shared vertices
Maintain a map from vertex index to counter (a vertex index is the index of a vertex in the large array of vertices created in 1.). This will keep track of how many polygons a vertex belongs to and allow to identify shared vertices.
Traverse all polygons and their vertex indices and for each vertex index you have, insert it in this map or increment the counter if it is already in the map.
Identify shared edges (and keep track of which polygons they belong to)
Maintain a map from (i, j) (with i < j) from pairs of vertex indices to (counter, polygon index1, polygon index2).
The constraint i < j make sure edges with different orientation are not counted twice (this also means when querying the map you have to make sure that i < j in your query pair).
The counter counts the number of polygons an edge belongs to. The problem is in 2D and I assume the data is clean (polygons are not overlapping each other), so the value of this counter should be either 1 or 2.
The polygon index1 and polygon index2 are referring to the indices of polygons the edge may belong to in the array of polygons (these indices can be initialized to -1).
Traverse all the polygons and their edges (iterate over the list of vertex indices without forgetting the final edge closing the loop). For each edge (i, j) with i < j, update the map by either creating the entry in the map, or updating its counter and polygon indices.
Generate the new array of polygons
Iterate over all the polygons from the initial array. For each polygon, a new polygon may be generated:
Find a vertex index in the polygon that is not shared (using the map from 2.). If there is no such vertex index, discard the polygon and move to the next non-discarded polygon.
Output the (non-shared) vertex index. Starting from this vertex index, iterate over all the edges of the polygon:
If the edge is not shared, output the destination vertex index and move to the next edge.
If the edge is shared, you need to find out which polygon it is shared with (to continue iterating over the edges of the new polygon). Use the edge map from 3. to do this. Locate the edge in the other polygon and continue iterating over the edges of this other polygon (in the opposite direction w.r.t. to the shared edge).
This iteration over the edges of the new polygon should eventually loop back to the starting (non-shared) vertex index, which means the new polygon is closed and can be appended to the new array of polygons.
While iterating over the edges of different polygons to generate the final merged polygon, the traversed polygons should be tracked, so that they can be discarded in the outer loop.
Convert the representation of the new polygons back to array of vertices (if needed)
Simply iterate over the new polygons and their array of vertex indices. Fetch the corresponding vertices from the array of vertices created in 1. and append it a new array of vertices for this polygon.
I dunno - make a list of all vertices and sort it by x and y values, then go through and discard the duplicates?
maybe GPC - General Polygon Clipper library can help. It has tons of features and algorithms. There is a Java port by Daniel Bridenbecker. I've used it to calculate polygon intersections and unions...
Related
I have n geometric shapes defined in GeoJson, I would like to calculate the intersection which involves maximum number of shapes.
I have the following constraints;
none of the shapes may intersects (no intersection between any of shapes, 0-participant intersection)
all shapes may intersects (there is an intersection that is in all shapes, n-participant intersection)
there might be more than one intersection with k participant (shape A B C intersects, shape D E F intersects, there are 2 3-participant intersection, doesn't need to find both, return when first 3-participant found)
So, as a starting point, I though I could do that by using brute force (trying to intersects n, n-1, n-2 combination of given shapes) but it's time complexity will be O(n!). I'm wondering that if the algorithm could be optimized?
EDIT:
Well, I forgot the tell about data types. I'm using Esri/geometry library for shapes. Specifically, Polygon class instances.
This problem feels like you can construct hard cases that cannot be solved efficiently, specifically if the shapes are not convex. Here are two ideas that you could try:
1. Iterative Intersection
Keep a list L of (disjoint) polygons with counts that is empty in the beginning. Now iterate through your given polygons P. For each polygon p from P intersect it with all polygons l from L. If there is an intersection between p and l then remove l from L and
add set_intersection(l, p) with previous count of l +1
add set_minus(l, p) with `previous count of l'
remember set_minus(p, l) and proceed to the next entry of L
when you are through all elements of L then add the remaining part of p to L with count 1.
Eventually you will have a list of disjoint polygons with counts that is equvalent to the number of participant polygons.
2. Space Decomposition
Build a bounding box around all polygons. Then iteratively split that space (similar to a KD-Tree). For each half (rectangle), compute the number of polygons from P intersecting that rectangle. Proceed best-first (always evaluate the rectangle that has the highest count). When you are at a certain level of the KD-Tree then stop and evaluate by brute-force or Iterative Intersection.
Both methods will benefit from a filter using minimum bounding rectangles around the polygons.
A list of unprocessed (non-empty) intersections together with the polygon indices from which the intersection was created is maintained. Initially it is filled with the single polygons. Always the intersection from most polygons and least maximal index of involved polygons is taken out and intersected with all polygons with higher indices (to avoid looking at the same subset of polygons again and again). This allows an efficient pruning:
if the number of polygons involved in the currently processed intersection and the remaining indices do not surpass the highest number of polygons to have a non-empty intersection, we do not need to pursue this intersection any longer.
Here is the algorithm in Python-like notation:
def findIntersectionFromMostMembers(polygons):
unprocessedIntersections = [(polygon, {i}) for i, polygon in enumerate(polygons)]
unprocessedIntersections.reverse() # make polygon_0 the last element
intersectionFromMostMembers, indicesMost = (polygons[0], {0})
while len(unprocessedIntersections) > 0:
# last element has most involved polygons and least maximal polygon index
# -> highest chance of being extended to best intersection
intersection, indices = unprocessedIntersections.pop() # take out unprocessed intersection from most polygons
if len(indices) + n - max(indices) - 1 <= len(indicesMost):
continue # pruning 1: this intersection cannot beat best found solution so far
for i in range(max(indices)+1, n): # pruning 2: only look at polyong with higher indices
intersection1 = intersection.intersect(polygons[i])
if not intersection1.isEmpty(): # pruning 3: empty intersections do not need to be considered any further
unprocessedIntersections.insertSorted(intersection1, indices.union({i}), key = lambda(t: len(t[1]), -max(t[1])))
if len(indices)+1 > len(indicesMost):
intersectionFromMostMembers, indicesMost = (intersection1, indices.union({i}))
return intersectionFromMostMembers, indicesMost
The performance highly depends on how many polygons in average do have an area in common. The fewer (<< n) polygons have areas in common, the more effective pruning 3 is. The more polygons have areas in common, the more effective pruning 1 is. Pruning 2 makes sure that no subset of polygons is considered twice. The worst scenario seems to be when a constant fraction of n (e.g. n/2) polygons have some area in common. Up to n=40 this algorithm terminates in reasonable time (in a few seconds or at most in a few minutes). If the non-empty intersection from most polygons involves only a few (any constant << n) polygons, much bigger sets of polygons can be processed in reasonable time.
What are the different types of Graph ADT's that can you implement in java, can you provide a link or list? For example, a queue in java can be further specified into a Linked List.
Adjacency List Structure
"Vertices are stored as records or objects, and every vertex stores a list of adjacent vertices. This data structure allows the storage of additional data on the vertices. Additional data can be stored if edges are also stored as objects, in which case each vertex stores its incident edges and each edge stores its incident vertices."
Adjacency Matrix
"A two-dimensional matrix, in which the rows represent source vertices and columns represent destination vertices. Data on edges and vertices must be stored externally. Only the cost for one edge can be stored between each pair of vertices."
Incidence Matrix
"A two-dimensional Boolean matrix, in which the rows represent the vertices and columns represent the edges. The entries indicate whether the vertex at a row is incident to the edge at a column."
Source: https://en.wikipedia.org/wiki/Graph_(abstract_data_type)
I have a problem in Java.I must create a graph. For input I have a char[][].
The graph has this proprerty:
Give an char's matrix and we suppose that this is in position [i][j].
Then I have a Node in the graph that represent this position.
The node that represent the position [i][j] has an edge with the node that represent(if possible):
the position'[i+1][j]'
the position '[i-1][j]'
the position'[i][j+1]'
The position'[i][j-1]'
But I have a problem in through the matrix and create an edge with this property. I think so I use a recursive algorithm. It's correct?
Thank to all
i need a method to calculate outdegree of each vertex of DAG to check whether it is leaf or not.i m using java with boolean adjancency matrix representation
Sum along the row.
In an adjacency matrix, there is a 1 at position (i, j) if there is an edge from vertex i to vertex j. Therefore, all the outgoing edges of vertex i are in row i. A sum of row i therefore gives you the outdegree of vertex i.
For a transposed adjacency matrix, sum along the columns.
Like David says, if you're only interested in whether the outdegree is zero or not you can save work by stopping the summation if you find a 1.
I have a n*m matrix with integer value at each node and its an undirected graph. I want to build an adjacency list for it. How do I do that? Any help is much appreciated.
Here is a simple implementation for creating adjacency list.According to the problem:
There will be n linked lists each of variable size.
First Initialize an ArrayList of linked lists of integers:
ArrayList<LinkedList<Integer>> adj_list = new ArrayList<LinkedList<Integer>>();
Then simply add linked lists by repeating following code:
adj_list.add(new LinkedList<Integer>());
If you are using it to represent graph,then no of linked lists=no of vertices.So you must repeat the above line n(no of vertices) times.
Say now you want to add numbers 3,4,5 to your first linked lists.Do the following:
adj_list.get(0).add(3);
adj_list.get(0).add(4);
adj_list.get(0).add(5);
It simply means there is an edge in your graph from vertex 0 to 3,4,5.
First your description seems to be of an adjacency matrix except you're saying m by n. Adjacency matrices are always square, so we must assume m==n. The matrix elements are the edge weights.
An adjacency list representation of a graph is (usually) an array adj of sets of pairs. The set adj[i] contains pair <j, w> iff there is a directed edge i--w-->j, i.e. from vertex i to j with weight w in the represented graph.
With this definition, it's clear you must start with n empty adjacency sets adj[i] and then iterate over the matrix elements m[i][j] = w. For each of these add <j, w> to adj[i].
The java code for this is pretty trivial, so I won't write it. The type for a graph represented with adjacency lists is something like ArrayList<HashMap<Integer, Integer>> adjacencies. The pairs <j,w> in adj[i] are mappings j -> w stored in the hash table adjacencies.get(i). The code to create such an adjacency will be adjacencies.get(i).put(j, w).
This method allows you to iterate over the vertices adjacent to i by iterating over keys in the hash table adjacencies.get(i), look up the weight of a given edge i--w-->j with w = adjacencies.get(i).get(j), and so on for all the usual graph operations.