How to identify the hexagons which overlap with a given geofence? - h3

The H3 API reference introduced polyfill, the idea of which is "a point-in-poly operation on every hexagon in a k-ring defined around the given geofence". The questions are:
I don't understand what's the meaning of "k-ring defined around a geofence", is this a "ring" and it center is actually the total geofence?
If the judgement is based on the hexagons' center location, and do an "point in polygon" operation, it's possible that the geofence and a hexagon overlaps, but the hexagon's center is out of the geofence and I can't get it's index using polyfill. So, is there any ways that I can get the 2 kinds of hexagons separately which are totally inside a geofence and the hexagons which are partly overlaps with the geofence?

You can actually ignore the k-ring part of this - it's an implementation detail, and in fact that detail has changed in the latest version of the library. The basic idea in both implementations is that we collect a "test" set of cells that covers the entire polygon, and then do a point-in-poly check based on the center of each cell.
It sounds like what you need are ways to get all fully-contained cells and all intersecting cells. There's an existing feature request for this functionality, and while we'd like to add this we don't have any support for other polyfill modes in the library at present.
It's not too hard to roll this yourself, but it may be slow for large sets. You'd need to have a polygon intersection check for a cell and the polygon - a naive implementation would simply check if any two segments intersect (O(polygonVertices), since the count of cell vertices is effectively constant).
Run polyfill to get the starting set. This includes fully contained and some, but not necessarily all, partially contained cells.
For each cell in the starting set, check if it intersects the polygon
If it does not intersect, it is fully contained, add to the set of contained cells
If it does intersect, add to the set of partially contained cells and also to a temporary queue of "border" cells.
If it is contiguous with the polygon, it's fully contained. Add it to the set of contained cells, and also to the border cell queue.
Now identify partially-contained cells that were not in the initial polyfill set. While cells remain in the border queue, pop the first cell and use kRing(cell, 1) to get its neighbors. For each neighbor:
If the neighbor is in the initial polyfill set, ignore.
If the neighbor does not intersect the polygon, ignore.
If the neighbor intersects the polygon, add to the set of partially contained cells and push onto the border queue.
When the border queue is empty, your two sets (contained and partially contained) are complete.

Related

CGAL arrangements: compute the ordered intersection of a polyline with a grid

Given a general polyline and an orthogonal grid, I would like to compute a simpler polyline whose vertices lie on the grid edges/vertices. This can look like this:
Left: A dense polyline as input, Right: A coarser polyline whose vertices lie on the intersection of the input polyline with the grid edges/vertices
(Sorry about the link to the image, but stack overflow apparently doesn't allow me to embed pictures before getting 10 credit points).
The grid is always orthogonal but its vertices do not necessarily have integer coordinates as some x or y lines might have coordinates defined by a previous geometric intersection computation. The initial curve can be represented as a polyline (though it would be nice to have also bezier curve support), not necessarily x-monotone, and it might intersect the grid also along whole edges.
My first thought was to call CGAL::compute_subcurves(..) with the grid lines and the curve I'm adding. I was hoping to get back a list of polylines, each composed of maximal multiple segments inside a face of the original grid. In practice even if the input is composed of polylines and the output of monotone polylines, I get back a list of separated segments. These include also the grid segments and also the polyline segments, and these are not ordered by "walking on the curve segments" as needed to compute the ordered interesection points. If they would have been ordered, a solution would be to iteratively go over them and check which one intersects the original grid, and then save the points.
Another option I thought of is to start with an arrangement of the grid lines, incrementally add polyline segements and have a notification mechanism notifying me on new edges that are pairwise disjoint in their interior, but in the case an edge of the intersected polylines is an original edge of the grid I won't get a notification and I'll miss it. Incrementally adding segments and checking for collisions also doesn't seem to be straightforward as the arrangement API do_intersect(..) seems to return at most a single point, while a given segment of the input polyline might easily intersect two grid lines next to a corner or even lie entirely on a grid segment.
I'm probably missing some simple solution. Can someone give me a pointer, or some api call that might help here?
Edit: There might have been a confusion. The grid is orthogonal but not necessarily regular and might have coordinates that could not globally scale to integers such as here.
Use Arrangement_with_history_2 (instead of Arrangement_2); see https://doc.cgal.org/latest/Arrangement_on_surface_2/classCGAL_1_1Arrangement__with__history__2.html. After you compute the arrangement, you can use point location to locate the end points of your polylines in the arrangement. Then, for each one, you can easily follow the original curve. If you are concerned with performance, you can try inserting (at least) the grid lines incrementally. Another option is to extend the halfedge records and insert the grid lines and each polyline separately. With the appropriate observer, you can mark the generated halfedges that correspond to a given polyline uniquely. I think you can even save the extra point location, by locating one of the two end points of a polyline before inserting it, and then provide the resulting location to the (incremental) insertion function.

Algorithm for finding triangles within a region

I am working on small project that requires me to quickly find which triangles within a set of triangles is either partially or entirely contained within a given rectangular region. I am interested in optimizing for fast searches - I am not memory limited.
This is not an area I am too familiar with, so all I've been able to do thus far is to poke around on Google for standard algorithms for dealing with this problem. The closest I've gotten to so far is to use two interval trees. This is a bit clumsy, since I have to perform a test for interval overlap between the edges of each triangle and the edges of the rectangular region in both directions x and y.
Can someone point me to any resource where the 'correct' way of dealing with this problem is?
Thanks!
Edit: I forgot to mention that the rectangular regions I am currently using are parallel to the coordinate axes x and y. For the time being, I am happy with any solution that exploits this constraint. Generally, though, a solution with completely arbitrary rectangles would be great to know about.
You can use an AABBTree (AABB stands for Axis Aligned Bounding Box tree), the
idea is to enclose each triangle in its axis aligned bounding box, then build a tree that has the initial triangles as leafs, and where upper nodes have a bounding box that is the union of the bounding boxes of its children. Then when searching which triangles have a non-empty intersection with "something", you check whether the "something" has an intersection with the bounding box of a node, and go down the tree to test its children when it's the case (recursive function).
You can find efficient implementations of AABBTrees in:
CGAL: http://doc.cgal.org/latest/AABB_tree/
the GEOGRAM library that I am writing: http://alice.loria.fr/software/geogram/doc/html/classGEO_1_1MeshFacetsAABB.html
OpCode: http://www.codercorner.com/Opcode.htm
Assuming the rectangle is axis aligned, I'd do this:
Compare the bounding box of a triangle to the region. If it is inside, the triangle is inside. If there is no overlap at all, it's not. Use an interval tree for each dimension for this step if you need to check the same set of triangles with different regions.
We have checked the two simple cases in step one, so we know the region and bounding box overlap. Check if any of the points of the triangle is inside the rectangle. If so, the triangle is inside.
Check the four sides of the rectangle with the three sides of the triangle for line segment intersections
If no preprocessing of the set of triangles is allowed, there is nothing better you can do than comparing exhaustively every triangle to the window.
To solve the triangle/rectangle overlap problem easily (or just to reason about it), you can form the Minkowski sum of the two polygons, to turn the problem in a "point-in-convex-polygon" instance.
Of course, an initial axis-aligned bounding box test is welcome.
If your window is a rotated rectangle, you can "unrotate" the whole scene to make the window axis-aligned and revert to the first problem.

Efficiently filling empty cells in 3D matrix

I have a 3D "cubical" matrix, with some cells filled and others empty. A closed region enclosed by filled cells represents a hollow shape. For example, the matrix could have cells filled in such a way that together they form the surface of a hollow sphere. Now, I want an efficient way to fill the interior of this sphere: if a cell C0 is surrounded in all directions by filled cells (filled cell in any direction need not be an immediate neighbor of C0), then fill C0.
A naive way would be the following :-
For each cell, scan in the +X, -X, +Y, -Y, +Z, -Z direction, and see
if you encounter a filled cell in each and every direction.
If a filled cell is encountered in each and every direction, then fill this
cell (as it is part of the interior of some shape).
If you reach the end of grid even in one direction without encountering any filled
cell, then the cell under consideration is not interior to any shape,
and should remain unfilled.
The complexity of above approach is O(n^4), where dimension of 3D grid is n*n*n.
An optimization could be to as follows :-
If for an unfilled cell C[x][y][z], we encountered one filled cell
each in all the 6 directions, then not only C[x][y][z] needs to
be filled, it is also guaranteed that all the cells which we scanned
just now (i.e. {in +X direction, all cells C[x][y][z], C[x+1][y][z],
C[x+2][y][z], ..., till the first filled cell}, similarly for -X, +Y,
-Y, +Z, -Z direction) must be part of the interior of some shape, and hence must be filled.
Another could be as follows :-
If for an unfilled cell C[x][y][z], we DO NOT encounter any filled
cell in, say, +X direction, then not only will C[x][y][z] remain
unfilled, it is also guaranteed that all the cells which we scanned
just now (i.e. in +X direction, all cells C[x][y][z], C[x+1][y][z],
C[x+2][y][z], ..., till the end of grid) must be part of the exterior
and hence, must remain unfilled.
Can someone suggest a more efficient approach to this problem? Even simple optimizations like above, which might not reduce the order of time complexity, are welcome.
You are dealing with 3D Flood Fill. See detailed Wikipedia article http://en.m.wikipedia.org/wiki/Flood_fill
Ok, as this is a closed hollow shapes, we can simply use a BFS or DFS to solve the problem.
BFS:
Starting with an empty queue, add to the queue any cell that lies inside the hollow shape. From the top of the queue, pop out one cell, fill this cell and check 6 other neighbors of this cell, if this neighbor is not filled, add it to the queue, else just ignore this cell. Continue this process until the queue is empty.
The remaining problem is to find a cell that located inside the hollow shape, one trick is the you need to find the cell located at the corner of the shape, which has at least three filled neighbors.
Time complexity is O(number of needed to filled cell * 6 direction need to check)
Tip to move to 6 direction:
int[] x = {0,0,0,0,1,-1};
int[] y = {0,0,1,-1,0,0};
int[] z = {1,-1,0,0,0,0};
Point p = // point in space with three dimension x,y,z
for(int i = 0; i < 6; i++){
int a = p.x + x[i];
int b = p.y + y[i];
int c = p.z + z[i];
}
For each cell, scan in the +X, -X, +Y, -Y, +Z, -Z direction, and see if you encounter a filled cell in each and every direction.
If a filled cell is encountered in each and every direction, then fill this cell (as it is part of the interior of some shape).
The above statement is incorrect unless you are only dealing with convex hulls. The image below shows that the point in question is not enclosed in the blue shape but it will still intersect in all (x,y,z) directions.
Instead, to handle the general case of finding hollowed shapes, you can add all cells to a Set. Then start at a boundary cell. The cell at the boundary is part of a hollowed shape if it is filled, otherwise it is part of a background (non-filled) shape.
Then, similar to #Pham Trung's answer, you can traverse outward in all directions until you have traversed all cells that are within the shape, ignoring the colored cells at the boundaries. Choose another cell at the boundary of the previous shape and start the process over until all cells are traversed.
In the end you will have each cell labeled as either part of a hollow shape or the background.
Just for completeness, two more. YMMV depending on a lot of factors.
1. Find the surface
If you are dealing with a large number of voxels, one optimisation possibility would be to find the border surface of the hollow. This can be done as in Pham Trung's answer but only accepting cells which have at least one of their 6 neighbours filled.
After the border surface has been determined, it can be filled line-by-line using 1D fills, as the directions "inside" and "outside" are known.
This method keeps the set size much smaller if you have a large number of voxels (scales as n^2 instead of n^3). Set lookups are usually very fast, but if the set does not fit into RAM, they slow down a lot.
2. Slice to 2D
Another possibility would be to slice the shape into 2D slices and connect the resulting cavities layer-by-layer. Then only two slices need to be kept in memory at the same time.
The principal idea is to give every separate connected 2D region an own identifier and then find its connections to the already known regions in the neighbouring layer. After handling all layers, connected 3D regions remain.
The challenging part is to find the best algorithm to connect the 2D regions in neighbouring layers. It seems that this method is fast with simple shapes (few disconnected regions in the 2D slices) but slow with complex shapes ("wormholes in tree"). Also, a quick algorithm to find a single common point in two sets is needed. (I.e. no full set intersection is required, just the information whether the sets have at least one common point or not.)
Again, if your sets are of reasonable size, the trivial algorithm described by Pham Trung is probably the best choice.

How to detect a click on an edge of a multigraph?

I have written a win32 api-based GUI app which uses GDI+ features such as DrawCurve() and DrawLine().
This app draws lines and curves that represent a multigraph.
The data structure for the edge is simply a struct of five int's. (x1, y1, x2, y2, and id)
If there is only one edge between two vertices, a straight line segment is drawn using DrawLine().
If there are more than one edges, curves are drawn using DrawCurve() -- Here, I spread straight-line edges about the midpoint of two vertices, making them curves. A point some unit pixels apart from it is calculated using the normal line equation. If more edges are added then a pixel two unit pixels apart from the midpoint is selected, then next time 3 unit pixels, and so on.
Now I have two questions on detecting the click on edges.
In finding straight-line edges, to minimize the search time, what should I do?
It's quite simple to check if the pixel clicked is on the line segment but comparing all edges would be inefficient if the number of edges large. It seems possible to do it in O(log n), where n is the number of edges.
EDIT: at this point the edges (class Edge) are stored in std::map that maps edge id (int)'s
to Edge objects and I'm considering declaring another container that maps pixels to edge id's.
I'm considering using binary search trees but what can be the key? Or should I use just a 2D pixel array?
Can I get the array of points used by DrawCurve()? If this is impossible, then I should re-calculate the cardinal spline, get the array of points, and check if the point clicked by the user matches any point in that array.
If you have complex shaped lines you can do as follows:
Create an internal bitmap the size of your graph and fill it with black.
When you render your graph also render to this bitmap the edges you want to have click-able, but, render them with a different color. Store these color values in a table together with the corresponding ID. The important thing here is that the colors are different (unique).
When the graph is clicked, transfer the X and Y co-ordinates to your internal bitmap and read the pixel. If non-black, look up the color value in your table and get the associated ID.
This way do don't need to worry about the shape at all, neither is there a need to use your own curve algorithm and so forth. The cost is extra memory, this will a consideration, but unless it is a huge graph (in which case you can buffer the drawing) it is in most cases not an issue. You can render the internal bitmap in a second pass to have main graphics appear faster (as usual).
Hope this helps!
(tip: you can render the "internal" lines with a wider Pen so it gets more sensitive).

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