geometry-api-java
geometry-api-java copied to clipboard
cut operator over dateline
Hi, I'm trying to migrate my code from JTS to your library to better deal with the poles and the dateline. What I need is to clip everything that get too close to the poles to keep the map clean, and to cut a polygon in a multipolygon when it cross the dateline. As for the clipping I think I've managed, but the cut does not seems to work. Here is my code:
Geometry polygon = OperatorImportFromWkt.local().execute(WktImportFlags.wktImportDefaults, Geometry.Type.Polygon, footprint, null);
SpatialReference wgs84 = SpatialReference.create(4326);
// clip to exlude parts outside of map
Envelope2D envelope = new Envelope2D(-180, -85, 180, 85);
polygon = OperatorClip.local().execute(polygon, envelope, wgs84, null);
// cut over dateline
Polyline dateline = new Polyline(new Point(180, 89.9), new Point(180, -89.9));
GeometryCursor cursor = OperatorCut.local().execute(true, polygon, dateline, wgs84, null);
Polygon split = (Polygon) cursor.next();
anyway split is always null, which according to the documentation, means no cut.
The data I'm doing this with are the following:
// this is a satellite orbit with its corresponding swath, it goes from north pole to north pole going around the globe
String footprint = "POLYGON ((49.5859 89.3816,115.712 89.8297,-163.024 89.4178,-154.723 88.8588,-151.886 88.2905,-150.465 87.7199,-149.612 87.1483,-149.043 86.5762,-148.637 86.0039,-148.333 85.4314,-148.096 84.8587,-147.907 84.286,-147.752 83.7132,-147.623 83.1403,-147.513 82.5674,-147.42 81.9945,-147.338 81.4215,-147.267 80.8485,-147.204 80.2755,-147.148 79.7024,-147.098 79.1293,-147.053 78.5561,-147.012 77.983,-146.975 77.4098,-146.941 76.8366,-146.909 76.2633,-146.881 75.69,-146.854 75.1167,-146.829 74.5433,-146.806 73.97,-146.785 73.3965,-146.765 72.8231,-146.746 72.2496,-146.742 72.1062,-140.744 72.0312,-131.759 71.5596,-123.385 70.6869,-115.843 69.464,-109.209 67.9488,-103.452 66.1973,-98.4598 64.2462,-94.178 62.1563,-90.4715 59.9483,-87.2451 57.6464,-84.4184 55.269,-81.9237 52.8306,-79.7063 50.3423,-77.7213 47.8129,-75.9322 45.2493,-74.3094 42.657,-72.8283 40.0405,-71.4689 37.4035,-70.2145 34.7489,-69.0513 32.0792,-67.9676 29.3965,-66.9538 26.7026,-66.0014 23.999,-65.1035 21.287,-64.254 18.5678,-63.4478 15.8424,-62.6804 13.1117,-61.9478 10.3765,-61.2468 7.63755,-60.5743 4.89547,-59.9278 2.15088,-59.305 -0.595683,-58.704 -3.34371,-58.1228 -6.09275,-57.5601 -8.84237,-57.0144 -11.5922,-56.4845 -14.3419,-55.9695 -17.0911,-55.4682 -19.8396,-54.9801 -22.587,-54.5043 -25.3332,-54.0404 -28.0779,-53.5879 -30.821,-53.1466 -33.5623,-52.7161 -36.3017,-52.2966 -39.0391,-51.8881 -41.7744,-51.491 -44.5075,-51.1058 -47.2385,-50.7336 -49.9673,-50.3755 -52.6939,-50.0336 -55.4184,-49.7104 -58.1407,-49.4099 -60.8611,-49.1377 -63.5794,-48.9022 -66.2958,-48.7161 -69.0103,-48.6002 -71.723,-48.5896 -74.4337,-48.7494 -77.1422,-49.2144 -79.8479,-50.3145 -82.5488,-53.1225 -85.2381,-64.0671 -87.8737,-177.529 -88.9745,149.079 -86.4983,144.207 -83.8225,142.533 -81.1255,141.831 -78.4217,141.551 -75.7142,141.492 -73.0044,141.564 -70.2925,141.72 -67.5787,141.934 -64.863,142.191 -62.1454,142.479 -59.4258,142.792 -56.7042,143.125 -53.9804,143.476 -51.2546,143.842 -48.5265,144.221 -45.7963,144.612 -43.0638,145.016 -40.3292,145.43 -37.5925,145.855 -34.8537,146.292 -32.1129,146.739 -29.3702,147.197 -26.6258,147.667 -23.8799,148.15 -21.1326,148.645 -18.3841,149.153 -15.6348,149.676 -12.8849,150.214 -10.1346,150.769 -7.38438,151.341 -4.63455,151.933 -1.88552,152.545 0.862255,153.181 3.6083,153.841 6.3521,154.528 9.09307,155.246 11.8306,155.996 14.5639,156.784 17.2924,157.613 20.015,158.487 22.7309,159.414 25.439,160.398 28.1381,161.448 30.8266,162.573 33.503,163.783 36.1654,165.092 38.8113,166.514 41.4381,168.068 44.0425,169.776 46.6205,171.666 49.1669,173.77 51.6756,176.13 54.1388,178.795 56.5464,-178.174 58.8857,-174.702 61.1403,-170.701 63.2888,-166.068 65.3035,-160.695 67.1495,-154.483 68.7826,-147.366 70.1504,-139.366 71.1952,-130.632 71.861,-121.463 72.1056,-121.467 72.249,-121.485 72.8225,-121.503 73.396,-121.524 73.9694,-121.545 74.5428,-121.569 75.1161,-121.594 75.6894,-121.621 76.2627,-121.651 76.836,-121.683 77.4092,-121.718 77.9824,-121.757 78.5556,-121.799 79.1287,-121.847 79.7018,-121.9 80.2749,-121.959 80.848,-122.026 81.421,-122.103 81.994,-122.192 82.5669,-122.295 83.1399,-122.417 83.7127,-122.564 84.2856,-122.743 84.8583,-122.966 85.431,-123.254 86.0035,-123.637 86.5759,-124.174 87.1481,-124.98 87.7198,-126.323 88.2906,-129.003 88.8592,-136.854 89.4194,140.518 89.8389,74.0012 89.3843,137.051 87.0571,142.22 84.3624,143.773 81.6485,144.363 78.9292,144.559 76.2071,144.553 73.4831,144.432 70.7575,144.236 68.0304,143.99 65.3018,143.708 62.5716,143.398 59.8399,143.067 57.1065,142.717 54.3713,142.353 51.6345,141.976 48.8958,141.587 46.1555,141.186 43.4134,140.776 40.6696,140.355 37.9241,139.924 35.1771,139.483 32.4287,139.031 29.6789,138.569 26.9279,138.096 24.176,137.611 21.4232,137.115 18.6699,136.605 15.9163,136.081 13.1626,135.543 10.4092,134.989 7.65648,134.417 4.90469,133.827 2.15428,133.217 -0.59433,132.585 -3.34066,131.928 -6.0842,131.245 -8.8244,130.532 -11.5607,129.787 -14.2923,129.006 -17.0186,128.186 -19.7387,127.32 -22.4517,126.404 -25.1566,125.432 -27.8522,124.396 -30.5372,123.288 -33.21,122.096 -35.8687,120.81 -38.5112,119.413 -41.1348,117.889 -43.7365,116.215 -46.3125,114.367 -48.8579,112.311 -51.367,110.01 -53.8323,107.414 -56.2445,104.466 -58.5916,101.092 -60.8579,97.2077 -63.0235,92.7126 -65.0624,87.4973 -66.9411,81.457 -68.6178,74.516 -70.0415,66.6715 -71.1551,58.0434 -71.9015,48.9031 -72.2343,39.6483 -72.1306,30.7067 -71.5978,22.4249 -70.671,15.0014 -69.4035,8.49228 -67.8534,2.85427 -66.0755,-2.00681 -64.1165,-6.19983 -62.0142,-9.83095 -59.7982,-12.9938 -57.4917,-15.7672 -55.1124,-18.2171 -52.674,-20.3969 -50.1872,-22.35 -47.6603,-24.1122 -45.1001,-25.7121 -42.5117,-27.1736 -39.8995,-28.5163 -37.2669,-29.7563 -34.6168,-30.9072 -31.9516,-31.9802 -29.2732,-32.985 -26.5834,-33.9295 -23.8837,-34.8206 -21.1752,-35.6643 -18.4591,-36.4657 -15.7364,-37.229 -13.008,-37.9582 -10.2745,-38.6565 -7.53676,-39.3269 -4.79538,-39.9718 -2.05092,-40.5936 0.696075,-41.1941 3.44512,-41.7752 6.19576,-42.3383 8.94758,-42.8849 11.7002,-43.4161 14.4533,-43.9329 17.2065,-44.4364 19.9595,-44.9274 22.7122,-45.4064 25.4641,-45.8742 28.2152,-46.3312 30.9651,-46.7777 33.7139,-47.214 36.4613,-47.6403 39.2071,-48.0564 41.9514,-48.4623 44.694,-48.8574 47.435,-49.2411 50.1741,-49.6124 52.9116,-49.9698 55.6473,-50.3109 58.3813,-50.6327 61.1136,-50.9304 63.8443,-51.197 66.5734,-51.4215 69.3011,-51.5862 72.0272,-51.6604 74.7667,-51.5853 77.4897,-51.2396 80.2104,-50.3127 82.9276,-47.724 85.6357,-35.6305 88.2935,49.5859 89.3816))";
// this is a polygon that goes near the north pole and cross the dateline
String footprint = "POLYGON ((80.0522 83.7357,85.3112 83.7546,90.5581 83.7213,95.7078 83.6365,100.684 83.5023,105.426 83.3217,109.891 83.0982,114.054 82.836,117.907 82.539,121.451 82.2113,124.7 81.8566,127.671 81.4782,130.385 81.0792,132.863 80.6622,135.127 80.2294,137.198 79.783,139.096 79.3245,140.837 78.8555,142.438 78.3773,143.914 77.8909,145.276 77.3974,146.536 76.8974,147.705 76.3917,148.792 75.8809,149.804 75.3655,150.748 74.8461,151.63 74.3229,152.457 73.7964,153.234 73.2669,153.963 72.7346,154.651 72.1998,155.299 71.6627,155.912 71.1235,156.06 70.9884,164.137 71.7139,172.839 72.0764,-178.306 72.038,-169.674 71.6014,-169.569 71.7409,-169.131 72.2983,-168.666 72.8546,-168.171 73.4098,-167.643 73.9637,-167.077 74.5162,-166.472 75.0671,-165.821 75.6162,-165.119 76.1635,-164.361 76.7085,-163.54 77.2511,-162.647 77.7909,-161.673 78.3275,-160.607 78.8606,-159.436 79.3894,-158.143 79.9135,-156.712 80.432,-155.119 80.944,-153.339 81.4482,-151.34 81.9433,-149.083 82.4274,-146.526 82.8984,-143.613 83.3533,-140.285 83.7888,-136.471 84.2005,-132.1 84.5828,-127.101 84.9291,-121.421 85.2317,-115.046 85.4816,-108.023 85.6699,-100.486 85.7882,-92.6582 85.8305,-84.8183 85.7945,-72.3555 88.3373,56.9057 88.7863,76.6766 86.2836,80.0522 83.7357))";
// this is a polygon that wrap the south pole
String footprint = "POLYGON ((2.18368 -70.4477,1.45577 -70.9684,0.688619 -71.4861,-0.120913 -72.0005,-0.976256 -72.5113,-1.88118 -73.0182,-2.83984 -73.5208,-3.85678 -74.0188,-4.937 -74.5116,-6.086 -74.9989,-7.30979 -75.48,-8.61495 -75.9544,-10.0087 -76.4212,-11.4988 -76.8797,-13.0937 -77.3291,-14.8025 -77.7682,-16.6348 -78.196,-18.6008 -78.6112,-20.7109 -79.0124,-22.9756 -79.3979,-25.4052 -79.766,-28.0091 -80.1148,-30.7954 -80.4422,-33.7701 -80.7458,-36.9358 -81.0233,-40.291 -81.2722,-43.829 -81.49,-47.5368 -81.6742,-51.3944 -81.8226,-55.3753 -81.9331,-59.4462 -82.0043,-63.5689 -82.0351,-67.7022 -82.0249,-68.7323 -82.016,-70.8282 -84.5548,-77.4161 -87.1071,-137.182 -89.2345,135.202 -87.492,132.016 -87.5294,118.591 -87.598,105.152 -87.5319,93.0367 -87.3409,82.9272 -87.0494,74.8366 -86.6837,68.4512 -86.2656,63.3987 -85.8108,59.3589 -85.3299,56.0846 -84.8302,53.3929 -84.3167,51.15 -83.7928,49.2572 -83.2609,47.6416 -82.7228,46.2483 -82.1797,45.0354 -81.6326,43.9708 -81.0823,43.0292 -80.5293,42.1908 -79.974,41.4397 -79.4168,40.763 -78.8579,40.1502 -78.2977,39.5927 -77.7363,39.0833 -77.1738,38.616 -76.6104,38.1858 -76.0462,37.7885 -75.4813,37.4202 -74.9157,37.078 -74.3495,36.7592 -73.7828,36.4613 -73.2156,36.1823 -72.648,35.9204 -72.08,27.0691 -72.2504,18.2473 -72.0184,9.82037 -71.3991,2.18368 -70.4477))";
I think I'm missing something. Please help :)
King regards, Fernando
I think I've got it. The polygon when it cross the dateline goes the other way around, so I'm cutting in the only line that is not part of the polygon. This is one of the reasons I want to cut over the dateline :(
Is there a way to tell that it shall close the polygons using the shortest path, not the longest?
Thank you
@fer-marino The clip call makes the polygon to be between -180 and +180. The cut call is made using a line x = 180. It has nothing to cut then.
@stolstov Even not clipping before cutting the problem remains. It does not wrap the polygon on the dateline, so it has nothing to cut
@fer-marino Clip polygon with a rectangles with x range [-540, -180], [-180, 180], [180, 540]. Then move the result of the first clip by +360, the result of the third clip by -360. Then union three polygons together using Operator_union.
@stolstov thank you for your answer, and patience! I will try. Just a quick question: to move a polygon there is an operator I can use (OffsetOperator maybe) or I have to iterate over all the vertex of the polygon and manually modify the x coordinate?
thank you again ;)
@fer-marino Use this:
Transformation2D trans = new Transformation2D();
trans.setShift(-180, 0);
polygon.applyTransformaion(trans);
@stolstov hi again. Sorry but it still does not work. The problem is always the same, the input is parsed in a wrong way, because it closes the polygon going around the map instead of crossing the dateline. This means that clipping or cutting such polygons will always produce an incorrect results.
In my opinion the problem resides in the first line that parse the polygon from wkt. I wonder if there is some option to tell it which one is the interior part of the polygon and which one is the exterior. Otherwise I have to manually manipulate the wkt before parsing it, maybe shifting left or right in case of dateline crossing.
@fer-marino Here is the first polygon you provided. It contains 360 degree jumps. May I ask you, how such polygon was produced?
this polygon is one orbit of sentinel 3a satellite, and represents the footprint of one of its instruments. It is a polar orbiting satellite, so it is a stripe wide 1700 km that goes from north pole to north pole. It is easier to understand on a 3D globe. It is not under my control unfortunately, but I have to show it on a planar map.
@fer-marino I can only suggest an approach to to such polygons that you'd detect jumps over 180 degrees and fix them. That's going to be an infinite polygon on a plane along x axis. However, you don't need to make an infinite polygon. You only need to get a good looking section of it of 360 degree wide and clip out anything outside.
However, the polygon seems to be malformed anyway. I zoomed into a top left section of it, and it contains self-intersection that cannot be explained by the 360 jumps.
@stolstov Can you please have a look at the other two polygons I gave you?