h3.polyfill misses indices for Antarctica geojson - h3

Could you please help me understand the issue with H3 geospatial indexing?
import h3
geo_antarctic = {"type":"Polygon","coordinates":[[[-170.63764683701507,-85.05113000000047],[-170.63764683701507,-77.89462449499929],[-63.82520589349025,-66.39564184408599],[-49.69216225292467,-77.30460454007437],[-35.16653406678777,-77.89462449499929],[-9.255954059083527,-70.29658532122083],[40.994867774038596,-68.50197979740217],[89.56411960844528,-64.94027568501143],[163.48124599227498,-67.77106116580279],[172.90327508598565,-72.42721956336818],[165.83675326570284,-77.7288586062699],[178.18462781512582,-77.47601087207454],[178.57721236069702,-85.0171471646522],[-178.63764683701507,-85.05113000000047]]]}
idx = h3.polyfill(geo_antarctic, 3)
I'm expecting to get indices like these ones, which are located inside of the geojson polygon above:
83ef9efffffffff
83eea4fffffffff
83f125fffffffff
83f2a4fffffffff
But instead, h3.polyfill returns indices that are “flipped” by 90 degrees like these:
836682fffffffff
830e59fffffffff
83b294fffffffff
836733fffffffff
838f0bfffffffff
830372fffffffff
All works fine for other geojsons that don't span Antarctica..
I’m using Python 3.10.7 and H3 3.7.4.
I would appreciate any hints.
Upd.
I used geo_json_conformant=True parameter and it flipped indices back. But it seems not all resolution 3 indices were generated and my expected indices are not in the list. On the image generated indices are in blue and expected are in red.
Upd 2
Following the suggestion from #nrabinowitz, I triangulated the original polygon from Pole and then polyfilled resulting "slices". Works perfectly fine, all missing indices are in place.
result
import h3
import geojson
geoj = {"type":"Polygon","coordinates":[[[-178.34111242523068,-85.0207089708011],[-178.69267492523034,-77.91567194747755],[-162.52079992523068,-78.4905544838336],[-140.02079992523,-73.8248242864237],[-126.66142492523065,-73.12494935304983],[-103.10673742523004,-74.59011176731619],[-103.45829992523063,-71.07406105104535],[-83.06767492523001,-73.52840349816283],[-61.97392492523001,-64.32087770911836],[-57.052049925230655,-62.43108077917767],[-59.86454992522999,-74.77584672076205],[-39.12236242523063,-77.8418507294947],[-12.052049925230301,-70.61261893331015],[35.05732507477002,-68.52824009786191],[53.33857507476973,-65.51296841598038],[76.54170007476968,-68.39918525054024],[93.06513757477003,-64.77413134111099],[143.69013757477003,-66.08937000336596],[173.22138757477006,-70.72898413027124],[167.94795007477003,-76.26869800825351],[177.79170007476975,-77.23507678015689],[178.60169170931843,-84.94715491814792],[-178.34111242523068,-85.0207089708011]]]}
polygon_coords = geoj["coordinates"][0]
pole_coord = (0.0, -89.999)
all_indexes = set()
for i in range(len(polygon_coords)-1):
polygon = geojson.Polygon([[pole_coord, tuple(polygon_coords[i]), tuple(polygon_coords[i+1])]])
idxes = h3.polyfill(dict(polygon), 5, geo_json_conformant=True)
all_indexes.update(idxes)
with open(f"./absent_polr.csv", "w") as out:
out.write("h3_idx\r\n")
out.write("\r\n".join(all_indexes))

H3 uses a Cartesian model for polygons used in polyfill, not a spherical model, so poles are slightly challenging. The other issue is that we assume the smaller polygon when some of the arcs are greater than 180 degrees, which is frequently the case very near the poles.
See the suggested workaround in this related issue:
I think the best workaround here is to slice up polygons that contain a pole. I think the simplest version of this, which ought to work, is to make triangles, one for each pair of vertexes, with the third vertex being the pole itself.
The other participant in that discussion glossed this as "slicing the polygon up like a pizza," which I thought was very descriptive.
There's a demo of this approach in this Observable notebook.

Related

How to overly depth data on 2D image?

All of this is done in Matlab. I have a 2D RGB image, with some depth data for key vertexes. That is, I have three vectors (m x 1): X, Y, Z. Together, [X(i), Y(i)] specifies the point in the image with depth Z(i).
The crux of my problem is this:
I would like to plot the image "warped" with the depth information. But, each time I keep calling functions like 'mesh(X,Y,Z,RGBImage)' and 'surf', I get weird errors like "Z need to be matrix not vector". Also, I haven't even been able to implement the 'warp' function, as I am not sure how to translate my data into a usable format.
Any help would be really appreciated.
EDIT: I finally got it to work the way I would like. The only thing that needed to be changed, that was not answered, was to include the line
s = surf(Xmat,Ymat,Zmat, T1, 'edgecolor', 'none', 'FaceColor', ...
'texturemap');
Where
T1 = rgb2gray(OrignialRGBImage);. Much thanks!
I don't have access to MATLAB right now, so I am giving the outline of the solution.
First, create two matrices using meshgrid: [Xmat,Ymat] = meshgrid(1:imgCols,1:imgRows);. Now, you can find every row of [X,Y] at [Xmat(i,j),Ymat(i,j)] for some (i,j). In the next step, create Zmat such that Zmat(i,j) is the correct depth value for [Ymat(i,j),Xmat(i,j)]. You should be able to do this as follows:
Zmat = zeros(imgRows,imgCols);
for i=1:size(X,1)
Zmat(Y(i),X(i))=Z(i);
end
Now you can do surf with Xmat,Ymat,Zmat as follows. Then overlay image as texture.
s = surf(Xmat,Ymat,Zmat);
set(s, 'faceColor', 'texture','edgecolor', 'none','cdata', subimage); %not tested,
%see if it works
Overlaying part taken from here.
If the above part doesn't work, then you can overlay Zmat in the heatmap style, see this question.

How to search geo-point with polygon across dateline?

How to search geo-point with polygon across dateline(International Date Line,or 180 and -180 longitude) use java api?
Hello everyone:
I use ElasticSearch 2.1 and its java api, I want to search documents with polygon geo filter(the polygon is rectangle usually),but when the polygon across the dateline (International Date Line,or 180 and -180 longitude),it go wrong. For example:
My code:
BoolQueryBuilder mustQuery = QueryBuilders.boolQuery().must(QueryBuilders.matchAllQuery());
......
GeoPolygonQueryBuilder qb = QueryBuilders.geoPolygonQuery("description.device_location.es_geo");
qb.addPoint(0,100);//the left down vertex of the polygon(rectangle),patams is (lat , lon)
qb.addPoint(0,-170);//right down
qb.addPoint(80,-170);//right up
qb.addPoint(80,100);//left up
qb.addPoint(0,100);//left down,same to the first vertex
mustQuery = mustQuery.must(qb);
SearchResponse searchResponse = EsClient.getClient().prepareSearch(Config.indexName)
.setTypes(Config.typeName)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(mustQuery)
.setFrom(0).setSize(size).setExplain(true)
.execute()
.actionGet();
diagrammatic sketch:
I want search in A area,but ES search in B area in fact
As the picture above, I provide ES points [0,100],[0,-170],[80,-170],[80,100],[0,100] to describe A area,and I want docs in A area, A area across dteline.
But according to the result, there is longitude 82,98,-121 etc., but no docs between [100,180]and between [-180,-170],so I suppose ES search in B area in fact(It analyze the polygon in error).
I search for the solution , on the ES's website, I found some words about this problem:
(form www.elastic.co/guide/en/elasticsearch/reference/2.1/geo-shape.html)
IMPORTANT NOTE: GeoJSON does not mandate a specific order for vertices thus ambiguous polygons around the dateline and poles are possible. To alleviate ambiguity the Open Geospatial Consortium (OGC) Simple Feature Access specification defines the following vertex ordering:
Outer Ring - Counterclockwise
Inner Ring(s) / Holes - Clockwise
For polygons that do not cross the dateline, vertex order will not matter in Elasticsearch. For polygons that do cross the dateline, Elasticsearch requires vertex ordering to comply with the OGC specification. Otherwise, an unintended polygon may be created and unexpected query/filter results will be returned.
The following provides an example of an ambiguous polygon. Elasticsearch will apply OGC standards to eliminate ambiguity resulting in a polygon that crosses the dateline.
But this is for geo-Shape datatype, and my docs' location is geo-point, I can't found similar words on geo-points's webpage(www.elastic.co/guide/en/elasticsearch/reference/2.1/geo-point.html).
I hava try some way:
1. Counterclockwise and clockwise vertex order;
2. start from every vertex of rectangle;
3. replace -170 lon with 190 lon;
but these ways all don't work.
Does anyone know how to search with a polygon across dateline ?
Thanks!
(sorry, I'm a Chinese developer and I can't speak English well, if there is solecism,please give me advice or comments, thank you.)
Here is the translated text of Chinese.Chinese characters couldn't be insert to question direct.
I'm the asker, and I have an answer already.
I have ask this question at https://discuss.elastic.co/t/search-geo-point-with-polygon-across-dateline/39103/3 ,and get answer there.
Before,I have ever think if there isn't perfect solution,I can split the polygon into 2 by dateline.I have know ES don't suport to search geo-point with polygon across dateline now:
At the moment geo_polygon queries for geo_point types do not work
across the dateline. You will either have to:
manually split the polygon into 2 and combine them using a boolean AND;
reindex the geo_points as geo_shapes (recommend setting points_only = true) and using a geo_shape (www.elastic.co/guide/en/elasticsearch/reference/2.1/geo-shape.html) query.
But if you know the polygon is a
rectangle, you can use a geo_bounding_box (www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-bounding-box-query.html) query which will properly
handle the dateline (as in your example).
Thanks for #nknize and #medcl1 (at discuss.elastic.co)!

Can I turn a D3 map projection clockwise around its centre point?

How can I turn my map - if I can - clockwise by about 15-20 degrees, so that is looks like the map of the middle east I would see in an atlas?
Intuitively, .rotate looks like it should do it, but I've tried inserting different values and it just 'uncentres' the map.
The important bit of D3 code, I believe, is:
var projection = d3.geo.albers()
.center([49.7, 27.4])
.rotate([0, 0, 0])
.parallels([12.6, 40])
.scale(800)
.translate([width / 2, height / 2]);
(1)
Thanks.
(2)
I'm trying to replicate a map the looks like this (2) - just because it is what people are familiar with seeing in a regular atlas.
Not knowing what you have tried thus far using projection.rotate() I still think this method will give the desired result. For example, a clockwise rotation by 20 degrees around LAT=49.7N, LON=27.4E as specified in your example could be done by:
projection.rotate([-49.7,-27.4,-20])
I set up a Plunk demonstrating the outcome.
Update
If you are not bound to using the Albers projection, there might be other options giving results which better fit your needs of
what people are familiar with seeing in a regular atlas.
I looked it up in three atlases where the Arabian Peninsula was depicted using the equirectangular projection which looks like your desired output:
var projection = d3.geo.equirectangular()
.rotate([-49.7,-27.4])
You just center on LAT=49.7N, LON=27.4E by applying .rotate([-49.7,-27.4]) without the need to further roll the projection, i.e. you won't have the third element in the array supplied to rotate(). See my updated Plunk. To me this looks like what I would expect it look when seeing it in an atlas.

Field of view/ convexity map

On a shape from a logical image, I am trying to extract the field of view from any point inside the shape on matlab :
I tried something involving to test each line going through the point but it is really really long.(I hope to do it for each points of the shape or at least each point of it's contour wich is quite a few times)
I think a faster method would be working iteratively by the expansion of a disk from the considered point but I am not sure how to do it.
How can I find this field of view in an efficient way?
Any ideas or solution would be appreciated, thanks.
Here is a possible approach (the principle behind the function I wrote, available on Matlab Central):
I created this test image and an arbitrary point of view:
testscene=zeros(500);
testscene(80:120,80:120)=1;
testscene(200:250,400:450)=1;
testscene(380:450,200:270)=1;
viewpoint=[250, 300];
imsize=size(testscene); % checks the size of the image
It looks like this (the circle marks the view point I chose):
The next line computes the longest distance to the edge of the image from the viewpoint:
maxdist=max([norm(viewpoint), norm(viewpoint-[1 imsize(2)]), norm(viewpoint-[imsize(1) 1]), norm(viewpoint-imsize)]);
angles=1:360; % use smaller increment to increase resolution
Then generate a set of points uniformly distributed around the viewpoint.:
endpoints=bsxfun(#plus, maxdist*[cosd(angles)' sind(angles)'], viewpoint);
for k=1:numel(angles)
[CX,CY,C] = improfile(testscene,[viewpoint(1), endpoints(k,1)],[viewpoint(2), endpoints(k,2)]);
idx=find(C);
intersec(k,:)=[CX(idx(1)), CY(idx(1))];
end
What this does is drawing lines from the view point to each directions specified in the array angles and look for the position of the intersection with an obstacle or the edge of the image.
This should help visualizing the process:
Finally, let's use the built-in roipoly function to create a binary mask from a set of coordinates:
FieldofView = roipoly(testscene,intersec(:,1),intersec(:,2));
Here is how it looks like (obstacles in white, visible field in gray, viewpoint in red):

Why do I get an incorrect Voronoi diagram?

I'm trying to generate a Voronoi diagram for a set of latitude/longitude points.
var points = [["-87.63374","41.878723"],["-87.680622","41.829353"],["-87.631739","41.8768"],["-87.626149","41.884431"]] ;
var boundingRegion = d3.geom.polygon([
[-88, 41.7],
[-88, 42.3],
[-87.5, 42.3],
[-87.5, 41.7]
]);
var voronoi = d3.geom.voronoi(points).map(function(cell) {
return boundingRegion.clip(cell);
});
document.write("<pre>"+JSON.stringify(voronoi, null, ' ')+"</pre>");​
I have a JSFiddle for that basic example here:
http://jsfiddle.net/ZzjpC/2/
I'm putting in 4 points and clipping them by using a simple rectangle.
The points are such that I should see at least one clipped vertex for each of the resulting Voronoi regions... the first one alone does not meet that.
When you plot them on a Google Map, the polygons intersect and are in total disarray.
If you look at http://jsfiddle.net/ZzjpC/3/, where the last point has been removed, everything looks fine.
So here's my question: is there something wrong with my set of points that is causing the Voronoi diagram generation to fail? Or is this a D3 bug and I should be telling those folks?
Turns out the problem was with the fact that my Voronoi sites (points) were arrays of strings instead of floats was the cause of the issue. My guess is that there was an addition taking place somewhere that was executed as a string concatenation instead and that broke things.
Converting the points to floats instead of strings fixed the problem.

Resources