From d3b017455b8068c5798566c4d768047cb175024b Mon Sep 17 00:00:00 2001 From: David Fauth Date: Tue, 26 Nov 2024 08:27:44 -0500 Subject: [PATCH] Update to Neo4j 5.25 Updated to Neo4j 5.25 Deprecating com.neo4jh3 in favor of neo4jh3 Added com.neo4jh3.coverage and com.neo4jh3.coverageString --- CHANGELOG.md | 6 + Documentation.md | 59 +- Documentation_525.md | 1811 +++++++++++ README.md | 11 +- pom.xml | 4 +- src/main/java/com/neo4jh3/uber/Neo4jH3.java | 3240 +++++++++++++++++++ src/main/java/com/neo4jh3/uber/Uberh3.java | 803 +++-- src/test/java/com/neo4jh3/Neo4jH3Test.java | 321 +- src/test/java/com/neo4jh3/UberH3Test.java | 519 +++ 9 files changed, 6326 insertions(+), 448 deletions(-) create mode 100644 Documentation_525.md create mode 100644 src/main/java/com/neo4jh3/uber/Neo4jH3.java mode change 100755 => 100644 src/main/java/com/neo4jh3/uber/Uberh3.java create mode 100644 src/test/java/com/neo4jh3/UberH3Test.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d4da2..2630610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# CHANGELOG - 5.25.1 - 2024-11-25 +* [Added] - Deprecating the old naming convention with com.neo4jh3 and migrating to neo4jh3 +* [Added] - Added new documentation document for the new naming convention. +* [Added] - Added com.neo4jh3.coverage and com.neo4jh3.coverageString procedures which return a list of hex addresses that fully cover a polygon. +* [Updated] - Tested through Neo4j 5.25.1 + # CHANGELOG - 5.19.1 - 2024-06-05 * [Added] - Added two new procedures to read a WKT polygon file and return the Hex Addresss. These are com.neo4jh3.polygonash3 and com.neo4jh3.polygonash3String. These procedures expect the POLYGON in Longitude, Latitude order. * [Updated] - Updated Documentation with bug fixes. diff --git a/Documentation.md b/Documentation.md index 10b5199..955e6f4 100644 --- a/Documentation.md +++ b/Documentation.md @@ -1019,8 +1019,63 @@ An LIST of H3 cell IDs of the same type as the values in the input LIST expressi "85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff" -## com.neo4jh3.gridDisk( h3CellIdExpr, kExpr ) -Returns the H3 cells that are within (grid) distance k of the origin cell. The set of these H3 cells is called the k-ring of the origin cell. +## com.neo4jh3.coverage( ListOuterGeography, h3_resolution, LatLonOrder ) +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography. + +### Syntax +CALL com.neo4jh3.coverage( ListOuterGeography, h3_resolution, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography + +### Error conditions +If h3_resolution is invalid, the function returns -2 + +### Example + call com.neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value; + 613196571542028287 + 613196571548319743 + 613196571598651391 + 613196571539931135 + 613196571560902655 + 613196571550416895 + + call com.neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value; + -2 + +## com.neo4jh3.coverageString( ListOuterGeography, h3_resolution, LatLonOrder ) +Returns a list of HexAddresses (as STRING values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography. + +### Syntax +CALL com.neo4jh3.coverageString( ListOuterGeography, h3_resolution, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography + +### Error conditions +If h3_resolution is invalid, the function returns -2 + +### Example + call com.neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value; + 8828308703fffff + 8828308715fffff + 88301c1a09fffff + 882830870bfffff + 8828308709fffff + 8828308739fffff + + call com.neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value; + "-2" ### Syntax CALL com.neo4jh3.gridDisk( h3CellIdExpr, kExpr ) yield value return value; diff --git a/Documentation_525.md b/Documentation_525.md new file mode 100644 index 0000000..62f93fa --- /dev/null +++ b/Documentation_525.md @@ -0,0 +1,1811 @@ +# Documentation +## neo4jh3.angleBetweenPoints( Latitude1, Longitude1, Latitude2, Longitude2 ) +Returns the angle in degrees between two points. + +### Syntax +RETURN neo4jh3.angleBetweenPoints( Latitude1, Longitude1, Latitude2, Longitude2 ) as value + +### Arguments +* Latitude1: A DOUBLE expression representing the latitude (in degrees) of the first point +* Longitude1: A DOUBLE expression representing the longitude (in degrees) of the first point +* Latitude2: A DOUBLE expression representing the latitude (in degrees) of the second point +* Longitude2: A DOUBLE expression representing the longitude (in degrees) of the second point + +### Returns +A value of the type DOUBLE representing the angle in degrees between the two points. + +### Error conditions +If any of the latitude or longitude values are invalid, the function returns -1 + +### Example + RETURN neo4jh3.angleBetweenPoints(40.123,-78.111,40.555,-78.910) AS value + 305.607560 + + RETURN neo4jh3.angleBetweenPoints(240.123,-78.111,40.555,-78.910) AS value + -1.0 + +## neo4jh3.boundaryaswkt( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in WKT format. + +### Syntax +RETURN neo4jh3.boundaryaswkt( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryaswkt(599686042433355775) AS value + POLYGON ((37.2713558667319 -121.91508032705622, 37.353926450852256 -121.86222328902491, 37.42834118609435 -121.92354999630156, 37.42012867767778 -122.03773496427027, 37.33755608435298 -122.09042892904397, 37.26319797461824 -122.02910130918998, 37.2713558667319 -121.91508032705622)) + + RETURN neo4jh3.boundaryaswkt(1234) AS value + -1 + +## neo4jh3.boundaryaswktString( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in WKT format. + +### Syntax +RETURN neo4jh3.boundaryaswktString( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryaswktString('8009fffffffffff') AS value + POLYGON ((63.09505407752544 -10.444977544778336, 55.706768465152265 5.523646549290317, 58.40154487035269 25.082722326707884, 68.92995788193983 31.831280499087388, 73.31022368544396 0.3256103519432604, 63.09505407752544 -10.444977544778336)) + + RETURN neo4jh3.boundaryaswktString('1234') AS value + -1 + +## neo4jh3.boundaryaswkb( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in WKB format. + +### Syntax +RETURN neo4jh3.boundaryaswkb( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryaswkb(599686042433355775) AS value + 000000000300000001000000074042A2BBC9FE987BC05E7A90AD137AD84042AD4D7641CCC6C05E772EAA970D8A4042B6D3E24CE70DC05E7B1B717195834042B5C6C6C95E70C05E826A3FE95D384042AB3509AB6E52C05E85C9966B36CB4042A1B078A2ADECC05E81DCCBBCCF794042A2BBC9FE987BC05E7A90AD137AD8 + + RETURN neo4jh3.boundaryaswkb(1234) AS value + -1 + +## neo4jh3.boundaryaswkbString( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in WKB format. + +### Syntax +RETURN neo4jh3.boundaryaswkbString( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryaswkbString('8009fffffffffff') AS value + 00000000030000000100000006404F8C2ABB65295FC024E3D418C48DFE404BDA776399D62840161836CD0F75ED404D3365D283054B4039152D4A57DC0140513B846E1065B2403FD4CECC7D6205405253DAB471DB4A3FD4D6CCCD35766F404F8C2ABB65295FC024E3D418C48DFE + + RETURN neo4jh3.boundaryaswkbString('1234') AS value + -1 + +## neo4jh3.boundaryasgeojson( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in GeoJSON format. + +### Syntax +RETURN neo4jh3.boundaryasgeojson( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryasgeojson(599686042433355775) AS value + {"type":"Polygon","coordinates":[[[-121.91508,37.271356],[-121.862223,37.353926],[-121.92355,37.428341],[-122.037735,37.420129],[-122.090429,37.337556],[-122.029101,37.263198],[-121.91508,37.271356]]]} + + RETURN neo4jh3.boundaryasgeojson(1234) AS value + -1 + +## neo4jh3.boundaryasgeojsonString( h3CellIdExpr ) +Returns the polygonal boundary of the input H3 cell in GeoJSON format. + +### Syntax +RETURN neo4jh3.boundaryasgeojsonString( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.boundaryasgeojsonString('8009fffffffffff') AS value + {"type":"Polygon","coordinates":[[[-10.444978,63.095054],[5.523647,55.706768],[25.082722,58.401545],[31.83128,68.929958],[0.32561,73.310224],[-10.444978,63.095054]]]} + + RETURN neo4jh3.boundaryasgeojsonString('1234') AS value + -1 + +## neo4jh3.toparent( h3CellIdExpr, resolutionExpr ) +Returns the parent H3 cell of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.toparent( h3CellIdExpr, resolutionExpr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* resolutionExpr: A LONG expression, whose value is expected to be between 0 and h3_resolution(h3CellIdExpr) inclusive, specifying the resolution of the parent H3 cell ID. + +### Returns +A LONG value of the h3CellIdExpr expression, corresponding to the parent H3 cell ID of the input H3 cell at the specified resolution. + +### Error conditions +If resolutionExpr is smaller than 0 or larger than h3_resolution(h3CellIdExpr), the function returns -1. +If h3CellIdExpr is an invalid H3 cell, the function returns -2. + +### Example + RETURN neo4jh3.toparent(604197150066212863, 3) AS value + 590686371182542847 + + RETURN neo4jh3.toparent(604197150066212863, 23) AS value + -1 + + RETURN neo4jh3.toparent(12345, 6) AS value + -2 + +## neo4jh3.toparentString( h3CellIdExpr, resolutionExpr ) +Returns the parent H3 cell of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.toparentString( h3CellIdExpr, resolutionExpr ) AS value; + +### Arguments +* h3CellIdExpr: A hexadecimal STRING expression representing an H3 cell ID. +* resolutionExpr: A LONG expression, whose value is expected to be between 0 and h3_resolution(h3CellIdExpr) inclusive, specifying the resolution of the parent H3 cell ID. + +### Returns +A STRING value of the h3CellIdExpr expression, corresponding to the parent H3 cell ID of the input H3 cell at the specified resolution. + +### Error conditions +If resolutionExpr is smaller than 0 or larger than h3_resolution(h3CellIdExpr), the function returns -1. +If h3CellIdExpr is an invalid H3 cell, the function returns -2. + +### Example + RETURN neo4jh3.toparentString('892830926cfffff', 6) AS value + 862830927ffffff + + RETURN neo4jh3.toparentString('892830926cfffff', 16) AS value + -1 + + RETURN neo4jh3.toparentString('1234', 6) AS value + -2 + + +## neo4jh3.cellToLatLng( h3CellId1Expr ) +Returns the center latitude and longitude of the input H3 cell. + +### Syntax +RETURN neo4jh3.cellToLatLng( h3CellId1Expr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. + +### Returns +A STRING value consisting of the latitude and longitude of the h3CellIdExpr. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. + +### Example + RETURN neo4jh3.cellToLatLng(635714569676958015) AS value + 37.819895,-122.478297 + + RETURN neo4jh3.cellToLatLng(123) AS value + -1 + +## neo4jh3.cellToLatLngString( h3CellIdExpr ) +Returns the center latitude and longitude of the input H3 cell. + +### Syntax +RETURN neo4jh3.cellToLatLngString( h3CellIdExpr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. + +### Returns +A STRING value consisting of the latitude and longitude of the h3CellIdExpr. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. + +### Example + RETURN neo4jh3.cellToLatLngString('892830926cfffff') AS value + 37.564248,-122.325306 + + RETURN neo4jh3.cellToLatLngString('notavalidhex') AS value + -1 + +## neo4jh3.centerasgeojson( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in GeoJSON format. + +### Syntax +RETURN neo4jh3.centerasgeojson( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centerasgeojson(599686042433355775) AS value + {"type":"Point","coordinates":[-121.976376,37.345793]} + + RETURN neo4jh3.centerasgeojson(1234) AS value + -1 + +## neo4jh3.centerasgeojsonString( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in GeoJSON format. + +### Syntax +RETURN neo4jh3.centerasgeojsonString( h3CellIdExpr ) AS value + + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centerasgeojsonString('8009fffffffffff') AS value + {"type":"Point","coordinates":[10.536199,64.7]} + + RETURN neo4jh3.centerasgeojsonString('1234') AS value + -1 + +## neo4jh3.centeraswkt( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in WKT format. + +### Syntax +RETURN neo4jh3.centeraswkt( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centeraswkt(599686042433355775) AS value + POINT (-121.976376 37.345793) + + RETURN neo4jh3.centeraswkt(1234) AS value + -1 + +## neo4jh3.centeraswktString( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in WKT format. + +### Syntax +RETURN neo4jh3.centeraswktString( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centeraswktString('8009fffffffffff') AS value + POINT (10.536199 64.7) + + RETURN neo4jh3.centeraswktString('1234') AS value + -1 + +## neo4jh3.centeraswkb( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in WKB format. + +### Syntax +RETURN neo4jh3.centeraswkb( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centeraswkb(599686042433355775) AS value + 0000000001C05E7E7CF1C3265B4042AC42F1ED17C6 + + RETURN neo4jh3.centeraswkb(1234) AS value + -1 + +## neo4jh3.centeraswkbString( h3CellIdExpr ) +Returns the center of the input H3 cell as a point in WKB format. + +### Syntax +RETURN neo4jh3.centeraswktString( h3CellIdExpr ) as value + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of the type STRING representing the center of the input H3 cell as a point in GeoJSON format. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + RETURN neo4jh3.centeraswkbString('8009fffffffffff') AS value + 000000000140251288ACE24BBA40502CCCCCCCCCCD + + RETURN neo4jh3.centeraswkbString('1234') AS value + -1 + +## neo4jh3.distanceBetweenHexes( h3CellId1Expr, h3CellId2Expr ) +Returns the great circle distance in KM between two valid H3 addresses. + +### Syntax +RETURN neo4jh3.distanceBetweenHexes( h3CellId1Expr, h3CellId2Expr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal LONG expression representing an H3 cell ID. + +### Returns +A DOUBLE value consisting of the great circle distance in KM between h3CellId1Expr and h3CellId2Expr + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is an invalid h3 address, the function returns -1.0. + +### Example + RETURN neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) AS value + 17.870163466857925 + + RETURN neo4jh3.distanceBetweenHexes(3111,599686015589810175) AS value + -1.0 + +## neo4jh3.distanceBetweenHexesString( h3CellId1Expr, h3CellId2Expr ) +Returns the great circle distance in KM between two valid H3 addresses. + +### Syntax +RETURN neo4jh3.distanceBetweenHexes( h3CellId1Expr, h3CellId2Expr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal STRING expression representing an H3 cell ID. + +### Returns +A DOUBLE value consisting of the great circle distance in KM between h3CellId1Expr and h3CellId2Expr + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is an invalid h3 address, the function returns -1.0. + +### Example + RETURN neo4jh3.distanceBetweenHexesString('8a2989352777fff','8a498935223ffff') AS value + 2360.8203881920604 + + RETURN neo4jh3.distanceBetweenHexesString('123','8a498935223ffff') AS value + -1.0 + +## neo4jh3.gridDistance( h3CellId1Expr, h3CellId2Expr ) +Returns the grid distance of the two input H3 cells, that are expected to have the same resolution. + +### Syntax +RETURN neo4jh3.gridDistance( h3CellId1Expr, h3CellId2Expr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal LONG expression representing an H3 cell ID. + +### Returns +A LONG value that is the grid distance of the two input H3 cells, that are expected to have the same resolution. + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.gridDistance(599686030622195711,599686015589810175) as value + 2 + + RETURN neo4jh3.gridDistance(1234,599686015589810175) as value + -1 + +## neo4jh3.gridDistanceString( h3CellId1Expr, h3CellId2Expr ) +Returns the grid distance of the two input H3 cells, that are expected to have the same resolution. + +### Syntax +RETURN neo4jh3. gridDistance( h3CellId1Expr, h3CellId2Expr ) AS value; + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal STRING expression representing an H3 cell ID. + +### Returns +A LONG value that is the grid distance of the two input H3 cells, that are expected to have the same resolution. + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is not a valid H3 cell ID, the function returns "-1". + +### Example + RETURN neo4jh3.gridDistanceString('85283473fffffff','8528342bfffffff') as value + 2 + + RETURN neo4jh3.gridDistanceString('12111','8528342bfffffff') as value + -1 + +## neo4jh3.h3HexAddress( latitude, longitude, resolution ) +Returns the H3 cell ID (as a LONG) corresponding to the provided longitude and latitude at the specified resolution. + +### Syntax +RETURN neo4jh3.h3HexAddress( latitudeExpr, longitudeExpr, resolutionExpr ) AS value; + +### Arguments +* latitudeExpr: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitudeExpr: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +A value of the type of LONG representing, as a hexadecimal string, the H3 cell ID of the input location at the specified resolution. + +### Error conditions +* If resolutionExpr is not a valid H3 cell ID, the function returns -2. +* If latitudeExpr is not a valid latitude the function returns -3. +* If longitudeExpr is not a valid longitude, the function returns -4. + +### Example + RETURN neo4jh3.h3HexAddress(37.8199, -122.4783, 13) AS value + 635714569676958015 + + RETURN neo4jh3.h3HexAddress(37.8199, -122.4783, 16) AS value + -2 + + RETURN neo4jh3.h3HexAddress(97.8199, -122.4783, 13) AS value + -3 + + +## neo4jh3.h3HexAddressString( latitude, longitude, resolution ) +Returns the H3 cell ID (as a hexadecimal STRING) corresponding to the provided longitude and latitude at the specified resolution. + +### Syntax +RETURN neo4jh3.h3HexAddressString( latitudeExpr, longitudeExpr, resolutionExpr ) AS value; + +### Arguments +* latitudeExpr: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitudeExpr: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +A value of the type of STRING representing, as a hexadecimal string, the H3 cell ID of the input location at the specified resolution. + +### Error conditions +* If resolutionExpr is not a valid H3 cell ID, the function returns -2. +* If latitudeExpr is not a valid latitude the function returns -3. +* If longitudeExpr is not a valid longitude, the function returns -4. + +### Example + RETURN neo4jh3.h3HexAddressString(37.8199, -122.4783, 13) AS value + 8d283087022a93f + + RETURN neo4jh3.h3HexAddressString(37.8199, -122.4783, 16) AS value + -2 + + RETURN neo4jh3.h3HexAddressString(97.8199, -122.4783, 13) AS value + -3 + +## neo4jh3.h3tostring( h3CellIdExpr ) +Converts the input H3 cell ID to its equivalent hexadecimal string representation. + +### Syntax +RETURN neo4jh3.h3tostring( h3CellIdExpr ) AS value; + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of type STRING. The function converts the LONG to its corresponding hexadecimal string. + + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns "-1". + +### Example + RETURN neo4jh3.h3tostring(599686042433355775) AS value + 85283473fffffff + + RETURN neo4jh3.h3tostring(0) AS value + -1 + +## neo4jh3.h3Resolution( h3CellIdExpr ) +Returns the resolution of the input H3 cell. + +### Syntax +RETURN neo4jh3.h3Resolution( h3CellIdExpr ) AS value; + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. + +### Returns +A value of whose type LONG between 0 and 15, that is the resolution of the input H3 cell ID. + + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.h3Resolution(599686042433355775) AS value + 5 + + RETURN neo4jh3.h3Resolution(337) AS value + -1 + +## neo4jh3.h3ResolutionString( h3CellIdExpr ) +Returns the resolution of the input H3 cell. + +### Syntax +RETURN neo4jh3.h3ResolutionString( h3CellIdExpr ) AS value; + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. + +### Returns +A value of whose type LONG between 0 and 15, that is the resolution of the input H3 cell ID. + + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.h3ResolutionString('85283473fffffff') AS value + 5 + + RETURN neo4jh3.h3ResolutionString('notavalidhexaddress') AS value + -1 + +## neo4jh3.h3Validate( h3CellIdExpr ) +Returns the input value, that is of type LONG if it corresponds to a valid H3 cell ID, or emits an error otherwise. + +### Syntax +RETURN neo4jh3.h3Validate( h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A LONG expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns 0. + +### Example + RETURN neo4jh3.h3Validate(590112357393367039) AS value; + 590112357393367039 + + RETURN neo4jh3.h3Validate(123411) AS value; + -1 + +## neo4jh3.h3ValidateString( h3CellIdExpr ) +Returns the input value, that is of type STRING if it corresponds to a valid H3 cell ID, or emits an error otherwise. + +### Syntax +RETURN neo4jh3.h3ValidateString( h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A STRING expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.h3ValidateString('85283447fffffff') AS value; + '85283447fffffff' + + RETURN neo4jh3.h3ValidateString('123411') AS value; + "-1" + + +## neo4jh3.ispentagon( h3CellIdExpr ) +Returns true if the input LONG corresponds to a pentagonal H3 cell or not. + +### Syntax +RETURN neo4jh3.ispentagon(h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A LONG expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns false; + +### Example + RETURN neo4jh3.ispentagon(590112357393367039) AS value; + true + + RETURN neo4jh3.ispentagon(123456) AS value; + false + +## neo4jh3.ispentagonString( h3CellIdExpr ) +Returns true if the input STRING corresponds to a pentagonal H3 cell or not. + +### Syntax +RETURN neo4jh3.ispentagonString(h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A STRING expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns false; + +### Example + + RETURN neo4jh3.ispentagonString('830800fffffffff') AS value; + true + + RETURN neo4jh3.ispentagonString('85283473fffffff') AS value; + false + +## neo4jh3.h3Validate( h3CellIdExpr ) +Returns the input value, that is of type LONG if it corresponds to a valid H3 cell ID, or emits an error otherwise. + +### Syntax +RETURN neo4jh3.h3Validate(h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A LONG expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.h3Validate(590112357393367039) AS value; + 590112357393367039 + + RETURN neo4jh3.h3Validate(1110) AS value; + -1 + +## neo4jh3.h3ValidateString( h3CellIdExpr ) +Returns the input value, that is of type STRING if it corresponds to a valid H3 cell ID, or emits an error otherwise. + +### Syntax +RETURN neo4jh3.h3ValidateString(h3CellIdExpr) AS value; + +### Arguments +h3CellIdExpr: A STRING expression that is expected to represent a valid H3 cell ID. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns "invalid h3 resolution". + +### Example + RETURN neo4jh3.h3ValidateString('85283473fffffff') AS value; + 85283473fffffff + + RETURN neo4jh3.h3ValidateString('notvalidstring') AS value; + -1 + + +## neo4jh3.latlongash3( latitude, longitude, resolution ) +Returns the H3 cell ID (as a LONG) corresponding to the provided longitude and latitude at the specified resolution. + +### Syntax +RETURN neo4jh3.latlongash3( latitudeExpr, longitudeExpr, resolutionExpr ) AS value; + +### Arguments +* latitudeExpr: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitudeExpr: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +A value of the type of LONG representing, as a hexadecimal string, the H3 cell ID of the input location at the specified resolution. + +### Error conditions +* If resolutionExpr is not a valid H3 cell ID, the function returns -2. +* If latitudeExpr is not a valid latitude the function returns -3. +* If longitudeExpr is not a valid longitude, the function returns -4. + + +### Example + RETURN neo4jh3.latlongash3(37.8199, -122.4783, 13) AS value + 635714569676958015 + + RETURN neo4jh3.latlongash3(37.8199, -122.4783, 16) AS value + -2 + + RETURN neo4jh3.latlongash3(97.8199, -122.4783, 13) AS value + -3 + + RETURN neo4jh3.latlongash3(67.8199, -222.4783, 13) AS value + -4 + +## neo4jh3.latlongash3String( latitude, longitude, resolution ) +Returns the H3 cell ID (as a hexadecimal STRING) corresponding to the provided longitude and latitude at the specified resolution. + +### Syntax +RETURN neo4jh3.latlongash3String( latitudeExpr, longitudeExpr, resolutionExpr ) AS value; + +### Arguments +* latitudeExpr: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitudeExpr: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +A value of the type of STRING representing, as a hexadecimal string, the H3 cell ID of the input location at the specified resolution. + +### Error conditions +* If resolutionExpr is not a valid H3 cell ID, the function returns -2. +* If latitudeExpr is not a valid latitude the function returns -3. +* If longitudeExpr is not a valid longitude, the function returns -4. +* +### Example + RETURN neo4jh3.latlongash3String(37.8199, -122.4783, 13) AS value + 8d283087022a93f + + RETURN neo4jh3.latlongash3String(37.8199, -122.4783, 16) AS value + -2 + + RETURN neo4jh3.latlongash3String(97.8199, -122.4783, 13) AS value + -3 + + RETURN neo4jh3.latlongash3String(67.8199, -222.4783, 13) AS value + -4 + + +## neo4jh3.maxChild( h3CellIdExpr, resolutionExpr ) +Returns the child of minimum value of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.maxChild( h3CellIdExpr, resolutionExpr ) AS value + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +A value of the same type as the type of the h3CellIdExpr expression, corresponding to the child of maximum value of the input H3 cell ID at the specified resolution. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. +If resolutionExpr is an invalid h3 resolution, the function returns -2. + +### Example + RETURN neo4jh3.maxChild(599686042433355775, 10) AS value + 622204040416821247 + + RETURN neo4jh3.maxChild(123,10) AS value + -1 + + RETURN neo4jh3.maxChild(599686042433355775,23) AS value + -2 + +## neo4jh3.maxChildString( h3CellIdExpr, resolutionExpr ) +Returns the child of maximum value of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.maxChildString( h3CellIdExpr, resolutionExpr ) AS value + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +A value of the same type as the type of the h3CellIdExpr expression, corresponding to the child of maximum value of the input H3 cell ID at the specified resolution. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. +If resolutionExpr is an invalid h3 resolution, the function returns -2. + +### Example + RETURN neo4jh3.maxChildString('85283473fffffff', 10) AS value + '8a2834736db7fff' + + RETURN neo4jh3.maxChildString('123',10) AS value + '-1' + + RETURN neo4jh3.maxChildString('85283473fffffff',27) AS value + '-2' + +## neo4jh3.minChild( h3CellIdExpr, resolutionExpr ) +Returns the child of minimum value of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.minChild( h3CellIdExpr, resolutionExpr ) AS value + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +A value of the same type as the type of the h3CellIdExpr expression, corresponding to the child of minimum value of the input H3 cell ID at the specified resolution. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. +If resolutionExpr is an i nvalid resolution or smaller than h3_resolution(h3CellIdExpr), the function returns -2. + +### Example + RETURN neo4jh3.minChild(599686042433355775, 10) AS value + 622204039496499199 + + RETURN neo4jh3.minChild(123,10) AS value + -1 + + RETURN neo4jh3.minChild(599686042433355775,23) AS value + -2 + +## neo4jh3.minChildString( h3CellIdExpr, resolutionExpr ) +Returns the child of minimum value of the input H3 cell at the specified resolution. + +### Syntax +RETURN neo4jh3.minChild( h3CellIdExpr, resolutionExpr ) AS value + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +A value of the same type as the type of the h3CellIdExpr expression, corresponding to the child of minimum value of the input H3 cell ID at the specified resolution. + +### Error conditions +If h3CellIdExpr is an invalid h3 address, the function returns -1. +If resolutionExpr is an invalid resolution or smaller than h3_resolution(h3CellIdExpr), the function returns -2. + +### Example + RETURN neo4jh3.minChildString('85283473fffffff', 10) AS value + '8a2834700007fff' + + RETURN neo4jh3.minChildString('123',10) AS value + '-1' + + RETURN neo4jh3.minChildString('85283473fffffff',27) AS value + '-2' + +## neo4jh3.pointash3( geographyExpr, resolutionExpr, LatLonOrder ) +Returns the H3 cell ID (as a LONG) corresponding to the provided point at the specified resolution. + +### Syntax +RETURN neo4jh3.pointash3( geographyExpr, resolutionExpr, LatLonOrder ) + +### Arguments +* geographyExpr: A LONG expression representing a point geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns the H3 cell ID (as a LONG) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a point, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + RETURN neo4jh3.pointash3('POINT(37.8199 -122.4783)',13, 'latlon') AS value + 635714569676958015 + + RETURN neo4jh3.pointash3('zzz(37.8199 -122.4783)',13, 'latlon') AS value + -1 + + RETURN neo4jh3.pointash3('POINT(37.8199 -122.4783)',16, 'latlon') AS value + -2 + +## neo4jh3.pointash3String( geographyExpr, resolutionExpr, LatLonOrder ) +Returns the H3 cell ID (as a STRING) corresponding to the provided point at the specified resolution. + +### Syntax +RETURN neo4jh3.pointash3String( geographyExpr, resolutionExpr, LatLonOrder ) + +### Arguments +* geographyExpr: A STRING expression representing a point geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns the H3 cell ID (as a STRING) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a point, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + RETURN neo4jh3.pointash3String('POINT(37.8199 -122.4783)',13, 'latlon') AS value + 8d283087022a93f + + RETURN neo4jh3.pointash3String('zzz(37.8199 -122.4783)',13, 'latlon') AS value + -1 + + RETURN neo4jh3.pointash3String('POINT(37.8199 -122.4783)',16, 'latlon') AS value + -2 + +## neo4jh3.stringToH3( h3CellIdExpr ) +Converts the input string, which is expected to be a hexadecimal string representing an H3 cell, to the corresponding LONG representation of the H3 cell. + +### Syntax +RETURN neo4jh3.stringToH3( h3CellIdExpr ) AS value; + +### Arguments +* h3CellIdExpr: A well-formed hexadecimal STRING expression representing a valid H3 cell ID. + +### Returns +A value of type LONG. The function converts the hexadecimal STRING to its corresponding LONG representation. + +### Error conditions +If h3CellIdExpr is not a valid H3 cell ID, the function returns -1. + +### Example + RETURN neo4jh3.stringToH3('85283473fffffff') AS value + 599686042433355775 + + RETURN neo4jh3.stringToH3('notavalidaddress') AS value + -1 + +# Procedures +## neo4jh3.compact( h3CellIdsExpr ) +Compacts the input set of H3 cells. The compacted set covers the same set of H3 cells as the original one. + +### Syntax +CALL neo4jh3.compact( h3CellIdsExpr ); + +### Arguments +* h3CellIdsExpr: A LIST of LONG expressions representing H3 cell IDs. + +### Returns +An LIST of H3 cell IDs of the same type as the values in the input LIST expression h3CellIdsExpr. + +### Error conditions + + +### Example + CALL neo4jh3.compact([599686042433355775,599686030622195711,599686044580839423,599686038138388479,599686043507097599,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686040285872127,599686041359613951,599686039212130303,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647]) yield value return value; + 599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751 + +## neo4jh3.compactString( h3CellIdsExpr ) +Compacts the input set of H3 cells. The compacted set covers the same set of H3 cells as the original one. + +### Syntax +CALL neo4jh3.compactString( h3CellIdsExpr ); + +### Arguments +* h3CellIdsExpr: A LIST of STRING expressions representing H3 cell IDs. + +### Returns +An LIST of H3 cell IDs of the same type as the values in the input LIST expression h3CellIdsExpr. + +### Error conditions + + +### Example + CALL neo4jh3.compactString(['85283473fffffff', '85283447fffffff', '8528347bfffffff', '85283463fffffff', '85283477fffffff', '8528340ffffffff', '8528340bfffffff', '85283457fffffff', '85283443fffffff', '8528344ffffffff', '852836b7fffffff', '8528346bfffffff', '8528346ffffffff', '85283467fffffff', '8528342bfffffff', '8528343bfffffff', '85283407fffffff', '85283403fffffff', '8528341bfffffff']) yield value return value; + + "85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff" + +## neo4jh3.coverage( ListOuterGeography, h3_resolution, LatLonOrder ) +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography. + +### Syntax +CALL neo4jh3.coverage( ListOuterGeography, h3_resolution, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography + +### Error conditions +If h3_resolution is invalid, the function returns -2 + +### Example + call neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value; + 613196571542028287 + 613196571548319743 + 613196571598651391 + 613196571539931135 + 613196571560902655 + 613196571550416895 + + call neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value; + -2 + +## neo4jh3.coverageString( ListOuterGeography, h3_resolution, LatLonOrder ) +Returns a list of HexAddresses (as STRING values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography. + +### Syntax +CALL neo4jh3.coverageString( ListOuterGeography, h3_resolution, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of HexAddresses (as LONG values) identifying the minimal set of H3 cells that completely cover a shape specified by the ListOuterGeography + +### Error conditions +If h3_resolution is invalid, the function returns -2 + +### Example + call neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value; + 8828308703fffff + 8828308715fffff + 88301c1a09fffff + 882830870bfffff + 8828308709fffff + 8828308739fffff + + call neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value; + "-2" + +### Syntax +CALL neo4jh3.gridDisk( h3CellIdExpr, kExpr ) yield value return value; + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. +* kExpr: An INTEGER expression representing the grid distance. kExpr must be non-negative. + +### Returns +A list of LONG values corresponding to the H3 cell IDs that have the same resolution as the input H3 cell and are within grid distance k of the input H3 cell, where k is the value of the kExpr. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 +If kExpr < 0, the function returns -2 + +### Example + CALL neo4jh3.gridDisk(599686042433355775,1) yield value return value; + 599686042433355775,599686030622195711,599686044580839423,599686038138388479,599686043507097599,599686015589810175,599686014516068351 + + CALL neo4jh3.gridDisk(1234,1) yield value return value; + -1 + + CALL neo4jh3.gridDisk(599686042433355775,-1) yield value return value; + -2 + +## neo4jh3.gridDiskString( h3CellIdExpr, kExpr ) +Returns the children H3 cells of the input H3 cell at the specified resolution. + +### Syntax +CALL neo4jh3.gridDiskString( h3CellIdExpr, kExpr ) yield value return value; + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. +* kExpr: An INTEGER expression representing the grid distance. kExpr must be non-negative. + +### Returns +A list of STRING values corresponding to the H3 cell IDs that have the same resolution as the input H3 cell and are within grid distance k of the input H3 cell, where k is the value of the kExpr. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 +If kExpr < 0, the function returns -2 + + +### Example + CALL neo4jh3.gridDiskString('85283473fffffff',1) yield value return value; + 85283473fffffff,85283447fffffff,8528347bfffffff,85283463fffffff,85283477fffffff,8528340ffffffff,8528340bfffffff + + CALL neo4jh3.gridDiskString('1234',1) yield value return value; + -1 + + CALL neo4jh3.gridDiskString('85283473fffffff',-1) yield value return value; + -2 + +## neo4jh3.lineash3( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided LINESTRING at the specified resolution. + +### Syntax +call neo4jh3.lineash3( geographyExpr, resolutionExpr ) yield value + +### Arguments +* geographyExpr: A STRING expression representing a LINESTRING geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a LINESTRING, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.lineash3('LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + 608693213150052351,608693229507837951,608693241537101823,608693229038075903,608693229038075903,608693228954189823 + + call neo4jh3.lineash3('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + -1 + + call neo4jh3.lineash3('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) yield value return value + -2 + +## neo4jh3.lineash3String( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided LINESTRING at the specified resolution. + +### Syntax +RETURN neo4jh3.lineash3String( geographyExpr, resolutionExpr ) + +### Arguments +* geographyExpr: A STRING expression representing a LINESTRING geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided LINESTRING at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a LINESTRING, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.lineash3String('LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + '87283409affffff','872834469ffffff','872834736ffffff','87283444dffffff','87283444dffffff','872834448ffffff' + + call neo4jh3.lineash3String('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + -1 + + call neo4jh3.lineash3String('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) yield value return value + -2 + +## neo4jh3.multilineash3( geographyExpr, resolutionExpr, LatLonOrder ) +Returns the H3 cell ID (as a LONG) corresponding to the provided MULTILINESTRING at the specified resolution. + +### Syntax +RETURN neo4jh3.multilineash3( geographyExpr, resolutionExpr ) + +### Arguments +* geographyExpr: A STRING expression representing a MULTILINESTRING geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns the H3 cell ID (as a LONG) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a MULTILINESTRING, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + CALL neo4jh3.multilineash3('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',6, 'latlon') yield value return value; + 604189629981130751, 604189629444259839, 604189629444259839 + + call neo4jh3.multilineash3('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7, 'latlon') yield value return value + -1 + + call neo4jh3.multilineash3('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17, 'latlon') yield value return value + -2 + +## neo4jh3.multilineash3String( geographyExpr, resolutionExpr, LatLonOrder ) +Returns the H3 cell ID (as a STRING) corresponding to the provided MULTILINESTRING at the specified resolution. + +### Syntax +call neo4jh3.multilineash3String( geographyExpr, resolutionExpr ) yield value + +### Arguments +* geographyExpr: A STRING expression representing a MULTILINESTRING geography in WKT format +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + + +### Returns +Returns the H3 cell ID (as a STRING) corresponding to the provided MULTILINESTRING at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a MULTILINESTRING, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + CALL neo4jh3.multilineash3String('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',6, 'latlon') yield value return value; + '86283446fffffff', '86283444fffffff', '86283444fffffff' + + call neo4jh3.multilineash3String('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7, 'latlon') yield value return value + '-1' + + call neo4jh3.multilineash3String('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17, 'latlon') yield value return value + '-2' + +## neo4jh3.multipolygonash3( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided POLYGON at the specified resolution. + +### Syntax +call neo4jh3.multipolygonash3( geographyExpr, resolutionExpr ) yield value + +### Arguments +* geographyExpr: A STRING expression representing a POLYGON geography in WKT format (Longitude and then Latitude) +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a POLYGON, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value + 613229524731035647, 613229523017662463, 613229524217233407, 613229524714258431, 613229524733132799 + + call neo4jh3.multipolygonash3('ZZZ(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value + -1 + + call neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',19) yield value return value + -2 + +## neo4jh3.multipolygonash3String( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided POLYGON at the specified resolution. + +### Syntax +RETURN neo4jh3.multipolygonash3String( geographyExpr, resolutionExpr ) + +### Arguments +* geographyExpr: A STRING expression representing a POLYGON geography in WKT format (Longitude and then Latitude) +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided POLYGON at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a polygon, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value + '882a100f35fffff','882a1008d3fffff','882a100d4bfffff', '882a100f25fffff', '882a100f37fffff' + + call neo4jh3.multipolygonash3String('zzz(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value + -1 + + call neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',18) yield value return value + -2 + +## neo4jh3.polygonash3( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided POLYGON at the specified resolution. + +### Syntax +call neo4jh3.polygonash3( geographyExpr, resolutionExpr ) yield value + +### Arguments +* geographyExpr: A STRING expression representing a POLYGON geography in WKT format (Longitude and then Latitude) +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a LONG) corresponding to the provided point at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a POLYGON, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',6) yield value return value + 604233031162527743, 604233025391165439, 604233031699398655 + + call neo4jh3.polygonash3('ZZZ((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',7) yield value return value + -1 + + call neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',16) yield value return value + -2 + +## neo4jh3.polygonash3String( geographyExpr, resolutionExpr ) +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided POLYGON at the specified resolution. + +### Syntax +RETURN neo4jh3.polygonash3String( geographyExpr, resolutionExpr ) + +### Arguments +* geographyExpr: A STRING expression representing a POLYGON geography in WKT format (Longitude and then Latitude) +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution of the child H3 cell ID. + +### Returns +Returns a list of H3 cell IDs (as a STRING) corresponding to the provided POLYGON at the specified resolution. + +### Error conditions +If geographyExpr is of type STRING and the value is either an invalid WKT or does not represent a polygon, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call neo4jh3.polygonash3String('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',6) yield value return value + '862aabd8fffffff','862aabc37ffffff','862aabdafffffff' + + call neo4jh3. polygonash3String('ZZZPOLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',7) yield value return value + -1 + + call neo4jh3.polygonash3String('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',16) yield value return value + -2 + +## neo4jh3.polygonToCells( ListOuterGeography, ListHoleGeography, resolutionExpr, LatLonOrder ) +Returns a list of H3 cell IDs (represented as LONGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained by the input area geography. + +### Syntax +call neo4jh3.polygonToCells( ListOuterGeography, ListHoleGeography, resolutionExpr, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListHoleGeography: A LIST of latitude and longitude values that express a hole within the ListLatLon polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +A list of H3 cell IDs (represented as LONGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained by the input area geography. + +### Error conditions +If resolutionExpr is invalid, the function returns -2 + +### Example + call neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value; + 608692971759468543, 608692970719281151, 608692970736058367, 608692970752835583, 608692975819554815, 608692970769612799, 608692975836332031, 608692970786390015, 608692975853109247, 608692970803167231, 608692975869886463, 608692970819944447, 608692975886663679, 608692975903440895, 608692970585063423, 608692975920218111, 608692970601840639, 608692975685337087, 608692975702114303, 608692975450456063, 608692975718891519, 608692971994349567, 608692970668949503, 608692975467233279, 608692975735668735, 608692972011126783 + + call neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value + -2 + +## neo4jh3.polygonToCellsString( h3CellIdExpr, resolutionExpr ) +Returns a list of H3 cell IDs (represented as STRINGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained by the input area geography. + +### Syntax +call neo4jh3.polygonToCellsString( h3CellIdExpr, resolutionExpr ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListHoleGeography: A LIST of latitude and longitude values that express a hole within the ListLatLon polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +A list of H3 cell IDs (represented as STRINGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained by the input area geography. + +### Error conditions +If resolutionExpr is invalid, the function returns -2 + +### Example + call neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value; + "872830866ffffff", "872830828ffffff", "872830829ffffff", "87283082affffff", "872830958ffffff", "87283082bffffff", "872830959ffffff", "87283082cffffff", "87283095affffff", "87283082dffffff", "87283095bffffff", "87283082effffff", "87283095cffffff", "87283095dffffff", "872830820ffffff", "87283095effffff", "872830821ffffff", "872830950ffffff", "872830951ffffff", "872830942ffffff", "872830952ffffff", "872830874ffffff", "872830825ffffff", "872830943ffffff", "872830953ffffff", "872830875ffffff" + + call neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value + -2 + +## neo4jh3.gridpathcell( h3CellId1Expr, h3CellId2Expr ) +Returns the line of indexes as LONGs between two H3 indexes (inclusive). + +### Syntax +CALL neo4jh3.gridpathcell( h3CellId1Expr, h3CellId2Expr ) yield value return value + +### Arguments +* h3CellId1Expr: A hexadecimal LONG expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal LONG expression representing an H3 cell ID. + +### Returns +Returns the line of indexes as LONG values between h3CellId1Expr and h3CellId2Expr + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is an invalid h3 address, the function returns -1. + +### Example + CALL neo4jh3.gridpathcell(599686030622195711, 599686015589810175) yield value return value; + 599686030622195711, 599686014516068351, 599686015589810175 + + CALL neo4jh3.gridpathcell(604189641121202175,604189642126508543) yield value return value; + -1 + +## neo4jh3.gridpathcellString( h3CellId1Expr, h3CellId2Expr ) +Returns the line of indexes as STRINGs between two H3 indexes (inclusive). + +### Syntax +CALL neo4jh3.gridpathcellString( h3CellId1Expr, h3CellId2Expr ) yield value return value + +### Arguments +* h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. +* h3CellId2Expr: A hexadecimal STRING expression representing an H3 cell ID. + +### Returns +Returns the line of indexes as STRING values between h3CellId1Expr and h3CellId2Expr + +### Error conditions +If h3CellId1Expr or h3CellId2Expr is an invalid h3 address, the function returns -1. + +### Example + CALL neo4jh3.gridpathcellString('862834707ffffff','86283472fffffff') yield value return value + "862834707ffffff", "86283472fffffff" + + CALL neo4jh3.gridpathcellString('as331','86283472fffffff') yield value return value + -1 + +## neo4jh3.gridpathlatlon( latitude1, longitude1, latitude2, longitude2, resolutionExpr ) +Returns the line of indexes as LONGs between a pair of latitude/longitude points converted to Hex Addresses at the specified resolution. + +### Syntax +CALL neo4jh3.gridpathlatlon( latitude1, longitude1, latitude2, longitude2, resolutionExpr ) yield value return value + +### Arguments +* latitude1: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitude1: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* latitude2: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitude2: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +Returns the line of indexes as LONG values between the two points + +### Error conditions +If resolutionExpr is invalid, the procedure returns -2. +If latitude1 or latitude2 are invalid, the procedure returns -3. +If longitude1 or longitude2 are invalid, the procedure returns -4. + + +### Example + CALL neo4jh3.gridpathlatlon(37.2,-119.2,38.2,-119.2,5) yield value return value; + 599711803647197183, 599711799352229887, 599711802573455359, 599709700186963967, 599709695891996671, 599709778570117119, 599709774275149823 + + CALL neo4jh3.gridpathlatlon(37.2,-119.2,38.2,-119.2,17) yield value return value; + -2 + + CALL neo4jh3.gridpathlatlon(97.2,-119.2,38.2,-119.2,5) yield value return collect(value); + -3 + + CALL neo4jh3.gridpathlatlon(37.2,-219.2,38.2,-119.2,5) yield value return collect(value); + -4 + +## neo4jh3.gridpathlatlonString( latitude1, longitude1, latitude2, longitude2, resolutionExpr ) +Returns the line of indexes as STRINGs between a pair of latitude/longitude points converted to Hex Addresses at the specified resolution. + +### Syntax +CALL neo4jh3.gridpathlatlonString( latitude1, longitude1, latitude2, longitude2, resolutionExpr ) yield value return value + +### Arguments +* latitude1: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitude1: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* latitude2: A DOUBLE expression representing the latitude (in degrees) of the location whose H3 cell ID we want to compute. +* longitude2: A DOUBLE expression representing the longitude (in degrees) of the location whose H3 cell ID we want to compute. +* resolutionExpr: An INT expression, whose value is expected to be between 0 and 15 inclusive, specifying the resolution for the H3 cell ID. + +### Returns +Returns the line of indexes as STRING values between the two points + +### Error conditions +If resolutionExpr is invalid, the procedure returns -2. +If latitude1 or latitude2 are invalid, the procedure returns -3. +If longitude1 or longitude2 are invalid, the procedure returns -4. + +### Example + CALL neo4jh3.gridpathlatlonString(37.2,-119.2,38.2,-119.2,5) yield value return value; + "8529ab53fffffff", "8529ab43fffffff", "8529ab4ffffffff", "85298cb7fffffff", "85298ca7fffffff", "85298ddbfffffff", "85298dcbfffffff" + + CALL neo4jh3.gridpathlatlonString(37.2,-119.2,38.2,-119.2,17) yield value return value; + "-2" + + CALL neo4jh3.gridpathlatlonString(97.2,-119.2,38.2,-119.2,5) yield value return collect(value); + "-3" + + CALL neo4jh3.gridpathlatlonString(37.2,-219.2,38.2,-119.2,5) yield value return collect(value); + "-4" + +## neo4jh3.polygonIntersection( ListOuterGeography, ListHoleGeography, ListSecondOuterGeography, ListSecondHoleGeography, resolutionExpr, LatLonOrder ) +Returns a list of H3 cell IDs (represented as LONGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained within both polygons. + +### Syntax +call neo4jh3.polygonIntersection( ListOuterGeography, ListHoleGeography, ListSecondOuterGeography, ListSecondHoleGeography, resolutionExpr, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListHoleGeography: A LIST of latitude and longitude values that express a hole within the ListLatLon polygon +* ListSecondOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListSecondHoleGeography: A LIST of latitude and longitude values that express a hole within the ListLatLon polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of H3 cell IDs (represented as LONGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained within both polygons. + +### Error conditions +If resolutionExpr is invalid, the function returns -2 + +### Example + call neo4jh3.polygonIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value + 608692975685337087, 608692970668949503, 608692975920218111, 608692975718891519, 608692975903440895, 608692975467233279, 608692975702114303, 608692975886663679, 608692975450456063, 608692975735668735 + + call neo4jh3.polygonIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],[],[],20,'latlon') yield value return value + -2 + +## neo4jh3.polygonIntersectionString( ListOuterGeography, ListHoleGeography, ListSecondOuterGeography, ListSecondHoleGeography, resolutionExpr, LatLonOrder ) +Returns a list of H3 cell IDs (represented as STRINGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained within both polygons. + +### Syntax +call neo4jh3.polygonIntersectionString( ListOuterGeography, ListHoleGeography, ListSecondOuterGeography, ListSecondHoleGeography, resolutionExpr, LatLonOrder ) yield value return value; + +### Arguments +* ListOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListHoleGeography: A LIST of latitude and longitude values that express a hole within the List LatLon polygon +* ListSecondOuterGeography: A LIST of latitude and longitude values that express a polygon +* ListSecondHoleGeography: A LIST of latitude and longitude values that express a hole within the List LatLon polygon +* h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. +* LatLonOrder A STRING that indicates the order of the geometry (latlon or lonlat) + +### Returns +Returns a list of H3 cell IDs (represented as LONGs) corresponding to hexagons or pentagons, of the specified resolution, that are contained within both polygons. + +### Error conditions +If resolutionExpr is invalid, the function returns -2 + +### Example + call neo4jh3.polygonIntersectionString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value + "872830950ffffff", "872830825ffffff", "87283095effffff", "872830952ffffff", "87283095dffffff", "872830943ffffff", "872830951ffffff", "87283095cffffff", "872830942ffffff", "872830953ffffff" + + call neo4jh3.polygonIntersectionString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],[],[],20,'latlon') yield value return value + "-2" + +## neo4jh3.uncompact( h3CellIdsExpr, resolutionExpr ) +Uncompacts the input set of H3 cells to the specified resolution. The uncompacted set covers the same set of H3 cells as the original one using cells at the specified resolution. + +### Syntax +call neo4jh3.uncompact(h3CellIdsExpr, resolutionExpr) yield value return value + +### Arguments +* h3CellIdsExpr: A LIST of LONG expressions representing H3 cell IDs. +* resolutionExpr: An INTEGER expression, whose value is expected to be between the maximum resolution of the input H3 cells and 15 inclusive, specifying the resolution of the H3 cell IDs in the output LIST. + +### Returns +A LIST of H3 cell IDs of the same type as the values in the input LIST expression h3CellIdsExpr. + +### Error conditions +If resolutionExpr is smaller than the maximum resolution of the H3 cell in the input ARRAY, or larger than 15, the function returns -2 + +### Example + call neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 5) yield value return value + 599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,599686038138388479,599686039212130303,599686040285872127,599686041359613951,599686042433355775,599686043507097599,599686044580839423 + + call neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 5) yield value return value +-2 + +## neo4jh3.uncompactString( h3CellIdsExpr, resolutionExpr ) +Uncompacts the input set of H3 cells to the specified resolution. The uncompacted set covers the same set of H3 cells as the original one using cells at the specified resolution. + +### Syntax +CALL neo4jh3.uncompactString(h3CellIdsExpr, resolutionExpr); + +### Arguments +* h3CellIdsExpr: A LIST of STRING expressions representing H3 cell IDs. +* * resolutionExpr: An INTEGER expression, whose value is expected to be between the maximum resolution of the input H3 cells and 15 inclusive, specifying the resolution of the H3 cell IDs in the output LIST. + +### Returns +An LIST of H3 cell IDs of the same type as the values in the input LIST expression h3CellIdsExpr. + +### Error conditions +If resolutionExpr is smaller than the maximum resolution of the H3 cell in the input ARRAY, or larger than 15, the function returns -2 + +### Example + CALL neo4jh3.uncompactString(["85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff"],5) yield value return value; + + "85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "85283463fffffff", "85283467fffffff", "8528346bfffffff", "8528346ffffffff", "85283473fffffff", "85283477fffffff", "8528347bfffffff" + + CALL neo4jh3.uncompactString(["85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff"],0) yield value return value; + "-2" + +## neo4jh3.tochildren( h3CellIdExpr, resolutionExpr ) +Returns an array of the children H3 cells of the input H3 cell at the specified resolution. + +### Syntax +CALL neo4jh3.tochildren(h3CellIdExpr, resolutionExpr) yield value return value; + +### Arguments +* h3CellIdExpr: A LONG expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. + +### Returns +A list of LONG values corresponding to the children H3 cell IDs of the input H3 cell at the specified resolution. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + CALL neo4jh3.tochildren(599686042433355775,6) yield value return value; + + 604189641121202175, 604189641255419903, 604189641389637631, 604189641523855359, 604189641658073087, 604189641792290815, 604189641926508543 + + CALL neo4jh3.tochildren(1234,1) yield value return value; + -1 + + CALL neo4jh3.tochildren(599686042433355775,-1) yield value return value; + -2 + +## neo4jh3.tochildrenString( h3CellIdExpr, resolutionExpr ) +Returns an array of the children H3 cells of the input H3 cell at the specified resolution. + +### Syntax +CALL neo4jh3.tochildrenString(h3CellIdExpr, resolutionExpr) yield value return value; + +### Arguments +* h3CellIdExpr: A STRING expression representing an H3 cell ID. +* resolutionExpr: An INT expression, whose value is expected to be between h3_resolution(h3CellIdExpr) and 15 inclusive, specifying the resolution of the children H3 cell IDs. + +### Returns +A list of STRING values corresponding to the children H3 cell IDs of the input H3 cell at the specified resolution. + +### Error conditions +If h3CellIdExpr is invalid, the function returns -1 + +### Example + CALL neo4jh3.tochildrenString('85283473fffffff',1) yield value return value; + 862834707ffffff,86283470fffffff,862834717ffffff,86283471fffffff,862834727ffffff,86283472fffffff,862834737ffffff + + CALL neo4jh3.tochildrenString('1234',1) yield value return value; + "-1" + + CALL neo4jh3. tochildrenString('85283473fffffff',-1) yield value return value; + "-2" + +## Experimental - Added in version 5.15.0 + +## neo4jh3.writeH3ToDB( ListOfCells, Neo4j Label, Neo4j Property, Transaction Size ) +Writes the H3 indexes to the Neo4j database using a user provided Label and Property. + +### Syntax +CALL neo4jh3.writeH3ToDB(listCells, strLabel, strProperty, txSize) yield value return value; + +### Arguments +* listCells: A LIST of LONG values representing an H3 cell ID. +* strLabel: A STRING indicating what Neo4j Label will be applied to the nodes. +* strProperty: A STRING indicating what Neo4j Property will be applied to the nodes. +* txSize: A LONG indicating the number of nodes to create in each transaction. + +### Returns +A STRING indicating completion. + +### Error conditions +If the strLabel or strProperty is empty, the procedure returns "-5" + +### Example + call neo4jh3.polygonToCells(value.Geometry,[],9,'lonlat') yield value as h3 + with collect(h3) as ch3 + call neo4jh3.writeH3ToDB(ch3,'Hex','hexAddress9') yield value return value; + "Finished" + + call neo4jh3.polygonToCells(value.Geometry,[],9,'lonlat') yield value as h3 + with collect(h3) as ch3 + call neo4jh3.writeH3ToDB(ch3,'','') yield value return value; + "-5" + +## neo4jh3.writeH3ToDBString( ListOfCells, Neo4j Label, Neo4j Property, Transaction Size ) +Writes the H3 indexes to the Neo4j database using a user provided Label and Property. + +### Syntax +CALL neo4jh3.writeH3ToDBString(listCells, strLabel, strProperty, txSize) yield value return value; + +### Arguments +* listCells: A LIST of STRING values representing an H3 cell ID. +* strLabel: A STRING indicating what Neo4j Label will be applied to the nodes. +* strProperty: A STRING indicating what Neo4j Property will be applied to the nodes. +* txSize: A LONG indicating the number of nodes to create in each transaction. + +### Returns +A STRING indicating completion. + +### Error conditions +If the strLabel or strProperty is empty, the procedure returns "-5" + +### Example + call neo4jh3.polygonToCellsString(value.Geometry,[],9,'lonlat') yield value as h3 + with collect(h3) as ch3 + call neo4jh3.writeH3ToDBString(ch3,'Hex','hexAddress9') yield value return value; + "Finished" + + call neo4jh3.polygonToCellsString(value.Geometry,[],9,'lonlat') yield value as h3 + with collect(h3) as ch3 + call neo4jh3.writeH3ToDBString(ch3,'','') yield value return value; + "-5" + +## neo4jh3.writeH3NodesRelsToDB( From Node, ListOfCells, Neo4j Label, Neo4j Property, Relationships Type, Transaction Size ) +Writes the H3 index values to the Neo4j database as a node using a user provided Label and Property. +Connects the H3 index values to the From Node using the specified Relationship value. + +### Syntax +CALL neo4jh3.writeH3NodesRelsToDB(fromNode, listCells, strLabel, strProperty, relationshipType, txSize) yield value return value; + +### Arguments +* fromNode: An existing Node in the Neo4j database. +* listCells: A LIST of LONG values representing an H3 cell ID. +* strLabel: A STRING indicating what Neo4j Label will be applied to the nodes. +* strProperty: A STRING indicating what Neo4j Property will be applied to the nodes. +* relationshipType: A STRING indicating what relationship type will be used for the relationships. +* txSize: A LONG indicating the number of nodes to create in each transaction. + +### Returns +A STRING indicating completion. + +### Error conditions +If the strLabel or strProperty is empty, the procedure returns "-5" + +### Example + match (cs:CountySubDivision {cousubns:value.COUSUBNS}) + call neo4jh3.polygonToCells(value.Geometry,[],8,'lonlat') yield value as h3 + with cs, collect(h3) as ch3 + call neo4jh3.writeH3NodesRelsToDB(cs,ch3,'Hex','hexAddress8','HAS_HEXADDRESS', 10000) yield value return value; + "Success" + + match (cs:CountySubDivision {cousubns:value.COUSUBNS}) + call neo4jh3.polygonToCells(value.Geometry,[],8,'lonlat') yield value as h3 + with cs, collect(h3) as ch3 + call neo4jh3.writeH3NodesRelsToDB(cs,ch3,'Hex','','HAS_HEXADDRESS', 10000) yield value return value; + "-5" + +# neo4jh3.writeH3StringNodesRelsToDB( From Node, ListOfCells, Neo4j Label, Neo4j Property, Relationships Type, Transaction Size ) +Writes the H3 index values to the Neo4j database as a node using a user provided Label and Property. +Connects the H3 index values to the From Node using the specified Relationship value. + +### Syntax +CALL neo4jh3.writeH3StringNodesRelsToDB(fromNode, listCells, strLabel, strProperty, relationshipType, txSize) yield value return value; + +### Arguments +* fromNode: An existing Node in the Neo4j database. +* listCells: A LIST of STRING values representing an H3 cell ID. +* strLabel: A STRING indicating what Neo4j Label will be applied to the nodes. +* strProperty: A STRING indicating what Neo4j Property will be applied to the nodes. +* relationshipType: A STRING indicating what relationship type will be used for the relationships. +* txSize: A LONG indicating the number of nodes to create in each transaction. + +### Returns +A STRING indicating completion. + +### Error conditions +If the strLabel or strProperty is empty, the procedure returns "-5" + +### Example + match (cs:CountySubDivision {cousubns:value.COUSUBNS}) + call neo4jh3.polygonToCells(value.Geometry,[],8,'lonlat') yield value as h3 + with cs, collect(h3) as ch3 + call neo4jh3.writeH3StringNodesRelsToDB(cs,ch3,'Hex','hexAddress8','HAS_HEXADDRESS', 10000) yield value return value; + "Success" + + match (cs:CountySubDivision {cousubns:value.COUSUBNS}) + call neo4jh3.polygonToCells(value.Geometry,[],8,'lonlat') yield value as h3 + with cs, collect(h3) as ch3 + call neo4jh3.writeH3StringNodesRelsToDB(cs,ch3,'Hex','','HAS_HEXADDRESS', 10000) yield value return value; + "-5" + +## Error Codes +* -1 or "-1" : Invalid H3 Address +* -2 or "-2" : Invalid Resolution +* -3 or "-3" : Invalid Latitude +* -4 or "-4" : Invalid Longitude +* -5 or "-5" : Empty Label and/or Property diff --git a/README.md b/README.md index d42a84a..07226fc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Neo4j H3 Library This library provides a set of H3 functions and procedures for Neo4j 5. - H3 is a hexagonal hierarchical geospatial indexing system (https://h3geo.org) This library uses the H3 api which can be found at https://h3geo.org/docs/api/indexing @@ -13,22 +12,22 @@ project, simply package the project with maven: mvn clean package -This will produce a jar-file, `neo4jh3-5.19.1.jar`, +This will produce a jar-file, `neo4jh3-5.25.1.jar`, that can be copied to the `plugins` directory of your Neo4j instance. - cp target/neo4jh3-5.19.1.jar neo4j-enterprise-5.x.0/plugins/. + cp target/neo4jh3-5.25.1.jar neo4j-enterprise-5.x.0/plugins/. Edit your Neo4j/conf/neo4j.conf file by adding this line: - dbms.security.procedures.unrestricted=apoc.*,gds.*,com.neo4jh3.* - dbms.security.procedures.allowlist=apoc.*,gds.*,com.neo4jh3.* + dbms.security.procedures.unrestricted=apoc.*,gds.*,com.neo4jh3.*,neo4jh3.* + dbms.security.procedures.allowlist=apoc.*,gds.*,com.neo4jh3.*,neo4jh3.* - (Re)start Neo4j # Documentation Refer to the Documentation.md file for detailed documentation on the functions / procedures. +The Documentation_525.md file contains documentation for the new naming convention. # Note The Neo4jH3 plugin requires the ability to write to the temp directory. If the temp directory configured with noexec, then you need to update the neo4j.conf with these two lines: diff --git a/pom.xml b/pom.xml index 0bac2c0..bb3b0ae 100644 --- a/pom.xml +++ b/pom.xml @@ -6,10 +6,10 @@ com.neo4jh3 neo4jh3 - 5.23.0 + 5.25.1 - 5.23.0 + 5.25.1 3.13.0 4.1.1 4.1 diff --git a/src/main/java/com/neo4jh3/uber/Neo4jH3.java b/src/main/java/com/neo4jh3/uber/Neo4jH3.java new file mode 100644 index 0000000..5594ccd --- /dev/null +++ b/src/main/java/com/neo4jh3/uber/Neo4jH3.java @@ -0,0 +1,3240 @@ +package com.neo4jh3.uber; + +import com.uber.h3core.H3Core; +import com.uber.h3core.LengthUnit; +import com.uber.h3core.util.LatLng; + +import mil.nga.sf.Geometry; +import mil.nga.sf.Point; +import mil.nga.sf.geojson.FeatureConverter; +import mil.nga.sf.wkb.GeometryWriter; +import mil.nga.sf.wkt.GeometryReader; + +import org.apache.commons.math3.util.Precision; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Label; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.Relationship; +import org.neo4j.graphdb.RelationshipType; +import org.neo4j.graphdb.Transaction; +import org.neo4j.procedure.*; +import org.neo4j.procedure.builtin.BuiltInDbmsProcedures.StringResult; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class Neo4jH3 { + @Context + public GraphDatabaseService db; + + @Context + public Transaction tx; + + private final static int DEFAULT_H3_RESOLUTION = 9; + private final static String NEO4J_H3_VERSION = "5.23.0"; + + private static H3Core h3 = null; + + static { + try { + h3 = H3Core.newInstance(); + } catch (IOException e) { + // TODO: switch to logging api + System.err.println("failed to initialize H3Core"); + e.printStackTrace(); + } + } + + @UserFunction(name = "neo4jh3.h3Validate") + @Description("neo4jh3.h3Validate(hexAddress) - validate a long hex Address.") + public Long h3Validate( + @Name("hexAddress") Long hexAddress) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + return hexAddress; + } else { + // throw new RuntimeException("invalid h3 resolution"); + return -1L; + } + } catch (NumberFormatException nfe) { + // throw new RuntimeException("invalid h3 resolution"); + return -1L; + } + + } + + @UserFunction(name = "neo4jh3.h3ValidateString") + @Description("neo4jh3.h3ValidateString(hexAddress) - validate a string hex Address.") + public String h3ValidateString( + @Name("hexAddress") String hexAddress) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + try { + if (h3.isValidCell(hexAddress)){ + return hexAddress; + } else { + // throw new RuntimeException("invalid h3 resolution"); + return "-1"; + } + } catch (NumberFormatException nfe) { + // throw new RuntimeException("invalid h3 resolution"); + return "-1"; + } + } + + @SuppressWarnings("null") + @UserFunction(name = "neo4jh3.h3HexAddress") + @Description("neo4jh3.h3HexAddress(latitude, longitude, resolution) - return the hex address for a given latitude.") + public Long h3HexAddress( + @Name("latitude") Double latValue, + @Name("longitude") Double longValue, + @Name("resolution") Long h3Res) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + Long returnValue = 0L; + int validLatLon = 1; + if (latValue == null || longValue == null) { + returnValue = -1L; + } + + if ( latValue > 90 || latValue < -90 ){ + validLatLon = 0; + returnValue = -3L; + } + + if ( longValue > 180 || longValue < -180 ){ + validLatLon = 0; + returnValue = -4L; + } + + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (validLatLon > 0){ + if (h3Resolution > 0 && h3Resolution <= 15) { + returnValue = h3.latLngToCell(latValue, longValue, h3Resolution); + } else { + returnValue = -2L; + } + } + return returnValue; + } + + @SuppressWarnings("null") + @UserFunction(name = "neo4jh3.h3HexAddressString") + @Description("neo4jh3.h3HexAddressString(latitude, longitude, resolution) - return the hex address for a given latitude.") + public String h3HexAddressString( + @Name("latitude") Double latValue, + @Name("longitude") Double longValue, + @Name("resolution") Long h3Res) { + String returnString = ""; + int validLatLon = 1; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + if (latValue == null || longValue == null) { + returnString = "NULL"; + } + + if ( latValue > 90 || latValue < -90 ){ + validLatLon = 0; + returnString = "-3"; + } + + if ( longValue > 180 || longValue < -180 ){ + validLatLon = 0; + returnString = "-4"; + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (validLatLon > 0){ + if (h3Resolution > 0 && h3Resolution <= 15) { + returnString = h3.latLngToCellAddress(latValue, longValue, h3Resolution); + } else { + returnString = "-2"; + } + } + return returnString; + } + + + + /** + * @param longHex + * @return + */ + @UserFunction(name = "neo4jh3.h3tostring") + @Description("neo4jh3.h3tostring(longHex) - return the string value of a long hex address.") + public String h3tostringFunction( + @Name("longHex") Long longHex) { + String returnString = ""; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(longHex)){ + returnString = h3.h3ToString(longHex); + } else { + returnString = "-1"; + } + return returnString; + } catch (Exception e) { + returnString = "-1"; + return returnString; + } + } + + @UserFunction(name = "neo4jh3.stringToH3") + @Description("neo4jh3.stringToH3(longHex) - return the string value of a long hex address.") + public Long stringToH3Function( + @Name("strHexAddress") String strHexAddress) { + Long returnString = 0L; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(strHexAddress)){ + returnString = h3.stringToH3(strHexAddress); + } else { + returnString = -1L; + } + return returnString; + } catch (Exception e) { + returnString = -1L; + return returnString; + } + } + + @UserFunction(name = "neo4jh3.h3ResolutionString") + @Description("neo4jh3.h3ResolutionString(longHex) - return the resolution of a string hex address.") + public Long h3ResolutionString( + @Name("strHexAddress") String strHexAddress) { + Long returnString = 0L; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(strHexAddress)){ + returnString = Long.valueOf(h3.getResolution(strHexAddress)); + } else { + returnString = -1L; + } + return returnString; + } catch (Exception e) { + returnString = -1L; + return returnString; + } + } + + @UserFunction(name = "neo4jh3.h3Resolution") + @Description("neo4jh3.h3Resolution(longHex) - return the string value of a long hex address.") + public Long h3Resolution( + @Name("hexAddress") Long hexAddress) { + Long returnString = 0L; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + returnString = Long.valueOf(h3.getResolution(hexAddress)); + } else { + returnString = -1L; + } + return returnString; + } catch (Exception e) { + returnString = -1L; + return returnString; + } + } + + + @UserFunction(name = "neo4jh3.latlongash3String") + @Description("neo4jh3.latlongash3String(latitude, longitude, resolution) - return the hex address for a given latitude.") + public String latlongash3String( + @Name("latitude") Double latValue, + @Name("longitude") Double longValue, + @Name("resolution") Long h3Res) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + if (latValue == null || longValue == null) { + throw new RuntimeException("invalid lat or long values"); + } + + String returnString = ""; + int validLatLon = 1; + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + if (latValue == null || longValue == null) { + returnString = "-5"; + } + + if ( latValue>90 || latValue<-90 ){ + validLatLon = 0; + returnString = "-3"; + } + + if ( longValue>180 || longValue<-180 ){ + validLatLon = 0; + returnString = "-4"; + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (validLatLon > 0){ + if (h3Resolution > 0 && h3Resolution <= 15) { + returnString = h3.latLngToCellAddress(latValue, longValue, h3Resolution); + } else { + returnString = "-2"; + } + } + return returnString; + } + + @SuppressWarnings("null") + @UserFunction(name = "neo4jh3.latlongash3") + @Description("neo4jh3.latlongash3(latitude, longitude, resolution) - return the hex address for a given latitude.") + public Long latlongash3( + @Name("latitude") Double latValue, + @Name("longitude") Double longValue, + @Name("resolution") Long h3Res) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + Long returnValue = 0L; + int validLatLon = 1; + if (latValue == null || longValue == null) { + returnValue = -1L; + } + + if ( latValue>90 || latValue<-90 ){ + validLatLon = 0; + returnValue = -3L; + } + + if ( longValue>180 || longValue<-180 ){ + validLatLon = 0; + returnValue = -4L; + } + + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (validLatLon > 0){ + if (h3Resolution > 0 && h3Resolution <= 15) { + returnValue = h3.latLngToCell(latValue, longValue, h3Resolution); + } else { + returnValue = -2L; + } + } + return returnValue; + } + + @UserFunction(name = "neo4jh3.h3RingsForDistance") + @Description("neo4jh3.h3RingsForDistance(resolution, distance) - return the number of rings for a given distance.") + public Long h3RingsForDistance( + @Name("h3Res") Long h3Res, + @Name("distanceValue") Long distanceValue) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + if (distanceValue == null) { + throw new RuntimeException("invalid distance value"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 0 && h3Resolution <= 15) { + final double hexLength = h3.getHexagonEdgeLengthAvg(h3Resolution, LengthUnit.km); + final Double numberHexRings = Math.ceil(distanceValue / hexLength); + return numberHexRings.longValue(); + } + throw new RuntimeException("invalid h3 resolution"); + } + + @UserFunction(name = "neo4jh3.gridDistance") + @Description("neo4jh3.gridDistance(fromHexAddress, toHexAddress) - Provides the distance in grid cells between the two indexes.") + public Long gridDistance( + @Name("fromHexAddress") Long fromHexAddress, + @Name("toHexAddress") Long toHexAddress) { + + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + Long returnValue = 0L; + if (fromHexAddress == null || toHexAddress == null) { + throw new RuntimeException("invalid from HexAddress or to HexAddress"); + } + if (h3.isValidCell(fromHexAddress) && h3.isValidCell(toHexAddress)){ + returnValue = h3.gridDistance(fromHexAddress, toHexAddress); + } else { + if (!h3.isValidCell(fromHexAddress) || !h3.isValidCell(toHexAddress)){ + returnValue = -1L; + } + } + + return returnValue; + } + + @UserFunction(name = "neo4jh3.gridDistanceString") + @Description("neo4jh3.gridDistanceString(fromHexAddress, toHexAddress) - Provides the distance in grid cells between the two indexes.") + public double gridDistanceString( + @Name("fromHexAddress") String fromHexAddress, + @Name("toHexAddress") String toHexAddress) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + if (fromHexAddress == null || toHexAddress == null) { + throw new RuntimeException("invalid from HexAddress or to HexAddress"); + } + + Long returnValue = 0L; + if (fromHexAddress == null || toHexAddress == null) { + throw new RuntimeException("invalid from HexAddress or to HexAddress"); + } + if (h3.isValidCell(fromHexAddress) && h3.isValidCell(toHexAddress)){ + returnValue = h3.gridDistance(fromHexAddress, toHexAddress); + } else { + if (!h3.isValidCell(fromHexAddress) || !h3.isValidCell(toHexAddress)){ + returnValue = -1L; + } + } + return returnValue; + } + + @UserFunction(name = "neo4jh3.toparent") + @Description("CALL neo4jh3.toparent(hexAddress, h3Resolution)") + public Long toparent(@Name("hexAddress") Long hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + Long returnValue = 0L; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + int h3MaxRes = h3.getResolution(hexAddress); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + if (h3Resolution > 0 && h3Resolution <= h3MaxRes && h3.isValidCell(hexAddress)) { + returnValue = h3.cellToParent(hexAddress, h3Resolution); + } else { + if (h3Resolution < 0 || h3Resolution > h3MaxRes){ + returnValue = -2L; + } + if (!h3.isValidCell(hexAddress)){ + returnValue = -1L; + } + } + return returnValue; + } + + @UserFunction(name = "neo4jh3.toparentString") + @Description("CALL neo4jh3.toparentString(hexAddress, h3Resolution)") + public String toparentString(@Name("hexAddress") String hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + String returnValue = ""; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + int h3MaxRes = h3.getResolution(hexAddress); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 0 && h3Resolution <= h3MaxRes && h3.isValidCell(hexAddress)) { + returnValue = h3.cellToParentAddress(hexAddress, h3Resolution); + } else { + if (h3Resolution < 0 || h3Resolution > h3MaxRes){ + returnValue = "-2"; + } + if (!h3.isValidCell(hexAddress)){ + returnValue = "-1"; + } + } + return returnValue; + } + + @UserFunction(name = "neo4jh3.cellToLatLng") + @Description("CALL neo4jh3.cellToLatLng(hexAddress)") + public String cellToLatLng(@Name("hexAddress") Long hexAddress) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + if (h3.isValidCell(hexAddress)){ + LatLng tmpGeoCoord = h3.cellToLatLng(hexAddress); + return String.valueOf(Precision.round(tmpGeoCoord.lat,6)) + "," + String.valueOf(Precision.round(tmpGeoCoord.lng,6)); + } else { + return "-1"; + } + } + + @UserFunction(name = "neo4jh3.cellToLatLngString") + @Description("CALL neo4jh3.cellToLatLngString(hexAddress)") + public String cellToLatLngString(@Name("hexAddress") String hexAddress) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + if (h3.isValidCell(hexAddress)){ + LatLng tmpGeoCoord = h3.cellToLatLng(hexAddress); + return String.valueOf(Precision.round(tmpGeoCoord.lat,6)) + "," + String.valueOf(Precision.round(tmpGeoCoord.lng,6)); + } else { + return "-1"; + } + } + + @SuppressWarnings("unused") + @UserFunction(name = "neo4jh3.distanceBetweenHexes") + @Description("CALL neo4jh3.distanceBetweenHexes(fromHexAddress, toHexAddress)") + public double distanceBetweenHexes(@Name("fromHexAddress") Long fromHexAddress, @Name("toHexAddress") Long toHexAddress) throws InterruptedException { + double returnDistance = 0.0; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null || toHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + if (h3.isValidCell(fromHexAddress) && h3.isValidCell(toHexAddress)){ + LatLng fromGeoCoord = h3.cellToLatLng(fromHexAddress); + LatLng toGeoCoord = h3.cellToLatLng(toHexAddress); + return returnDistance = Precision.round(h3.greatCircleDistance(fromGeoCoord, toGeoCoord, LengthUnit.km),6); + } else { + return -1.0; + } + } + + @SuppressWarnings("unused") + @UserFunction(name = "neo4jh3.distanceBetweenHexesString") + @Description("CALL neo4jh3.distanceBetweenHexesString(fromHexAddress, toHexAddress)") + public double distanceBetweenHexesString(@Name("fromHexAddress") String fromHexAddress, @Name("toHexAddress") String toHexAddress) throws InterruptedException { + double returnDistance = 0.0; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null || toHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + if (h3.isValidCell(fromHexAddress) && h3.isValidCell(fromHexAddress)){ + LatLng fromGeoCoord = h3.cellToLatLng(fromHexAddress); + LatLng toGeoCoord = h3.cellToLatLng(toHexAddress); + return returnDistance = Precision.round(h3.greatCircleDistance(fromGeoCoord, toGeoCoord, LengthUnit.km),6); + } else { + return -1.0; + } + } + + @UserFunction(name = "neo4jh3.minChild") + @Description("CALL neo4jh3.minChild(hexAddress, h3Resolution)") + public Long minChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + int h3CurRes = h3.getResolution(fromHexAddress); + + if (h3.isValidCell(fromHexAddress)){ + if (h3Resolution > h3CurRes && h3Resolution <= 15) { + Long minChild = 648302213769948598L; + Long curChild = 0L; + List listChildren = h3.cellToChildren(fromHexAddress, h3Resolution); + ListIterator + iterator = listChildren.listIterator(); + while (iterator.hasNext()) { + curChild = iterator.next(); + if (curChild < minChild){ + minChild = curChild; + } + } + return minChild; + } else { + return -2L; + } + } else { + return -1L; + } + } + + @UserFunction(name = "neo4jh3.minChildString") + @Description("CALL neo4jh3.minChildString(hexAddress, h3Resolution)") + public String minChildString(@Name("fromHexAddress") String fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + int h3CurRes = h3.getResolution(fromHexAddress); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3.isValidCell(fromHexAddress)){ + if (h3Resolution > h3CurRes && h3Resolution <= 15) { + String minChild = "8ff3b6db6db6db6"; + String curChild = ""; + List listChildren = h3.cellToChildren(fromHexAddress, h3Resolution); + ListIterator + iterator = listChildren.listIterator(); + while (iterator.hasNext()) { + curChild = iterator.next(); + if (curChild.compareTo(minChild) < 0){ + minChild = curChild; + } + } + return minChild; + } else { + return "-2"; + } + } else { + return "-1"; + } + } + + @UserFunction(name = "neo4jh3.maxChild") + @Description("CALL neo4jh3.maxChild(hexAddress, h3Resolution)") + public Long maxChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + int h3CurRes = h3.getResolution(fromHexAddress); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3.isValidCell(fromHexAddress)){ + if (h3Resolution > h3CurRes && h3Resolution <= 15) { + Long maxChild = 0L; + Long curChild = 0L; + List listChildren = h3.cellToChildren(fromHexAddress, h3Resolution); + ListIterator + iterator = listChildren.listIterator(); + while (iterator.hasNext()) { + curChild = iterator.next(); + //System.out.println(curChild); + if (curChild > maxChild){ + maxChild = curChild; + } + } + return maxChild; + } else { + return -2L; + } + } else { + return -1L; + } + } + + @UserFunction(name = "neo4jh3.maxChildString") + @Description("CALL neo4jh3.maxChildString(hexAddress, h3Resolution)") + public String maxChild(@Name("fromHexAddress") String fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (fromHexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + int h3CurRes = h3.getResolution(fromHexAddress); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3.isValidCell(fromHexAddress)){ + if (h3Resolution > h3CurRes && h3Resolution <= 15) { + String maxChild = "8001fffffffffff"; + String curChild = ""; + List listChildren = h3.cellToChildren(fromHexAddress, h3Resolution); + ListIterator + iterator = listChildren.listIterator(); + while (iterator.hasNext()) { + curChild = iterator.next(); + //System.out.println(curChild); + if (curChild.compareTo(maxChild) > 0){ + maxChild = curChild; + } + } + return maxChild; + } else { + return "-2"; + } + } else { + return "-1"; + } + } + + @UserFunction(name = "neo4jh3.angleBetweenPoints") + @Description("CALL neo4jh3.angleBetweenPoints(latitude1, longitude1, latitude2, longitude2)") + public Double angleBetweenPoints( + @Name("latitude1") Double lat1Value, + @Name("longitude1") Double lon1Value, + @Name("latitude2") Double lat2Value, + @Name("longitude2") Double lon2Value + ) throws InterruptedException { + Double returnValue = 0.0; + int hasError=0; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if ( lat1Value>90 || lat2Value<-90 || lat1Value>90 || lat2Value<-90 ){ + returnValue = -1.0; + hasError = 1; + } + + if ( lon1Value>180 || lon1Value<-180 || lon2Value>180 || lon2Value<-180 ){ + returnValue = -2.0; + hasError = 1; + } + if (hasError < 1){ + return Precision.round(angleDistance(lat1Value,lon1Value,lat2Value,lon2Value),6); + } else { + return returnValue; + } + } + + // Geography Functions + @UserFunction(name = "neo4jh3.pointash3") + @Description("neo4jh3.pointash3(wktString, resolution, latlon order) - Loads a WKT POINT and returns H3 LONG values.") + public Long pointash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + Long h3Address = 0L; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + Geometry geometry = GeometryReader.readGeometry(wktString); + + if (latlonorder.equalsIgnoreCase("latlon")){ + if (geometry.getGeometryType().toString().equalsIgnoreCase("Point")){ + h3Address=h3.latLngToCell(geometry.getEnvelope().getMinX(), geometry.getEnvelope().getMinY(), h3Resolution); + } + } else { + if (geometry.getGeometryType().toString().equalsIgnoreCase("Point")){ + h3Address=h3.latLngToCell(geometry.getEnvelope().getMinY(), geometry.getEnvelope().getMinX(), h3Resolution); + } + } + } else { + h3Address = -2L; + } + } catch (Exception e) { + //System.out.println(e); + h3Address = -1L; + //e.printStackTrace(); + } + return h3Address; + } + @UserFunction(name = "neo4jh3.pointash3String") + @Description("neo4jh3.pointash3String(wktString, resolution, latlon order) - Loads a WKT POINT and returns H3 String values.") + public String pointash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + String h3Address = ""; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + Geometry geometry = GeometryReader.readGeometry(wktString); + if (latlonorder.equalsIgnoreCase("latlon")){ + if (geometry.getGeometryType().toString().equalsIgnoreCase("Point")){ + h3Address=h3.latLngToCellAddress(geometry.getEnvelope().getMinX(), geometry.getEnvelope().getMinY(), h3Resolution); + } + } else { + if (geometry.getGeometryType().toString().equalsIgnoreCase("Point")){ + h3Address=h3.latLngToCellAddress(geometry.getEnvelope().getMinY(), geometry.getEnvelope().getMinX(), h3Resolution); + } + } + } else { + h3Address = "-2"; + } + } catch (Exception e) { + //System.out.println(e); + h3Address = "-1"; + //e.printStackTrace(); + } + return h3Address; + } + + @UserFunction(name = "neo4jh3.version") + @Description("neo4jh3.version() - Returns the version of the plugin.") + public String neo4jH3Version() throws InterruptedException + { + String h3Version = NEO4J_H3_VERSION; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + return h3Version; + } + + // Procedures + + @Procedure(name = "neo4jh3.lineash3", mode = Mode.READ) + @Description("neo4jh3.lineash3(wktString, resolution, latlonorder) - Loads a WKT LINESTRING and returns H3 Long values.") + public Stream lineash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + Long h3StartAddress = 0L; + Long h3MidAddress = 0L; + Long h3EndAddress = 0L; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + if (latlonorder.isBlank()){ + latlonorder = "latlon"; + } + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("LINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + if (latlonorder.equalsIgnoreCase("latlon")){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); + } else { + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[1]); + fromLon = Double.valueOf(lonlat.split("\\s+")[0]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[1]); + toLon =Double.valueOf(lonlat.split("\\s+")[0]); + } + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCell(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCell(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCell(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + + } + + } + } + } else { + listh3Address = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + listh3Address = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3LongAddress::of); + } + + // New Geo Procedures + @Procedure(name = "neo4jh3.lineash3String", mode = Mode.READ) + @Description("neo4jh3.lineash3String(wktString, resolution, latlonorder) - Loads a WKT LINESTRING and returns H3 String values.") + public Stream lineash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + + { + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + String h3StartAddress = ""; + String h3MidAddress = ""; + String h3EndAddress = ""; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + if (latlonorder.isBlank()){ + latlonorder = "latlon"; + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("LINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + if (latlonorder.equalsIgnoreCase("latlon")){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); + } else { + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[1]); + fromLon = Double.valueOf(lonlat.split("\\s+")[0]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[1]); + toLon =Double.valueOf(lonlat.split("\\s+")[0]); + } + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCellAddress(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCellAddress(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCellAddress(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + //listh3Address = Collections.singletonList("-1"); + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + //listh3Address = Collections.singletonList("-1"); + } + } + } + } else { + listh3Address = Collections.singletonList("-2"); + } + } catch (Exception e) { + //System.out.println(e); + listh3Address = Collections.singletonList("-1"); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3StringAddress::of); + } + + @Procedure(name = "neo4jh3.multilineash3", mode = Mode.READ) + @Description("neo4jh3.multilineash3(wktString, resolution, latlonorder) - Provides the distance in grid cells between the two indexes.") + public Stream multilineash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + Long h3StartAddress = 0L; + Long h3MidAddress = 0L; + Long h3EndAddress = 0L; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + if (latlonorder.isBlank()){ + latlonorder = "latlon"; + } + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("MULTILINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + if (latlonorder.equalsIgnoreCase("latlon")){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); + } else { + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[1]); + fromLon = Double.valueOf(lonlat.split("\\s+")[0]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[1]); + toLon =Double.valueOf(lonlat.split("\\s+")[0]); + } + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCell(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCell(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCell(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + + } + + } + } + } else { + listh3Address = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + listh3Address = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3LongAddress::of); + } + + // New Geo Procedures + @Procedure(name = "neo4jh3.multilineash3String", mode = Mode.READ) + @Description("neo4jh3.multilineash3String(wktString, resolution, latlonorder) - Provides the distance in grid cells between the two indexes.") + public Stream multilineash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + String h3StartAddress = ""; + String h3MidAddress = ""; + String h3EndAddress = ""; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + if (latlonorder.isBlank()){ + latlonorder = "latlon"; + } + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("MULTILINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + if (latlonorder.equalsIgnoreCase("latlon")){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); + } else { + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[1]); + fromLon = Double.valueOf(lonlat.split("\\s+")[0]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[1]); + toLon =Double.valueOf(lonlat.split("\\s+")[0]); + } + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCellAddress(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCellAddress(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCellAddress(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + + } + + } + } + } else { + listh3Address = Collections.singletonList("-2"); + + } + } catch (Exception e) { + //System.out.println(e); + listh3Address = Collections.singletonList("-1"); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3StringAddress::of); + } + + // TO DO + // Add MultiPolygon Support for WKT file + // Example: https://www.georgia811.com/wp-content/uploads/2022/06/Well_Known_Text.pdf + // Added 4 June 2024 + @Procedure(name = "neo4jh3.polygonash3", mode = Mode.READ) + @Description("neo4jh3.polygonash3(wktString, resolution) - Returns the hex addresses as a long from a WKT Polygon string.") + public Stream polygonash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) throws InterruptedException + { + List listh3Address = new ArrayList(); + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("POLYGON", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] lonlatPairs = mls.split(","); + for (int i = 0; i < lonlatPairs.length; i++) { + LatLng tmpGeoCoord = null; + tmpGeoCoord = returnLngLat(lonlatPairs[i]); + hexPoints.add(tmpGeoCoord); + } + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + listh3Address = h3.polygonToCells(hexPoints, holesList, h3Resolution); + } else { + listh3Address = h3.polygonToCells(hexPoints, null, h3Resolution); + } + + } else { + listh3Address = Collections.singletonList(-2L); + + } + } catch (Exception e) { + System.out.println(e); + listh3Address = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3LongAddress::of); + } + + @Procedure(name = "neo4jh3.polygonash3String", mode = Mode.READ) + @Description("neo4jh3.polygonash3String(wktString, resolution) - Returns the hex addresses as a String from a WKT Polygon string") + public Stream polygonash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) throws InterruptedException + { + List listh3Address = new ArrayList(); + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("POLYGON", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + //System.out.println(mls); + String[] lonlatPairs = mls.split(","); + for (int i = 0; i < lonlatPairs.length; i++) { + LatLng tmpGeoCoord = null; + tmpGeoCoord = returnLngLat(lonlatPairs[i]); + hexPoints.add(tmpGeoCoord); + } + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + listh3Address = h3.polygonToCellAddresses(hexPoints, holesList, h3Resolution); + } else { + listh3Address = h3.polygonToCellAddresses(hexPoints, null, h3Resolution); + } + + } else { + listh3Address = Collections.singletonList("-2"); + + } + } catch (Exception e) { + System.out.println(e); + listh3Address = Collections.singletonList("-1"); + //e.printStackTrace(); + } + return listh3Address.stream().map(H3StringAddress::of); + } + + // Added June 2024 + @Procedure(name = "neo4jh3.multipolygonash3", mode = Mode.READ) + @Description("neo4jh3.multipolygonash3(wktString, resolution) - Returns the hex addresses as a long from a WKT MultiPolygon string.") + public Stream multipolygonash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) throws InterruptedException + { + List listh3Address = new ArrayList(); + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + String mls = ""; + String mps = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("MULTIPOLYGON", ""); + String[] polygonStrings = mls.split("\\)\\),\\(\\("); + // Loop through each polygon and create Hex Addresses + for (int i=0; i multipolygonash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) throws InterruptedException + { + List listh3Address = new ArrayList(); + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + String mls = ""; + String mps = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + mls = wktString.replace("MULTIPOLYGON", ""); + String[] polygonStrings = mls.split("\\)\\),\\(\\("); + // Loop through each polygon and create Hex Addresses + for (int i=0; i hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + geoJsonString = mil.nga.sf.wkt.GeometryWriter.writeGeometry(polygon); + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.boundaryaswktString") + @Description("neo4jh3.boundaryaswktString(hexAddress) - Returns the boundary of a hex address in WKT format.") + public String boundaryaswktString( + @Name("hexAddress") String hexAddress) throws InterruptedException + { + String geoJsonString = ""; + List hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + geoJsonString = mil.nga.sf.wkt.GeometryWriter.writeGeometry(polygon); + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.boundaryaswkb") + @Description("neo4jh3.boundaryaswkb(hexAddress) - Returns the boundary of a hex address in WKB format.") + public String boundaryaswkb( + @Name("hexAddress") Long hexAddress) throws InterruptedException + { + String geoJsonString = ""; + List hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + byte[] bytes = GeometryWriter.writeGeometry(polygon); + for (byte bi : bytes) { + geoJsonString += String.format("%02X", bi); + } + + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.boundaryaswkbString") + @Description("neo4jh3.boundaryaswkbString(hexAddress) -- Returns the boundary of a hex address in WKB format.") + public String boundaryaswkbString( + @Name("hexAddress") String hexAddress) throws InterruptedException + { + String geoJsonString = ""; + List hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + byte[] bytes = GeometryWriter.writeGeometry(polygon); + for (byte bi : bytes) { + geoJsonString += String.format("%02X", bi); + } + + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.centerasgeojson") + @Description("neo4jh3.centerasgeojson(hexAddress) - Returns the center of a hex address as a GeoJson string.") + public String centerasgeojson( + @Name("hexAddress") Long hexAddress) throws InterruptedException + { + String geoJsonString = ""; + LatLng centerPoint = null; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + centerPoint = h3.cellToLatLng(hexAddress); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point = new Point(false, false, lng, lat); + geoJsonString = FeatureConverter.toStringValue(point); + + } else { + geoJsonString = "-1"; + } + + } catch (Exception e) { + geoJsonString = "Error getting value"; + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.centerasgeojsonString") + @Description("neo4jh3.centerasgeojsonString(hexAddress) - Returns the center of a hex address as a GeoJson string.") + public String centerasgeojsonString( + @Name("hexAddress") String hexAddress) throws InterruptedException + { + String geoJsonString = ""; + LatLng centerPoint = null; + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + centerPoint = h3.cellToLatLng(hexAddress); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point = new Point(false, false, lng, lat); + geoJsonString = FeatureConverter.toStringValue(point); + } else { + geoJsonString = "-1"; + } + + } catch (Exception e) { + geoJsonString = "Error getting value"; + } + return geoJsonString; + } + + + @UserFunction(name = "neo4jh3.boundaryasgeojson") + @Description("neo4jh3.boundaryasgeojson(hexAddress) - Returns the boundary of a hex address as a GeoJson string.") + public String boundaryasgeojson( + @Name("hexAddress") Long hexAddress) throws InterruptedException + { + String geoJsonString = ""; + List hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + geoJsonString = FeatureConverter.toStringValue(polygon); + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.boundaryasgeojsonString") + @Description("neo4jh3.boundaryasgeojsonString(hexAddress) - Returns the boundary of a hex address as a GeoJson string.") + public String boundaryasgeojsonString( + @Name("hexAddress") String hexAddress) throws InterruptedException + { + String geoJsonString = ""; + List hexPoints = new ArrayList<>(); + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + try { + if (h3.isValidCell(hexAddress)){ + hexPoints = h3.cellToBoundary(hexAddress); + // Iterating ArrayList using Iterator + Iterator it = hexPoints.iterator(); + int i = 0; + mil.nga.sf.LinearRing ring = new mil.nga.sf.LinearRing(false, false); + Point tpfirst = new Point(); + while (it.hasNext()){ + LatLng thisHex = it.next(); + + if (i < 1){ + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + //ring.addPoint(tpfirst); + } + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); + ring.addPoint(tp); + i++; + } + ring.addPoint(tpfirst); + mil.nga.sf.Polygon polygon = new mil.nga.sf.Polygon(ring); + geoJsonString = FeatureConverter.toStringValue(polygon); + } else { + geoJsonString = "-1"; + } + } catch (Exception e) { + e.printStackTrace(); + } + return geoJsonString; + } + + @UserFunction(name = "neo4jh3.ispentagon") + @Description("neo4jh3.ispentagon(hexAddress) - is hexAddress a pentagon.") + public Boolean ispentagon( + @Name("hexAddress") Long hexAddress) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isPentagon(hexAddress)){ + return true; + } else { + // throw new RuntimeException("invalid h3 resolution"); + return false; + } + } catch (NumberFormatException nfe) { + // throw new RuntimeException("invalid h3 resolution"); + return false; + } + } + + @UserFunction(name = "neo4jh3.ispentagonString") + @Description("neo4jh3.ispentagonString(hexAddress) - is hexAddress a pentagon.") + public Boolean ispentagonString( + @Name("hexAddress") String hexAddress) { + if (h3 == null) { + throw new RuntimeException("h3 failed to initialize"); + } + + try { + if (h3.isPentagon(hexAddress)){ + return true; + } else { + // throw new RuntimeException("invalid h3 value"); + return false; + } + } catch (NumberFormatException nfe) { + // throw new RuntimeException("invalid h3 value"); + return false; + } + } + + /* Neo4j H3 Procedures */ + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.gridDisk", mode = Mode.READ) + @Description("CALL neo4jh3.gridDisk(hexAddress, ringSize) - Returns all H3 addresses around the hexAddress at the given ring size") + public Stream gridDisk(@Name("hexAddress") Long hexAddress, @Name("ringSize") Long ringSize) + throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null || ringSize == null) { + throw new InterruptedException("invalid arguments"); + } + + if (ringSize > 0 && h3.isValidCell(hexAddress)){ + List ringList = h3.gridDisk(hexAddress, ringSize.intValue()); + return ringList.stream().map(H3LongAddress::of); + } else { + List ringList = null; + if (ringSize < 0) { + ringList = Collections.singletonList( -2L ); + } + if (!h3.isValidCell(hexAddress)){ + ringList = Collections.singletonList( -1L ); + } + return ringList.stream().map(H3LongAddress::of); + } + } + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.gridDiskString", mode = Mode.READ) + @Description("CALL neo4jh3.gridDiskString(hexAddress, ringSize) - Returns all H3 addresses around the hexAddress at the given ring size") + public Stream gridDiskString(@Name("hexAddress") String hexAddress, @Name("ringSize") Long ringSize) + throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null || ringSize == null) { + throw new InterruptedException("invalid arguments"); + } + + //List ringList = Collections.emptyList(); + if (ringSize > 0 && h3.isValidCell(hexAddress)){ + List ringList = h3.gridDisk(hexAddress, ringSize.intValue()); + return ringList.stream().map(H3StringAddress::of); + } else { + List ringList = null; + if (ringSize < 0) { + ringList = Collections.singletonList("-2"); + } + if (!h3.isValidCell(hexAddress)){ + ringList = Collections.singletonList("-1"); + } + return ringList.stream().map(H3StringAddress::of); + } + } + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.tochildren", mode = Mode.READ) + @Description("CALL neo4jh3.tochildren(hexAddress, h3Resolution)") + public Stream tochildren(@Name("hexAddress") Long hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + int h3MaxRes = h3.getResolution(hexAddress); + + if (h3.isValidCell(hexAddress) && h3Resolution >= h3MaxRes && h3Resolution < 16){ + return h3.cellToChildren(hexAddress, h3Resolution).stream().map(H3LongAddress::of); + } else { + List ringList = null; + if (!h3.isValidCell(hexAddress)){ + ringList = Collections.singletonList(-1L); + } + if (h3Resolution < h3MaxRes){ + ringList = Collections.singletonList(-2L); + } + return ringList.stream().map(H3LongAddress::of); + } + } + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.tochildrenString", mode = Mode.READ) + @Description("CALL neo4jh3.tochildrenString(hexAddress, h3Resolution)") + public Stream tochildrenString(@Name("hexAddress") String hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + if (hexAddress == null) { + throw new InterruptedException("invalid hex address"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + int h3MaxRes = h3.getResolution(hexAddress); + + if (h3.isValidCell(hexAddress) && h3Resolution >= h3MaxRes && h3Resolution < 16){ + return h3.cellToChildren(hexAddress, h3Resolution).stream().map(H3StringAddress::of); + } else { + List ringList = null; + if (!h3.isValidCell(hexAddress)){ + ringList = Collections.singletonList("-1"); + } + if (h3Resolution < h3MaxRes){ + ringList = Collections.singletonList("-2"); + } + return ringList.stream().map(H3StringAddress::of); + } + } + +/* + * + * call neo4jh3.polygonToCellsTest(["37.7866,-122.3805","37.7198,-122.3544","37.7076,-122.5123","37.7835,-122.5247","37.8151,-122.4798"],[],7) yield value return value; + */ + @Procedure(name = "neo4jh3.polygonToCells", mode = Mode.READ) + @Description("CALL neo4jh3.polygonToCells(polyEdges, polyEdgeHoles, resolution, latlon order)") + public Stream polygonToCells(@Name("polyEdges") List polyEdges, @Name("polyEdgeHoles") List polyEdgeHoles, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + if (h3 == null) { + return Stream.empty(); + } + if (polyEdges == null || polyEdgeHoles == null) { + throw new InterruptedException("invalid arguments"); + } + + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution >= 1 && h3Resolution <= 15) { + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + List hexList; + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCells(hexPoints, holesList, h3Resolution); + } else { + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); + } + return hexList.stream().map(H3LongAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList(-2L); + return ringList.stream().map(H3LongAddress::of); + } + } + + /* + * + * call neo4jh3.polygonToCellsTest(["37.7866,-122.3805","37.7198,-122.3544","37.7076,-122.5123","37.7835,-122.5247","37.8151,-122.4798"],[],7) yield value return value; + */ + @Procedure(name = "neo4jh3.polygonToCellsString", mode = Mode.READ) + @Description("CALL neo4jh3.polygonToCellsString(polyEdges, polyEdgeHoles, resolution, latlon order)") + public Stream polygonToCellsString(@Name("polyEdges") List polyEdges, @Name("polyEdgeHoles") List polyEdgeHoles, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + if (h3 == null) { + return Stream.empty(); + } + if (polyEdges == null || polyEdgeHoles == null) { + throw new InterruptedException("invalid arguments"); + } + + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + if (h3Resolution >= 1 && h3Resolution <= 15) { + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + List hexList; + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCellAddresses(hexPoints, holesList, h3Resolution); + } else { + hexList = h3.polygonToCellAddresses(hexPoints, null, h3Resolution); + } + return hexList.stream().map(H3StringAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList("-2"); + return ringList.stream().map(H3StringAddress::of); + } + } + + @Procedure(name = "neo4jh3.polygonIntersection", mode = Mode.READ) + @Description("CALL neo4jh3.polygonIntersection(polyEdges, polyEdgeHoles, polyEdgesSecond, polyEdgeHolesSecond,resolution, latlon order)") + public Stream polygonIntersection(@Name("polyEdges") List polyEdges, @Name("polyEdgeHoles") List polyEdgeHoles, @Name("polyEdgesSecond") List polyEdgesSecond, @Name("polyEdgeHolesSecond") List polyEdgeHolesSecond, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + if (h3 == null) { + return Stream.empty(); + } + if (polyEdges == null || polyEdgeHoles == null || polyEdgesSecond == null || polyEdgeHolesSecond == null) { + throw new InterruptedException("invalid arguments"); + } + + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexPointsSecond = new ArrayList<>(); + List hexHolesSecond = new ArrayList<>(); + List> holesListSecond = new ArrayList<>(); + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + if (h3Resolution >= 1 && h3Resolution <= 15) { + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgesSecond) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPointsSecond.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHolesSecond) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHolesSecond.add(tmpGeoCoord); + } + + + List hexList; + List hexListSecond; + List hexListFinal = new ArrayList(); + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCells(hexPoints, holesList, h3Resolution); + } else { + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); + } + + if (!hexHolesSecond.isEmpty()) { + holesListSecond.add(hexHoles); + hexListSecond = h3.polygonToCells(hexPointsSecond, holesListSecond, h3Resolution); + } else { + hexListSecond = h3.polygonToCells(hexPointsSecond, null, h3Resolution); + } + + for (Long secondHexList : hexListSecond){ + if (hexList.contains(secondHexList)){ + hexListFinal.add(secondHexList); + } + } + return hexListFinal.stream().map(H3LongAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList(-2L); + return ringList.stream().map(H3LongAddress::of); + } + } + + @Procedure(name = "neo4jh3.polygonIntersectionString", mode = Mode.READ) + @Description("CALL neo4jh3.polygonIntersectionString(polyEdges, polyEdgeHoles, polyEdgesSecond, polyEdgeHolesSecond,resolution, latlon order)") + public Stream polygonIntersectionString(@Name("polyEdges") List polyEdges, @Name("polyEdgeHoles") List polyEdgeHoles, @Name("polyEdgesSecond") List polyEdgesSecond, @Name("polyEdgeHolesSecond") List polyEdgeHolesSecond, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + if (h3 == null) { + return Stream.empty(); + } + if (polyEdges == null || polyEdgeHoles == null || polyEdgesSecond == null || polyEdgeHolesSecond == null) { + throw new InterruptedException("invalid arguments"); + } + + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexPointsSecond = new ArrayList<>(); + List hexHolesSecond = new ArrayList<>(); + List> holesListSecond = new ArrayList<>(); + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + if (h3Resolution >= 1 && h3Resolution <= 15) { + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgesSecond) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPointsSecond.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHolesSecond) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHolesSecond.add(tmpGeoCoord); + } + + + List hexList; + List hexListSecond; + List hexListFinal = new ArrayList(); + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCellAddresses(hexPoints, holesList, h3Resolution); + } else { + hexList = h3.polygonToCellAddresses(hexPoints, null, h3Resolution); + } + + if (!hexHolesSecond.isEmpty()) { + holesListSecond.add(hexHoles); + hexListSecond = h3.polygonToCellAddresses(hexPointsSecond, holesListSecond, h3Resolution); + } else { + hexListSecond = h3.polygonToCellAddresses(hexPointsSecond, null, h3Resolution); + } + + for (String secondHexList : hexListSecond){ + if (hexList.contains(secondHexList)){ + hexListFinal.add(secondHexList); + } + } + return hexListFinal.stream().map(H3StringAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList("-2"); + return ringList.stream().map(H3StringAddress::of); + } + } + + @Procedure(name = "neo4jh3.coverage", mode = Mode.READ) + @Description("CALL neo4jh3.coverage(polyEdges, h3Resolution, latlon order)") + public Stream gridPathCellsLonLat(@Name("polyEdges") List polyEdges, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + + if (h3 == null) { + return Stream.empty(); + } + + List gpCells = new ArrayList(); + List hexPoints = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexListFinal = new ArrayList(); + List hexList; + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); + + for (int i = 0; i < hexPoints.size(); i++) { + if (i <1 ){ + int maxVal = hexPoints.size()-1; + try { + Double startLat = Precision.round(hexPoints.get(0).lat,6); + Double startLong = Precision.round(hexPoints.get(0).lng,6); + Double endLat = Precision.round(hexPoints.get(maxVal).lat,6); + Double endLong = Precision.round(hexPoints.get(maxVal).lng,6); + Long starthexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + Long endhexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } else { + try { + Double startLat = Precision.round(hexPoints.get(i-1).lat,6); + Double startLong = Precision.round(hexPoints.get(i-1).lng,6); + Double endLat = Precision.round(hexPoints.get(i).lat,6); + Double endLong = Precision.round(hexPoints.get(i).lng,6); + Long starthexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + Long endhexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } + } + + } else { + hexList = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + hexList = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return hexList.stream().map(H3LongAddress::of); + } + + @Procedure(name = "neo4jh3.coverageString", mode = Mode.READ) + @Description("CALL neo4jh3.coverageString(polyEdges, h3Resolution, latlon order)") + public Stream gridPathCellsLonLatString(@Name("polyEdges") List polyEdges, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + + if (h3 == null) { + return Stream.empty(); + } + + List gpCells = new ArrayList(); + List hexPoints = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexListFinal = new ArrayList(); + List hexList; + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + hexList = h3.polygonToCellAddresses(hexPoints, null, h3Resolution); + + for (int i = 0; i < hexPoints.size(); i++) { + if (i <1 ){ + int maxVal = hexPoints.size()-1; + try { + Double startLat = Precision.round(hexPoints.get(0).lat,6); + Double startLong = Precision.round(hexPoints.get(0).lng,6); + Double endLat = Precision.round(hexPoints.get(maxVal).lat,6); + Double endLong = Precision.round(hexPoints.get(maxVal).lng,6); + String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + String endhexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } else { + try { + Double startLat = Precision.round(hexPoints.get(i-1).lat,6); + Double startLong = Precision.round(hexPoints.get(i-1).lng,6); + Double endLat = Precision.round(hexPoints.get(i).lat,6); + Double endLong = Precision.round(hexPoints.get(i).lng,6); + String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + String endhexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } + } + + } else { + hexList = Collections.singletonList("-2"); + + } + } catch (Exception e) { + //System.out.println(e); + hexList = Collections.singletonList("-1"); + //e.printStackTrace(); + } + return hexList.stream().map(H3StringAddress::of); + } + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.gridpathlatlon", mode = Mode.READ) + @Description("CALL neo4jh3.gridpathlatlon(latitude, longitude, latitude, longitude, h3Resolution)") + public Stream gridpathlatlon(@Name("startLat") Double startLat, @Name("startLong") Double startLong, @Name("endLat") Double endLat, @Name("endLong") Double endLong, @Name("h3Res") Long h3Res) throws InterruptedException { + if (startLat == null || startLong == null || endLat == null || endLong == null) { + throw new InterruptedException("invalid arguments"); + } + if (h3 == null) { + return Stream.empty(); + } + List ringList = null; + int validLatLon = 1; + + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution < 1 || h3Resolution > 15) { + ringList = Collections.singletonList(-2L); + } + + if ( startLat>90 || startLat<-90 || endLat>90 || endLat<-90 ){ + validLatLon = 0; + ringList = Collections.singletonList(-3L); + } + + if ( startLong>180 || startLong<-180 || endLong>180 || endLong<-180 ){ + validLatLon = 0; + ringList = Collections.singletonList(-4L); + } + + if (h3Resolution > 0 && h3Resolution <= 15 && validLatLon > 0){ + final String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + final String endhexAddr = h3.latLngToCellAddress(endLat, endLong, h3Resolution); + return h3.gridPathCells(starthexAddr, endhexAddr) + .stream() + .map(H3LongAddress::of); + } else { + return ringList.stream().map(H3LongAddress::of); + } + } + + @SuppressWarnings("null") + @Procedure(name = "neo4jh3.gridpathlatlonString", mode = Mode.READ) + @Description("CALL neo4jh3.gridpathlatlonString(latitude, longitude, latitude, longitude, h3Resolution)") + public Stream gridpathlatlonString(@Name("startLat") Double startLat, @Name("startLong") Double startLong, @Name("endLat") Double endLat, @Name("endLong") Double endLong, @Name("h3Res") Long h3Res) throws InterruptedException { + if (startLat == null || startLong == null || endLat == null || endLong == null) { + throw new InterruptedException("invalid arguments"); + } + if (h3 == null) { + return Stream.empty(); + } + + List ringList = null; + int validLatLon = 1; + + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution < 1 || h3Resolution > 15) { + ringList = Collections.singletonList("-2"); + } + + if ( startLat>90 || startLat<-90 || endLat>90 || endLat<-90 ){ + validLatLon = 0; + ringList = Collections.singletonList("-3"); + } + + if ( startLong>180 || startLong<-180 || endLong>180 || endLong<-180 ){ + validLatLon = 0; + ringList = Collections.singletonList("-4"); + } + + if (h3Resolution > 0 && h3Resolution <= 15 && validLatLon > 0){ + final String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + final String endhexAddr = h3.latLngToCellAddress(endLat, endLong, h3Resolution); + return h3.gridPathCells(starthexAddr, endhexAddr) + .stream() + .map(H3StringAddress::of); + } else { + return ringList.stream().map(H3StringAddress::of); + } + } + + @Procedure(name = "neo4jh3.gridpathcell", mode = Mode.READ) + @Description("CALL neo4jh3.gridpathcell(fromAddress, toAddress)") + public Stream gridpathcell(@Name("fromAddress") Long fromAddress, @Name("toAddress") Long toAddress) throws InterruptedException { + if (fromAddress == null || toAddress == null) { + throw new InterruptedException("invalid arguments"); + } + if (h3 == null) { + return Stream.empty(); + } + + List ringList = null; + + if (h3.isValidCell(fromAddress) && h3.isValidCell(toAddress)){ + return h3.gridPathCells(fromAddress, toAddress) + .stream() + .map(H3LongAddress::of); + } else { + ringList = Collections.singletonList("-1"); + return ringList.stream().map(H3LongAddress::of); + } + } + + @Procedure(name = "neo4jh3.gridpathcellString", mode = Mode.READ) + @Description("CALL neo4jh3.gridpathcellString(fromAddress, toAddress, h3Resolution)") + public Stream gridpathcellString(@Name("fromAddress") String fromAddress, @Name("toAddress") String toAddress) throws InterruptedException { + if (fromAddress == null || toAddress == null) { + throw new InterruptedException("invalid arguments"); + } + if (h3 == null) { + return Stream.empty(); + } + + List ringList = null; + + if (h3.isValidCell(fromAddress) && h3.isValidCell(toAddress)){ + return h3.gridPathCells(fromAddress, toAddress) + .stream() + .map(H3StringAddress::of); + } else { + ringList = Collections.singletonList("-1"); + return ringList.stream().map(H3StringAddress::of); + } + } + + /* + * Return list of hex addresses for a line + */ + @Procedure(name = "neo4jh3.lineHexAddresses", mode = Mode.READ) + @Description("CALL neo4jh3.lineHexAddresses(polyEdges, h3Resolution)") + public Stream lineHexAddresses(@Name("polyEdges") List polyEdges, @Name("h3Res") Long h3Res) throws InterruptedException { + if (polyEdges == null) { + throw new InterruptedException("invalid polygon edges"); + } + if (h3 == null) { + return Stream.empty(); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution < 1 || h3Resolution > 15) { + throw new InterruptedException("invalid h3 resolution"); + } + + /* Loop through the list of lat/lon + * Convert pair to hexAddress + * For hex(0), hex(1) + * run gridPathCells and add hexAddress to list + * Until you reach last lat/lon + */ + if (polyEdges.size() < 1) { + throw new InterruptedException("invalid amount of polygon edges"); + } + + final List addresses = polyEdges.stream() + .map(s -> s.split(",")) + .map(tuple -> new double[]{Double.parseDouble(tuple[0]), Double.parseDouble(tuple[1])}) + .map(tuple -> h3.latLngToCellAddress(tuple[0], tuple[1], h3Resolution)) + .toList(); + + final Iterator> iterator = new Iterator<>() { + private int index = 0; + private String prevAddress = null; + + @Override + public boolean hasNext() { + return index < addresses.size(); + } + + @Override + public List next() { + if (prevAddress == null) { + // Must be first tic... + prevAddress = addresses.get(index); + index++; + } + + final String nextAddress = addresses.get(index); + final List list = h3.gridPathCells(prevAddress, nextAddress); + prevAddress = nextAddress; + + return list; + } + }; + + final Spliterator> spliterator = Spliterators.spliterator(iterator, addresses.size() - 1, Spliterator.ORDERED); + + return StreamSupport + .stream(spliterator, false) + .flatMap(Collection::stream) + .map(H3StringAddress::of); + } + +// Compact +@Procedure(name = "neo4jh3.compactString", mode = Mode.READ) +@Description("CALL neo4jh3.compactString(listCells)") +public Stream compactString(@Name("listCells") List listCells) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + return h3.compactCellAddresses(listCells) + .stream() + .map(H3StringAddress::of); +} + +// Compact +@Procedure(name = "neo4jh3.compact", mode = Mode.READ) +@Description("CALL neo4jh3.compact(listCells)") +public Stream compact(@Name("listCells") List listCells) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + return h3.compactCells(listCells) + .stream() + .map(H3LongAddress::of); + +} + +// Uncompact +@Procedure(name = "neo4jh3.uncompact", mode = Mode.READ) +@Description("CALL neo4jh3.uncompact(listCells, h3Resolution)") +public Stream unCompact(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 1 && h3Resolution < 15) { + Integer maxRes = 0; + Integer curRes = 0; + + ListIterator iterator = listCells.listIterator(); + while (iterator.hasNext()) { + curRes = h3.getResolution(iterator.next()); + if (curRes.compareTo(maxRes)>0){ + maxRes = curRes; + } + } + if (h3Resolution >= maxRes){ + return h3.uncompactCells(listCells,h3Resolution) + .stream() + .map(H3LongAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList(-2L); + return ringList.stream().map(H3LongAddress::of); + } + } else { + List ringList = null; + ringList = Collections.singletonList(-2L); + return ringList.stream().map(H3LongAddress::of); + } + +} + +@Procedure(name = "neo4jh3.linepolyIntersection", mode = Mode.READ) +@Description("neo4jh3.linepolyIntersection(polyEdges, polyEdgeHoles,wktString, resolution, latlon order) - Provides the distance in grid cells between the two indexes.") + public Stream lineash3( + @Name("polyEdges") List polyEdges, + @Name("polyEdgeHoles") List polyEdgeHoles, + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { + + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexList; + List hexListFinal = new ArrayList(); + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + Long h3StartAddress = 0L; + Long h3MidAddress = 0L; + Long h3EndAddress = 0L; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; + + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } + + if (polyEdges == null || polyEdgeHoles == null) { + throw new InterruptedException("invalid arguments"); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCells(hexPoints, holesList, h3Resolution); + } else { + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); + } + + mls = wktString.replace("LINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); + + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCell(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCell(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCell(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + + } + + for (Long secondHexList : listh3Address){ + if (hexList.contains(secondHexList)){ + hexListFinal.add(secondHexList); + } + } + + } + } + } else { + hexListFinal = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + hexListFinal = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return hexListFinal.stream().map(H3LongAddress::of); +} + + +// Uncompact +@Procedure(name = "neo4jh3.uncompactString", mode = Mode.READ) +@Description("CALL neo4jh3.uncompactString(listCells, h3Resolution)") +public Stream uncompactString(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 1 && h3Resolution < 15) { + Integer maxRes = 0; + Integer curRes = 0; + + ListIterator iterator = listCells.listIterator(); + while (iterator.hasNext()) { + curRes = h3.getResolution(iterator.next()); + if (curRes.compareTo(maxRes)>0){ + maxRes = curRes; + } + } + if (h3Resolution >= maxRes){ + return h3.uncompactCellAddresses(listCells,h3Resolution) + .stream() + .map(H3StringAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList("-2"); + return ringList.stream().map(H3StringAddress::of); + } + } else { + List ringList = null; + ringList = Collections.singletonList("-2"); + return ringList.stream().map(H3StringAddress::of); + } +} + + // Experimental write to db procedure +@SuppressWarnings("unused") +@Procedure(name = "neo4jh3.writeH3ToDB", mode = Mode.WRITE) +@Description("CALL neo4jh3.writeH3ToDB(listCells, strLabel, strProperty, txSize)") +public Stream writeH3ToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank()){ + returnMessage = "-5"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 0; + Long curRes = 0L; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + Transaction tx = db.beginTx(); + try { + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; + } + tx.commit(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); + } + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); + } +} + + // Experimental write to db procedure +@SuppressWarnings("unused") +@Procedure(name = "neo4jh3.writeH3StringToDB", mode = Mode.WRITE) +@Description("CALL neo4jh3.writeH3StringToDB(listCells, strLabel, strProperty, txSize)") +public Stream writeH3StringToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank()){ + returnMessage = "Empty Label and/or Property"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 0; + String curRes = ""; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + Transaction tx = db.beginTx(); + try { + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; + } + tx.commit(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); + } + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); + } +} + + // Experimental write to db procedure + @SuppressWarnings("unused") + @Procedure(name = "neo4jh3.writeH3NodesRelsToDB", mode = Mode.WRITE) + @Description("CALL neo4jh3.writeH3NodesRelsToDB(From Node, List of H3 Cells, To Node Label, To Node Property Name, RelationshipType, Transaction Size)") + public Stream writeH3NodesRelsToDB(@Name("fromNode") Node fromNode, @Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("strRelationshipType") String strRelationshipType, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + String fromNodeElmementID = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank() || strRelationshipType.isBlank()){ + returnMessage = "-5"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 1; + Long curRes =0L; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + HashMap relNodeList = new HashMap(); + String endNodeID = ""; + String qry = ""; + List hexList = new ArrayList(); + Map params = new HashMap<>(); + Transaction tx = db.beginTx(); + + try { + fromNodeElmementID = fromNode.getElementId(); + Node tFromNode = tx.getNodeByElementId(fromNodeElmementID); + for (Relationship r : tFromNode.getRelationships(RelationshipType.withName(strRelationshipType))) { + endNodeID = r.getEndNode().getElementId(); + relNodeList.put(endNodeID,endNodeID); + } + + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + endNodeID = h3Node.getElementId(); + if (relNodeList.get(endNodeID) == null){ + hexList.add(endNodeID); + relNodeList.put(endNodeID,endNodeID); + } + + if (count % txSize == 0) { + params.put("fromNode",fromNodeElmementID); + params.put("hexList",hexList); + qry = "UNWIND $hexList as teid MATCH (t) where elementId(t) = teid MATCH (f) where elementID(f) = $fromNode MERGE (f)-[:" + strRelationshipType + "]->(t);"; + tx.execute( qry, params); + hexList.clear(); + params.clear(); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; + } + // Run final relationship group + params.put("hexList",hexList); + params.put("fromNode",fromNodeElmementID); + qry = "UNWIND $hexList as teid MATCH (t) where elementId(t) = teid MATCH (f) where elementID(f) = $fromNode MERGE (f)-[:" + strRelationshipType + "]->(t);"; + tx.execute( qry, params); + tx.commit(); + hexList.clear(); + params.clear(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); + } + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); + } + } + + // Experimental write to db procedure + @Procedure(name = "neo4jh3.writeH3StringNodesRelsToDB", mode = Mode.WRITE) + @Description("CALL neo4jh3.writeH3StringNodesRelsToDB(From Node, List of H3 Cells, To Node Label, To Node Property Name, RelationshipType, Transaction Size)") + public Stream writeH3StringNodesRelsToDB(@Name("fromNode") Node fromNode, @Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("strRelationshipType") String strRelationshipType, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + String fromNodeElmementID = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank() || strRelationshipType.isBlank()){ + returnMessage = "-5"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 1; + String curRes = ""; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + HashMap relNodeList = new HashMap(); + String endNodeID = ""; + String qry = ""; + List hexList = new ArrayList(); + Map params = new HashMap<>(); + Transaction tx = db.beginTx(); + + try { + fromNodeElmementID = fromNode.getElementId(); + Node tFromNode = tx.getNodeByElementId(fromNodeElmementID); + for (Relationship r : tFromNode.getRelationships(RelationshipType.withName(strRelationshipType))) { + endNodeID = r.getEndNode().getElementId(); + relNodeList.put(endNodeID,endNodeID); + } + + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + endNodeID = h3Node.getElementId(); + if (relNodeList.get(endNodeID) == null){ + hexList.add(endNodeID); + relNodeList.put(endNodeID,endNodeID); + } + + if (count % txSize == 0) { + params.put("fromNode",fromNodeElmementID); + params.put("hexList",hexList); + qry = "UNWIND $hexList as teid MATCH (t) where elementId(t) = teid MATCH (f) where elementID(f) = $fromNode MERGE (f)-[:" + strRelationshipType + "]->(t);"; + tx.execute( qry, params); + hexList.clear(); + params.clear(); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; + } + // Run final relationship group + params.put("hexList",hexList); + params.put("fromNode",fromNodeElmementID); + qry = "UNWIND $hexList as teid MATCH (t) where elementId(t) = teid MATCH (f) where elementID(f) = $fromNode MERGE (f)-[:" + strRelationshipType + "]->(t);"; + tx.execute( qry, params); + tx.commit(); + hexList.clear(); + params.clear(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); + } + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); + } + } + + private static double distance(double lat1, double lon1, double lat2, double lon2, String unit) { + if ((lat1 == lat2) && (lon1 == lon2)) { + return 0; + } + else { + double theta = lon1 - lon2; + double dist = Math.sin(Math.toRadians(lat1)) * Math.sin(Math.toRadians(lat2)) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.cos(Math.toRadians(theta)); + dist = Math.acos(dist); + dist = Math.toDegrees(dist); + dist = dist * 60 * 1.1515; + if (unit.equals("K")) { + dist = dist * 1.609344; + } else if (unit.equals("N")) { + dist = dist * 0.8684; + } + return (dist); + } + } + + private static double angleDistance(double lat1, double lon1, double lat2, double lon2) { + if ((lat1 == lat2) && (lon1 == lon2)) { + return 0; + } + else { + double longitude1 = lon1; + double longitude2 = lon2; + double latitude1 = Math.toRadians(lat1); + double latitude2 = Math.toRadians(lat2); + double longDiff= Math.toRadians(longitude2-longitude1); + double y= Math.sin(longDiff)*Math.cos(latitude2); + double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff); + + return (Math.toDegrees(Math.atan2(y, x))+360)%360; + } + } + + private static LatLng returnLatLng (String lonlatPairs) { + LatLng tmpGeoCoord = null; + Double polyLat = 0.0; + Double polyLon = 0.0; + if (!lonlatPairs.isBlank()){ + String lonlat = lonlatPairs.toString(); + lonlat = lonlat.trim(); + polyLat = Double.valueOf(lonlat.split("\\s+")[0]); + polyLon = Double.valueOf(lonlat.split("\\s+")[1]); + tmpGeoCoord = new LatLng(polyLat,polyLon); + } + return tmpGeoCoord; + } + + private static LatLng returnLngLat (String lonlatPairs) { + LatLng tmpGeoCoord = null; + Double polyLat = 0.0; + Double polyLon = 0.0; + if (!lonlatPairs.isBlank()){ + String lonlat = lonlatPairs.toString(); + lonlat = lonlat.trim(); + polyLat = Double.valueOf(lonlat.split("\\s+")[1]); + polyLon = Double.valueOf(lonlat.split("\\s+")[0]); + tmpGeoCoord = new LatLng(polyLat,polyLon); + } + return tmpGeoCoord; + } + +} diff --git a/src/main/java/com/neo4jh3/uber/Uberh3.java b/src/main/java/com/neo4jh3/uber/Uberh3.java old mode 100755 new mode 100644 index c7aef4d..ec51e46 --- a/src/main/java/com/neo4jh3/uber/Uberh3.java +++ b/src/main/java/com/neo4jh3/uber/Uberh3.java @@ -47,6 +47,7 @@ public class Uberh3 { } } + @Deprecated @UserFunction(name = "com.neo4jh3.h3Validate") @Description("com.neo4jh3.h3Validate(hexAddress) - validate a long hex Address.") public Long h3Validate( @@ -69,6 +70,7 @@ public Long h3Validate( } + @Deprecated @UserFunction(name = "com.neo4jh3.h3ValidateString") @Description("com.neo4jh3.h3ValidateString(hexAddress) - validate a string hex Address.") public String h3ValidateString( @@ -90,6 +92,7 @@ public String h3ValidateString( } @SuppressWarnings("null") + @Deprecated @UserFunction(name = "com.neo4jh3.h3HexAddress") @Description("com.neo4jh3.h3HexAddress(latitude, longitude, resolution) - return the hex address for a given latitude.") public Long h3HexAddress( @@ -128,6 +131,7 @@ public Long h3HexAddress( } @SuppressWarnings("null") + @Deprecated @UserFunction(name = "com.neo4jh3.h3HexAddressString") @Description("com.neo4jh3.h3HexAddressString(latitude, longitude, resolution) - return the hex address for a given latitude.") public String h3HexAddressString( @@ -170,6 +174,7 @@ public String h3HexAddressString( * @param longHex * @return */ + @Deprecated @UserFunction(name = "com.neo4jh3.h3tostring") @Description("com.neo4jh3.h3tostring(longHex) - return the string value of a long hex address.") public String h3tostringFunction( @@ -192,6 +197,7 @@ public String h3tostringFunction( } } + @Deprecated @UserFunction(name = "com.neo4jh3.stringToH3") @Description("com.neo4jh3.stringToH3(longHex) - return the string value of a long hex address.") public Long stringToH3Function( @@ -214,6 +220,7 @@ public Long stringToH3Function( } } + @Deprecated @UserFunction(name = "com.neo4jh3.h3ResolutionString") @Description("com.neo4jh3.h3ResolutionString(longHex) - return the resolution of a string hex address.") public Long h3ResolutionString( @@ -236,6 +243,7 @@ public Long h3ResolutionString( } } + @Deprecated @UserFunction(name = "com.neo4jh3.h3Resolution") @Description("com.neo4jh3.h3Resolution(longHex) - return the string value of a long hex address.") public Long h3Resolution( @@ -259,6 +267,7 @@ public Long h3Resolution( } + @Deprecated @UserFunction(name = "com.neo4jh3.latlongash3String") @Description("com.neo4jh3.latlongash3String(latitude, longitude, resolution) - return the hex address for a given latitude.") public String latlongash3String( @@ -303,6 +312,7 @@ public String latlongash3String( } @SuppressWarnings("null") + @Deprecated @UserFunction(name = "com.neo4jh3.latlongash3") @Description("com.neo4jh3.latlongash3(latitude, longitude, resolution) - return the hex address for a given latitude.") public Long latlongash3( @@ -341,6 +351,7 @@ public Long latlongash3( return returnValue; } + @Deprecated @UserFunction(name = "com.neo4jh3.h3RingsForDistance") @Description("com.neo4jh3.h3RingsForDistance(resolution, distance) - return the number of rings for a given distance.") public Long h3RingsForDistance( @@ -362,6 +373,7 @@ public Long h3RingsForDistance( throw new RuntimeException("invalid h3 resolution"); } + @Deprecated @UserFunction(name = "com.neo4jh3.gridDistance") @Description("com.neo4jh3.gridDistance(fromHexAddress, toHexAddress) - Provides the distance in grid cells between the two indexes.") public Long gridDistance( @@ -386,6 +398,7 @@ public Long gridDistance( return returnValue; } + @Deprecated @UserFunction(name = "com.neo4jh3.gridDistanceString") @Description("com.neo4jh3.gridDistanceString(fromHexAddress, toHexAddress) - Provides the distance in grid cells between the two indexes.") public double gridDistanceString( @@ -412,6 +425,7 @@ public double gridDistanceString( return returnValue; } + @Deprecated @UserFunction(name = "com.neo4jh3.toparent") @Description("CALL com.neo4jh3.toparent(hexAddress, h3Resolution)") public Long toparent(@Name("hexAddress") Long hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -439,6 +453,7 @@ public Long toparent(@Name("hexAddress") Long hexAddress, @Name("h3Res") Long h3 return returnValue; } + @Deprecated @UserFunction(name = "com.neo4jh3.toparentString") @Description("CALL com.neo4jh3.toparentString(hexAddress, h3Resolution)") public String toparentString(@Name("hexAddress") String hexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -465,6 +480,7 @@ public String toparentString(@Name("hexAddress") String hexAddress, @Name("h3Res return returnValue; } + @Deprecated @UserFunction(name = "com.neo4jh3.cellToLatLng") @Description("CALL com.neo4jh3.cellToLatLng(hexAddress)") public String cellToLatLng(@Name("hexAddress") Long hexAddress) throws InterruptedException { @@ -482,6 +498,7 @@ public String cellToLatLng(@Name("hexAddress") Long hexAddress) throws Interrupt } } + @Deprecated @UserFunction(name = "com.neo4jh3.cellToLatLngString") @Description("CALL com.neo4jh3.cellToLatLngString(hexAddress)") public String cellToLatLngString(@Name("hexAddress") String hexAddress) throws InterruptedException { @@ -501,6 +518,7 @@ public String cellToLatLngString(@Name("hexAddress") String hexAddress) throws I } @SuppressWarnings("unused") + @Deprecated @UserFunction(name = "com.neo4jh3.distanceBetweenHexes") @Description("CALL com.neo4jh3.distanceBetweenHexes(fromHexAddress, toHexAddress)") public double distanceBetweenHexes(@Name("fromHexAddress") Long fromHexAddress, @Name("toHexAddress") Long toHexAddress) throws InterruptedException { @@ -521,6 +539,7 @@ public double distanceBetweenHexes(@Name("fromHexAddress") Long fromHexAddress, } @SuppressWarnings("unused") + @Deprecated @UserFunction(name = "com.neo4jh3.distanceBetweenHexesString") @Description("CALL com.neo4jh3.distanceBetweenHexesString(fromHexAddress, toHexAddress)") public double distanceBetweenHexesString(@Name("fromHexAddress") String fromHexAddress, @Name("toHexAddress") String toHexAddress) throws InterruptedException { @@ -540,6 +559,7 @@ public double distanceBetweenHexesString(@Name("fromHexAddress") String fromHexA } } + @Deprecated @UserFunction(name = "com.neo4jh3.minChild") @Description("CALL com.neo4jh3.minChild(hexAddress, h3Resolution)") public Long minChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -575,6 +595,7 @@ public Long minChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") } } + @Deprecated @UserFunction(name = "com.neo4jh3.minChildString") @Description("CALL com.neo4jh3.minChildString(hexAddress, h3Resolution)") public String minChildString(@Name("fromHexAddress") String fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -608,6 +629,7 @@ public String minChildString(@Name("fromHexAddress") String fromHexAddress, @Nam } } + @Deprecated @UserFunction(name = "com.neo4jh3.maxChild") @Description("CALL com.neo4jh3.maxChild(hexAddress, h3Resolution)") public Long maxChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -643,6 +665,7 @@ public Long maxChild(@Name("fromHexAddress") Long fromHexAddress, @Name("h3Res") } } + @Deprecated @UserFunction(name = "com.neo4jh3.maxChildString") @Description("CALL com.neo4jh3.maxChildString(hexAddress, h3Resolution)") public String maxChild(@Name("fromHexAddress") String fromHexAddress, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -678,6 +701,7 @@ public String maxChild(@Name("fromHexAddress") String fromHexAddress, @Name("h3R } } + @Deprecated @UserFunction(name = "com.neo4jh3.angleBetweenPoints") @Description("CALL com.neo4jh3.angleBetweenPoints(latitude1, longitude1, latitude2, longitude2)") public Double angleBetweenPoints( @@ -708,6 +732,7 @@ public Double angleBetweenPoints( } // Geography Functions + @Deprecated @UserFunction(name = "com.neo4jh3.pointash3") @Description("com.neo4jh3.pointash3(wktString, resolution, latlon order) - Loads a WKT POINT and returns H3 LONG values.") public Long pointash3( @@ -745,6 +770,8 @@ public Long pointash3( } return h3Address; } + + @Deprecated @UserFunction(name = "com.neo4jh3.pointash3String") @Description("com.neo4jh3.pointash3String(wktString, resolution, latlon order) - Loads a WKT POINT and returns H3 String values.") public String pointash3String( @@ -795,6 +822,7 @@ public String neo4jH3Version() throws InterruptedException // Procedures + @Deprecated @Procedure(name = "com.neo4jh3.lineash3", mode = Mode.READ) @Description("com.neo4jh3.lineash3(wktString, resolution, latlonorder) - Loads a WKT LINESTRING and returns H3 Long values.") public Stream lineash3( @@ -891,6 +919,7 @@ public Stream lineash3( } // New Geo Procedures + @Deprecated @Procedure(name = "com.neo4jh3.lineash3String", mode = Mode.READ) @Description("com.neo4jh3.lineash3String(wktString, resolution, latlonorder) - Loads a WKT LINESTRING and returns H3 String values.") public Stream lineash3String( @@ -987,6 +1016,7 @@ public Stream lineash3String( return listh3Address.stream().map(H3StringAddress::of); } + @Deprecated @Procedure(name = "com.neo4jh3.multilineash3", mode = Mode.READ) @Description("com.neo4jh3.multilineash3(wktString, resolution, latlonorder) - Provides the distance in grid cells between the two indexes.") public Stream multilineash3( @@ -1083,6 +1113,7 @@ public Stream multilineash3( } // New Geo Procedures + @Deprecated @Procedure(name = "com.neo4jh3.multilineash3String", mode = Mode.READ) @Description("com.neo4jh3.multilineash3String(wktString, resolution, latlonorder) - Provides the distance in grid cells between the two indexes.") public Stream multilineash3String( @@ -1182,6 +1213,7 @@ public Stream multilineash3String( // Add MultiPolygon Support for WKT file // Example: https://www.georgia811.com/wp-content/uploads/2022/06/Well_Known_Text.pdf // Added 4 June 2024 + @Deprecated @Procedure(name = "com.neo4jh3.polygonash3", mode = Mode.READ) @Description("com.neo4jh3.polygonash3(wktString, resolution) - Returns the hex addresses as a long from a WKT Polygon string.") public Stream polygonash3( @@ -1232,6 +1264,7 @@ public Stream polygonash3( return listh3Address.stream().map(H3LongAddress::of); } + @Deprecated @Procedure(name = "com.neo4jh3.polygonash3String", mode = Mode.READ) @Description("com.neo4jh3.polygonash3String(wktString, resolution) - Returns the hex addresses as a String from a WKT Polygon string") public Stream polygonash3String( @@ -1284,6 +1317,7 @@ public Stream polygonash3String( } // Added June 2024 + @Deprecated @Procedure(name = "com.neo4jh3.multipolygonash3", mode = Mode.READ) @Description("com.neo4jh3.multipolygonash3(wktString, resolution) - Returns the hex addresses as a long from a WKT MultiPolygon string.") public Stream multipolygonash3( @@ -1339,7 +1373,8 @@ public Stream multipolygonash3( return listh3Address.stream().map(H3LongAddress::of); } // Added June 2024 - @Procedure(name = "com.neo4jh3.multipolygonash3String", mode = Mode.READ) + @Deprecated + @Procedure(name = "com.neo4jh3.multipolygonash3String", mode = Mode.READ) @Description("com.neo4jh3.multipolygonash3String(wktString, resolution) - Returns the hex addresses as a String from a WKT MultiPolygon string.") public Stream multipolygonash3String( @Name("wktString") String wktString, @@ -1396,6 +1431,7 @@ public Stream multipolygonash3String( // Geography Functions + @Deprecated @UserFunction(name = "com.neo4jh3.centeraswkb") @Description("com.neo4jh3.centeraswkb(hexAddress) - Returns the center of a hex address in WKB format.") public String centeraswkb( @@ -1428,6 +1464,7 @@ public String centeraswkb( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.centeraswkbString") @Description("com.neo4jh3.centeraswkbString(hexAddress) - Returns the center of a hex address in WKB format.") public String centeraswkbString( @@ -1459,6 +1496,8 @@ public String centeraswkbString( } return geoJsonString; } + + @Deprecated @UserFunction(name = "com.neo4jh3.centeraswkt") @Description("com.neo4jh3.centeraswkt(hexAddress) - Returns the center of a hex address in WKT format.") public String centeraswkt( @@ -1488,6 +1527,7 @@ public String centeraswkt( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.centeraswktString") @Description("com.neo4jh3.centeraswktString(hexAddress) - Returns the center of a hex address in WKT format.") public String centeraswktString( @@ -1517,6 +1557,7 @@ public String centeraswktString( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryaswkt") @Description("com.neo4jh3.boundaryaswkt(hexAddress) - Returns the boundary of a hex address in WKT format.") public String boundaryaswkt( @@ -1560,6 +1601,7 @@ public String boundaryaswkt( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryaswktString") @Description("com.neo4jh3.boundaryaswktString(hexAddress) - Returns the boundary of a hex address in WKT format.") public String boundaryaswktString( @@ -1603,6 +1645,7 @@ public String boundaryaswktString( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryaswkb") @Description("com.neo4jh3.boundaryaswkb(hexAddress) - Returns the boundary of a hex address in WKB format.") public String boundaryaswkb( @@ -1650,6 +1693,7 @@ public String boundaryaswkb( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryaswkbString") @Description("com.neo4jh3.boundaryaswkbString(hexAddress) -- Returns the boundary of a hex address in WKB format.") public String boundaryaswkbString( @@ -1697,6 +1741,7 @@ public String boundaryaswkbString( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.centerasgeojson") @Description("com.neo4jh3.centerasgeojson(hexAddress) - Returns the center of a hex address as a GeoJson string.") public String centerasgeojson( @@ -1726,6 +1771,7 @@ public String centerasgeojson( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.centerasgeojsonString") @Description("com.neo4jh3.centerasgeojsonString(hexAddress) - Returns the center of a hex address as a GeoJson string.") public String centerasgeojsonString( @@ -1755,6 +1801,7 @@ public String centerasgeojsonString( } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryasgeojson") @Description("com.neo4jh3.boundaryasgeojson(hexAddress) - Returns the boundary of a hex address as a GeoJson string.") public String boundaryasgeojson( @@ -1798,6 +1845,7 @@ public String boundaryasgeojson( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.boundaryasgeojsonString") @Description("com.neo4jh3.boundaryasgeojsonString(hexAddress) - Returns the boundary of a hex address as a GeoJson string.") public String boundaryasgeojsonString( @@ -1841,6 +1889,7 @@ public String boundaryasgeojsonString( return geoJsonString; } + @Deprecated @UserFunction(name = "com.neo4jh3.ispentagon") @Description("com.neo4jh3.ispentagon(hexAddress) - is hexAddress a pentagon.") public Boolean ispentagon( @@ -1862,6 +1911,7 @@ public Boolean ispentagon( } } + @Deprecated @UserFunction(name = "com.neo4jh3.ispentagonString") @Description("com.neo4jh3.ispentagonString(hexAddress) - is hexAddress a pentagon.") public Boolean ispentagonString( @@ -1886,6 +1936,7 @@ public Boolean ispentagonString( /* Neo4j H3 Procedures */ @SuppressWarnings("null") + @Deprecated @Procedure(name = "com.neo4jh3.gridDisk", mode = Mode.READ) @Description("CALL com.neo4jh3.gridDisk(hexAddress, ringSize) - Returns all H3 addresses around the hexAddress at the given ring size") public Stream gridDisk(@Name("hexAddress") Long hexAddress, @Name("ringSize") Long ringSize) @@ -2303,7 +2354,179 @@ public Stream polygonIntersectionString(@Name("polyEdges") List } } + @Procedure(name = "com.neo4jh3.coverage", mode = Mode.READ) + @Description("CALL com.neo4jh3.coverage(polyEdges, h3Resolution, latlon order)") + public Stream gridPathCellsLonLat(@Name("polyEdges") List polyEdges, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + + if (h3 == null) { + return Stream.empty(); + } + + List gpCells = new ArrayList(); + List hexPoints = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexListFinal = new ArrayList(); + List hexList; + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); + + for (int i = 0; i < hexPoints.size(); i++) { + if (i <1 ){ + int maxVal = hexPoints.size()-1; + try { + Double startLat = Precision.round(hexPoints.get(0).lat,6); + Double startLong = Precision.round(hexPoints.get(0).lng,6); + Double endLat = Precision.round(hexPoints.get(maxVal).lat,6); + Double endLong = Precision.round(hexPoints.get(maxVal).lng,6); + Long starthexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + Long endhexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } else { + try { + Double startLat = Precision.round(hexPoints.get(i-1).lat,6); + Double startLong = Precision.round(hexPoints.get(i-1).lng,6); + Double endLat = Precision.round(hexPoints.get(i).lat,6); + Double endLong = Precision.round(hexPoints.get(i).lng,6); + Long starthexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + Long endhexAddr = h3.latLngToCell(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } + } + + } else { + hexList = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + hexList = Collections.singletonList(-1L); + //e.printStackTrace(); + } + return hexList.stream().map(H3LongAddress::of); + } + + @Deprecated + @Procedure(name = "com.neo4jh3.coverageString", mode = Mode.READ) + @Description("CALL com.neo4jh3.coverageString(polyEdges, h3Resolution, latlon order)") + public Stream gridPathCellsLonLatString(@Name("polyEdges") List polyEdges, @Name("h3Res") Long h3Res, @Name("latlonorder") String latlonorder) throws InterruptedException { + + if (h3 == null) { + return Stream.empty(); + } + + List gpCells = new ArrayList(); + List hexPoints = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexListFinal = new ArrayList(); + List hexList; + + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + + try { + if (h3Resolution > 0 && h3Resolution <= 15) { + + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); + } + + hexList = h3.polygonToCellAddresses(hexPoints, null, h3Resolution); + + for (int i = 0; i < hexPoints.size(); i++) { + if (i <1 ){ + int maxVal = hexPoints.size()-1; + try { + Double startLat = Precision.round(hexPoints.get(0).lat,6); + Double startLong = Precision.round(hexPoints.get(0).lng,6); + Double endLat = Precision.round(hexPoints.get(maxVal).lat,6); + Double endLong = Precision.round(hexPoints.get(maxVal).lng,6); + String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + String endhexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } else { + try { + Double startLat = Precision.round(hexPoints.get(i-1).lat,6); + Double startLong = Precision.round(hexPoints.get(i-1).lng,6); + Double endLat = Precision.round(hexPoints.get(i).lat,6); + Double endLong = Precision.round(hexPoints.get(i).lng,6); + String starthexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + String endhexAddr = h3.latLngToCellAddress(startLat, startLong, h3Resolution); + gpCells = h3.gridPathCells(starthexAddr, endhexAddr); + for (int j = 0; j < gpCells.size(); j++) { + if (!hexList.contains(gpCells.get(j))){ + hexList.add(gpCells.get(j)); + } + } + gpCells.clear(); + } catch (Exception e1){ + + } + } + } + + } else { + hexList = Collections.singletonList("-2"); + + } + } catch (Exception e) { + //System.out.println(e); + hexList = Collections.singletonList("-1"); + //e.printStackTrace(); + } + return hexList.stream().map(H3StringAddress::of); + } + @SuppressWarnings("null") + @Deprecated @Procedure(name = "com.neo4jh3.gridpathlatlon", mode = Mode.READ) @Description("CALL com.neo4jh3.gridpathlatlon(latitude, longitude, latitude, longitude, h3Resolution)") public Stream gridpathlatlon(@Name("startLat") Double startLat, @Name("startLong") Double startLong, @Name("endLat") Double endLat, @Name("endLong") Double endLong, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -2344,6 +2567,7 @@ public Stream gridpathlatlon(@Name("startLat") Double startLat, @ } @SuppressWarnings("null") + @Deprecated @Procedure(name = "com.neo4jh3.gridpathlatlonString", mode = Mode.READ) @Description("CALL com.neo4jh3.gridpathlatlonString(latitude, longitude, latitude, longitude, h3Resolution)") public Stream gridpathlatlonString(@Name("startLat") Double startLat, @Name("startLong") Double startLong, @Name("endLat") Double endLat, @Name("endLong") Double endLong, @Name("h3Res") Long h3Res) throws InterruptedException { @@ -2385,6 +2609,7 @@ public Stream gridpathlatlonString(@Name("startLat") Double sta } @Procedure(name = "com.neo4jh3.gridpathcell", mode = Mode.READ) + @Deprecated @Description("CALL com.neo4jh3.gridpathcell(fromAddress, toAddress)") public Stream gridpathcell(@Name("fromAddress") Long fromAddress, @Name("toAddress") Long toAddress) throws InterruptedException { if (fromAddress == null || toAddress == null) { @@ -2407,6 +2632,7 @@ public Stream gridpathcell(@Name("fromAddress") Long fromAddress, } @Procedure(name = "com.neo4jh3.gridpathcellString", mode = Mode.READ) + @Deprecated @Description("CALL com.neo4jh3.gridpathcellString(fromAddress, toAddress, h3Resolution)") public Stream gridpathcellString(@Name("fromAddress") String fromAddress, @Name("toAddress") String toAddress) throws InterruptedException { if (fromAddress == null || toAddress == null) { @@ -2495,347 +2721,355 @@ public List next() { .map(H3StringAddress::of); } -// Compact -@Procedure(name = "com.neo4jh3.compactString", mode = Mode.READ) -@Description("CALL com.neo4jh3.compactString(listCells)") -public Stream compactString(@Name("listCells") List listCells) throws InterruptedException { - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (h3 == null) { - return Stream.empty(); + // Compact + @Deprecated + @Procedure(name = "com.neo4jh3.compactString", mode = Mode.READ) + @Description("CALL com.neo4jh3.compactString(listCells)") + public Stream compactString(@Name("listCells") List listCells) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + return h3.compactCellAddresses(listCells) + .stream() + .map(H3StringAddress::of); } - return h3.compactCellAddresses(listCells) - .stream() - .map(H3StringAddress::of); -} -// Compact -@Procedure(name = "com.neo4jh3.compact", mode = Mode.READ) -@Description("CALL com.neo4jh3.compact(listCells)") -public Stream compact(@Name("listCells") List listCells) throws InterruptedException { - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (h3 == null) { - return Stream.empty(); + // Compact + @Deprecated + @Procedure(name = "com.neo4jh3.compact", mode = Mode.READ) + @Description("CALL com.neo4jh3.compact(listCells)") + public Stream compact(@Name("listCells") List listCells) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } + return h3.compactCells(listCells) + .stream() + .map(H3LongAddress::of); + } - return h3.compactCells(listCells) - .stream() - .map(H3LongAddress::of); - -} -// Uncompact -@Procedure(name = "com.neo4jh3.uncompact", mode = Mode.READ) -@Description("CALL com.neo4jh3.uncompact(listCells, h3Resolution)") -public Stream unCompact(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (h3 == null) { - return Stream.empty(); - } + // Uncompact + @Deprecated + @Procedure(name = "com.neo4jh3.uncompact", mode = Mode.READ) + @Description("CALL com.neo4jh3.uncompact(listCells, h3Resolution)") + public Stream unCompact(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } - final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); - if (h3Resolution > 1 && h3Resolution < 15) { - Integer maxRes = 0; - Integer curRes = 0; + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 1 && h3Resolution < 15) { + Integer maxRes = 0; + Integer curRes = 0; - ListIterator iterator = listCells.listIterator(); - while (iterator.hasNext()) { - curRes = h3.getResolution(iterator.next()); - if (curRes.compareTo(maxRes)>0){ - maxRes = curRes; + ListIterator iterator = listCells.listIterator(); + while (iterator.hasNext()) { + curRes = h3.getResolution(iterator.next()); + if (curRes.compareTo(maxRes)>0){ + maxRes = curRes; + } + } + if (h3Resolution >= maxRes){ + return h3.uncompactCells(listCells,h3Resolution) + .stream() + .map(H3LongAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList(-2L); + return ringList.stream().map(H3LongAddress::of); } - } - if (h3Resolution >= maxRes){ - return h3.uncompactCells(listCells,h3Resolution) - .stream() - .map(H3LongAddress::of); } else { List ringList = null; ringList = Collections.singletonList(-2L); return ringList.stream().map(H3LongAddress::of); } - } else { - List ringList = null; - ringList = Collections.singletonList(-2L); - return ringList.stream().map(H3LongAddress::of); + } - -} -@Procedure(name = "com.neo4jh3.linepolyIntersection", mode = Mode.READ) -@Description("com.neo4jh3.linepolyIntersection(polyEdges, polyEdgeHoles,wktString, resolution, latlon order) - Provides the distance in grid cells between the two indexes.") - public Stream lineash3( - @Name("polyEdges") List polyEdges, - @Name("polyEdgeHoles") List polyEdgeHoles, - @Name("wktString") String wktString, - @Name("h3Res") Long h3Res, - @Name("latlonorder") String latlonorder) throws InterruptedException - { + @Deprecated + @Procedure(name = "com.neo4jh3.linepolyIntersection", mode = Mode.READ) + @Description("com.neo4jh3.linepolyIntersection(polyEdges, polyEdgeHoles,wktString, resolution, latlon order) - Provides the distance in grid cells between the two indexes.") + public Stream lineash3( + @Name("polyEdges") List polyEdges, + @Name("polyEdgeHoles") List polyEdgeHoles, + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res, + @Name("latlonorder") String latlonorder) throws InterruptedException + { - List hexPoints = new ArrayList<>(); - List hexHoles = new ArrayList<>(); - List> holesList = new ArrayList<>(); - List hexList; - List hexListFinal = new ArrayList(); - List listh3Address = new ArrayList(); - List gpCells = new ArrayList(); - Long h3StartAddress = 0L; - Long h3MidAddress = 0L; - Long h3EndAddress = 0L; - Double fromLat = 0.0; - Double fromLon = 0.0; - Double toLat = 0.0; - Double toLon = 0.0; - Double midLat = 0.0; - Double midLon = 0.0; - String mls = ""; + List hexPoints = new ArrayList<>(); + List hexHoles = new ArrayList<>(); + List> holesList = new ArrayList<>(); + List hexList; + List hexListFinal = new ArrayList(); + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + Long h3StartAddress = 0L; + Long h3MidAddress = 0L; + Long h3EndAddress = 0L; + Double fromLat = 0.0; + Double fromLon = 0.0; + Double toLat = 0.0; + Double toLon = 0.0; + Double midLat = 0.0; + Double midLon = 0.0; + String mls = ""; - if (h3 == null) { - throw new InterruptedException("h3 failed to initialize"); - } + if (h3 == null) { + throw new InterruptedException("h3 failed to initialize"); + } - if (polyEdges == null || polyEdgeHoles == null) { - throw new InterruptedException("invalid arguments"); - } + if (polyEdges == null || polyEdgeHoles == null) { + throw new InterruptedException("invalid arguments"); + } - final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); - try { - if (h3Resolution > 0 && h3Resolution <= 15) { + try { + if (h3Resolution > 0 && h3Resolution <= 15) { - for (String mapEdges : polyEdges) { - final String[] latLonList = mapEdges.split(","); - LatLng tmpGeoCoord = null; - if (latlonorder.equalsIgnoreCase("latlon")){ - tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); - } else { - tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + for (String mapEdges : polyEdges) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[0])); + } + hexPoints.add(tmpGeoCoord); } - hexPoints.add(tmpGeoCoord); - } - for (String mapEdges : polyEdgeHoles) { - final String[] latLonList = mapEdges.split(","); - LatLng tmpGeoCoord = null; - if (latlonorder.equalsIgnoreCase("latlon")){ - tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + for (String mapEdges : polyEdgeHoles) { + final String[] latLonList = mapEdges.split(","); + LatLng tmpGeoCoord = null; + if (latlonorder.equalsIgnoreCase("latlon")){ + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[0]), Double.parseDouble(latLonList[1])); + } else { + tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + } + hexHoles.add(tmpGeoCoord); + } + + if (!hexHoles.isEmpty()) { + holesList.add(hexHoles); + hexList = h3.polygonToCells(hexPoints, holesList, h3Resolution); } else { - tmpGeoCoord = new LatLng(Double.parseDouble(latLonList[1]), Double.parseDouble(latLonList[2])); + hexList = h3.polygonToCells(hexPoints, null, h3Resolution); } - hexHoles.add(tmpGeoCoord); - } - if (!hexHoles.isEmpty()) { - holesList.add(hexHoles); - hexList = h3.polygonToCells(hexPoints, holesList, h3Resolution); - } else { - hexList = h3.polygonToCells(hexPoints, null, h3Resolution); - } + mls = wktString.replace("LINESTRING((", ""); + mls = mls.replace(" (",""); + mls = mls.replace(")",""); + mls = mls.replace("(",""); + String[] latlonPairs = mls.split(","); + String lonlat = ""; + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + lonlat = latlonPairs[i-1].toString(); + lonlat = lonlat.trim(); + fromLat = Double.valueOf(lonlat.split("\\s+")[0]); + fromLon = Double.valueOf(lonlat.split("\\s+")[1]); + lonlat = latlonPairs[i].toString(); + lonlat = lonlat.trim(); + toLat = Double.valueOf(lonlat.split("\\s+")[0]); + toLon =Double.valueOf(lonlat.split("\\s+")[1]); - mls = wktString.replace("LINESTRING((", ""); - mls = mls.replace(" (",""); - mls = mls.replace(")",""); - mls = mls.replace("(",""); - String[] latlonPairs = mls.split(","); - String lonlat = ""; - for (int i = 0; i < latlonPairs.length; i++) { - if (i > 0){ - lonlat = latlonPairs[i-1].toString(); - lonlat = lonlat.trim(); - fromLat = Double.valueOf(lonlat.split("\\s+")[0]); - fromLon = Double.valueOf(lonlat.split("\\s+")[1]); - lonlat = latlonPairs[i].toString(); - lonlat = lonlat.trim(); - toLat = Double.valueOf(lonlat.split("\\s+")[0]); - toLon =Double.valueOf(lonlat.split("\\s+")[1]); + midLat = (fromLat + toLat) / 2; + midLon = (fromLon + toLon) / 2; + h3StartAddress = h3.latLngToCell(fromLat, fromLon, h3Resolution); + h3MidAddress = h3.latLngToCell(midLat, midLon, h3Resolution); + h3EndAddress = h3.latLngToCell(toLat, toLon, h3Resolution); + try { + gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ + } + try { + gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); + for (int j = 0; j < gpCells.size(); j++) { + listh3Address.add(gpCells.get(j)); + } + gpCells.clear(); + } catch (Exception e1){ - midLat = (fromLat + toLat) / 2; - midLon = (fromLon + toLon) / 2; - h3StartAddress = h3.latLngToCell(fromLat, fromLon, h3Resolution); - h3MidAddress = h3.latLngToCell(midLat, midLon, h3Resolution); - h3EndAddress = h3.latLngToCell(toLat, toLon, h3Resolution); - try { - gpCells = h3.gridPathCells(h3StartAddress, h3MidAddress); - for (int j = 0; j < gpCells.size(); j++) { - listh3Address.add(gpCells.get(j)); } - gpCells.clear(); - } catch (Exception e1){ - } - try { - gpCells = h3.gridPathCells((h3MidAddress), h3EndAddress); - for (int j = 0; j < gpCells.size(); j++) { - listh3Address.add(gpCells.get(j)); + + for (Long secondHexList : listh3Address){ + if (hexList.contains(secondHexList)){ + hexListFinal.add(secondHexList); + } } - gpCells.clear(); - } catch (Exception e1){ } - - for (Long secondHexList : listh3Address){ - if (hexList.contains(secondHexList)){ - hexListFinal.add(secondHexList); - } - } - } + } else { + hexListFinal = Collections.singletonList(-2L); + } - } else { - hexListFinal = Collections.singletonList(-2L); - + } catch (Exception e) { + //System.out.println(e); + hexListFinal = Collections.singletonList(-1L); + //e.printStackTrace(); } - } catch (Exception e) { - //System.out.println(e); - hexListFinal = Collections.singletonList(-1L); - //e.printStackTrace(); - } - return hexListFinal.stream().map(H3LongAddress::of); -} + return hexListFinal.stream().map(H3LongAddress::of); + } -// Uncompact -@Procedure(name = "com.neo4jh3.uncompactString", mode = Mode.READ) -@Description("CALL com.neo4jh3.uncompactString(listCells, h3Resolution)") -public Stream uncompactString(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (h3 == null) { - return Stream.empty(); - } + // Uncompact + @Deprecated + @Procedure(name = "com.neo4jh3.uncompactString", mode = Mode.READ) + @Description("CALL com.neo4jh3.uncompactString(listCells, h3Resolution)") + public Stream uncompactString(@Name("listCells") List listCells, @Name("h3Res") Long h3Res) throws InterruptedException { + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (h3 == null) { + return Stream.empty(); + } - final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); - if (h3Resolution > 1 && h3Resolution < 15) { - Integer maxRes = 0; - Integer curRes = 0; + final int h3Resolution = h3Res == null ? DEFAULT_H3_RESOLUTION : h3Res.intValue(); + if (h3Resolution > 1 && h3Resolution < 15) { + Integer maxRes = 0; + Integer curRes = 0; - ListIterator iterator = listCells.listIterator(); - while (iterator.hasNext()) { - curRes = h3.getResolution(iterator.next()); - if (curRes.compareTo(maxRes)>0){ - maxRes = curRes; + ListIterator iterator = listCells.listIterator(); + while (iterator.hasNext()) { + curRes = h3.getResolution(iterator.next()); + if (curRes.compareTo(maxRes)>0){ + maxRes = curRes; + } + } + if (h3Resolution >= maxRes){ + return h3.uncompactCellAddresses(listCells,h3Resolution) + .stream() + .map(H3StringAddress::of); + } else { + List ringList = null; + ringList = Collections.singletonList("-2"); + return ringList.stream().map(H3StringAddress::of); } - } - if (h3Resolution >= maxRes){ - return h3.uncompactCellAddresses(listCells,h3Resolution) - .stream() - .map(H3StringAddress::of); } else { List ringList = null; ringList = Collections.singletonList("-2"); return ringList.stream().map(H3StringAddress::of); } - } else { - List ringList = null; - ringList = Collections.singletonList("-2"); - return ringList.stream().map(H3StringAddress::of); } -} - // Experimental write to db procedure -@SuppressWarnings("unused") -@Procedure(name = "com.neo4jh3.writeH3ToDB", mode = Mode.WRITE) -@Description("CALL com.neo4jh3.writeH3ToDB(listCells, strLabel, strProperty, txSize)") -public Stream writeH3ToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { - String returnMessage = ""; - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (strLabel.isBlank() || strProperty.isBlank()){ - returnMessage = "-5"; - //throw new InterruptedException("Empty Label and/or Property"); - } else { - if (txSize < 1) { - txSize = 10000L; - } - Integer count = 0; - Long curRes = 0L; - Throwable txEx = null; - ListIterator iterator = listCells.listIterator(); - Transaction tx = db.beginTx(); - try { - while (iterator.hasNext()) { - curRes = iterator.next(); - Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); - if (h3Node == null) { - h3Node = tx.createNode(Label.label(strLabel)); - h3Node.setProperty(strProperty,curRes); - } - - if (count % txSize == 0) { - tx.commit(); - tx = db.beginTx(); + // Experimental write to db procedure + @SuppressWarnings("unused") + @Deprecated + @Procedure(name = "com.neo4jh3.writeH3ToDB", mode = Mode.WRITE) + @Description("CALL com.neo4jh3.writeH3ToDB(listCells, strLabel, strProperty, txSize)") + public Stream writeH3ToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank()){ + returnMessage = "-5"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 0; + Long curRes = 0L; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + Transaction tx = db.beginTx(); + try { + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; } - count++; + tx.commit(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); } - tx.commit(); - } catch (Throwable ex) { - txEx = ex; - System.out.println(ex); + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); } - } - if (returnMessage.isBlank()){ - return Stream.of(new StringResult("Finished")); - } else { - return Stream.of(new StringResult(returnMessage)); } -} - // Experimental write to db procedure -@SuppressWarnings("unused") -@Procedure(name = "com.neo4jh3.writeH3StringToDB", mode = Mode.WRITE) -@Description("CALL com.neo4jh3.writeH3StringToDB(listCells, strLabel, strProperty, txSize)") -public Stream writeH3StringToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { - String returnMessage = ""; - if (listCells == null) { - throw new InterruptedException("invalid list of hex addresses"); - } - if (strLabel.isBlank() || strProperty.isBlank()){ - returnMessage = "Empty Label and/or Property"; - //throw new InterruptedException("Empty Label and/or Property"); - } else { - if (txSize < 1) { - txSize = 10000L; - } - Integer count = 0; - String curRes = ""; - Throwable txEx = null; - ListIterator iterator = listCells.listIterator(); - Transaction tx = db.beginTx(); - try { - while (iterator.hasNext()) { - curRes = iterator.next(); - Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); - if (h3Node == null) { - h3Node = tx.createNode(Label.label(strLabel)); - h3Node.setProperty(strProperty,curRes); - } - - if (count % txSize == 0) { - tx.commit(); - tx = db.beginTx(); + // Experimental write to db procedure + @SuppressWarnings("unused") + @Deprecated + @Procedure(name = "com.neo4jh3.writeH3StringToDB", mode = Mode.WRITE) + @Description("CALL com.neo4jh3.writeH3StringToDB(listCells, strLabel, strProperty, txSize)") + public Stream writeH3StringToDB(@Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("txSize") Long txSize) throws InterruptedException { + String returnMessage = ""; + if (listCells == null) { + throw new InterruptedException("invalid list of hex addresses"); + } + if (strLabel.isBlank() || strProperty.isBlank()){ + returnMessage = "Empty Label and/or Property"; + //throw new InterruptedException("Empty Label and/or Property"); + } else { + if (txSize < 1) { + txSize = 10000L; + } + Integer count = 0; + String curRes = ""; + Throwable txEx = null; + ListIterator iterator = listCells.listIterator(); + Transaction tx = db.beginTx(); + try { + while (iterator.hasNext()) { + curRes = iterator.next(); + Node h3Node = tx.findNode(Label.label(strLabel), strProperty, curRes); + if (h3Node == null) { + h3Node = tx.createNode(Label.label(strLabel)); + h3Node.setProperty(strProperty,curRes); + } + + if (count % txSize == 0) { + tx.commit(); + tx = db.beginTx(); + } + count++; } - count++; + tx.commit(); + } catch (Throwable ex) { + txEx = ex; + System.out.println(ex); } - tx.commit(); - } catch (Throwable ex) { - txEx = ex; - System.out.println(ex); + } + if (returnMessage.isBlank()){ + return Stream.of(new StringResult("Finished")); + } else { + return Stream.of(new StringResult(returnMessage)); } - } - if (returnMessage.isBlank()){ - return Stream.of(new StringResult("Finished")); - } else { - return Stream.of(new StringResult(returnMessage)); } -} // Experimental write to db procedure @SuppressWarnings("unused") + @Deprecated @Procedure(name = "com.neo4jh3.writeH3NodesRelsToDB", mode = Mode.WRITE) @Description("CALL com.neo4jh3.writeH3NodesRelsToDB(From Node, List of H3 Cells, To Node Label, To Node Property Name, RelationshipType, Transaction Size)") public Stream writeH3NodesRelsToDB(@Name("fromNode") Node fromNode, @Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("strRelationshipType") String strRelationshipType, @Name("txSize") Long txSize) throws InterruptedException { @@ -2920,6 +3154,7 @@ public Stream writeH3NodesRelsToDB(@Name("fromNode") Node fromNode } // Experimental write to db procedure + @Deprecated @Procedure(name = "com.neo4jh3.writeH3StringNodesRelsToDB", mode = Mode.WRITE) @Description("CALL com.neo4jh3.writeH3StringNodesRelsToDB(From Node, List of H3 Cells, To Node Label, To Node Property Name, RelationshipType, Transaction Size)") public Stream writeH3StringNodesRelsToDB(@Name("fromNode") Node fromNode, @Name("listCells") List listCells, @Name("strLabel") String strLabel, @Name("strProperty") String strProperty, @Name("strRelationshipType") String strRelationshipType, @Name("txSize") Long txSize) throws InterruptedException { diff --git a/src/test/java/com/neo4jh3/Neo4jH3Test.java b/src/test/java/com/neo4jh3/Neo4jH3Test.java index 7314ff8..e043d16 100644 --- a/src/test/java/com/neo4jh3/Neo4jH3Test.java +++ b/src/test/java/com/neo4jh3/Neo4jH3Test.java @@ -11,6 +11,7 @@ import org.neo4j.harness.Neo4j; import org.neo4j.harness.Neo4jBuilders; +import com.neo4jh3.uber.Neo4jH3; import com.neo4jh3.uber.Uberh3; import com.uber.h3core.H3CoreLoader; @@ -23,8 +24,8 @@ public class Neo4jH3Test { public void should_return_hex_address() throws InterruptedException { embeddedDatabaseServer = Neo4jBuilders.newInProcessBuilder() .withDisabledServer() - .withProcedure(Uberh3.class) - .withFunction(Uberh3.class) + .withProcedure(Neo4jH3.class) + .withFunction(Neo4jH3.class) .build(); driver = GraphDatabase.driver(embeddedDatabaseServer.boltURI()); @@ -32,470 +33,482 @@ public void should_return_hex_address() throws InterruptedException { Result result = null; /* - result = session.run("call com.neo4jh3.compactNumber(['85283473fffffff','8528342bfffffff']) yield value return value limit 1"); + result = session.run("call neo4jh3.compactNumber(['85283473fffffff','8528342bfffffff']) yield value return value limit 1"); assertEquals(599686042433355775L,result.single().get(0).asLong()); */ if (System.getProperty("os.name").toLowerCase().equalsIgnoreCase("mac os x")){ - result = session.run("return com.neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); + result = session.run("return neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); assertEquals(17.870163, result.single().get("value").asDouble(),0); - result = session.run("RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.centeraswkb(599686042433355775) AS value"); assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkt(599686042433355775) AS value"); assertEquals("\"POLYGON ((-121.91508 37.271356, -121.862223 37.353926, -121.92355 37.428341, -122.037735 37.420129, -122.090429 37.337556, -122.029101 37.263198, -121.91508 37.271356))\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkt(111) AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkt(111) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswktString('822d57fffffffff') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswktString('822d57fffffffff') AS value"); assertEquals("\"POLYGON ((38.777546 44.198571, 39.938746 42.736298, 42.150674 42.631271, 43.258395 44.047542, 42.146575 45.539505, 39.897167 45.559577, 38.777546 44.198571))\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswktString('111') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswktString('111') AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centeraswkt(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.centeraswkt(599686042433355775) AS value"); assertEquals("\"POINT (-121.976376 37.345793)\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkb(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkb(599686042433355775) AS value"); assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.centeraswktString('8009fffffffffff') AS value"); assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centerasgeojson(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.centerasgeojson(599686042433355775) AS value"); assertEquals("\"{\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-121.976376,37.345793]}\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centerasgeojsonString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.centerasgeojsonString('8009fffffffffff') AS value"); assertEquals("\"{\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[10.536199,64.7]}\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centerasgeojsonString('1234') AS value"); + result = session.run("RETURN neo4jh3.centerasgeojsonString('1234') AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centerasgeojson(1234) AS value"); + result = session.run("RETURN neo4jh3.centerasgeojson(1234) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); } if (System.getProperty("os.name").toLowerCase().startsWith("wind")){ - result = session.run("return com.neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); + result = session.run("return neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); assertEquals(17.870163466857125,result.single().get("value").asDouble(),0); - result = session.run("RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.centeraswkb(599686042433355775) AS value"); assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkt(599686042433355775) AS value"); assertEquals("\"POLYGON ((-121.91508 37.271356, -121.862223 37.353926, -121.92355 37.428341, -122.037735 37.420129, -122.090429 37.337556, -122.029101 37.263198, -121.91508 37.271356))\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centeraswkt(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.centeraswkt(599686042433355775) AS value"); assertEquals("\"POINT (-121.976376 37.345793)\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswktString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswktString('8009fffffffffff') AS value"); assertEquals("\"POLYGON ((-10.444978 63.095054, 5.523647 55.706768, 25.082722 58.401545, 31.83128 68.929958, 0.32561 73.310224, -10.444978 63.095054))\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkb(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkb(599686042433355775) AS value"); assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); + result = session.run("RETURN neo4jh3.centeraswktString('8009fffffffffff') AS value"); assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); } - result = session.run("RETURN com.neo4jh3.version() AS value"); + result = session.run("RETURN neo4jh3.version() AS value"); assertEquals("\"5.23.0\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value"); + result = session.run("RETURN neo4jh3.cellToLatLngString('892830926cfffff') AS value"); assertEquals("\"37.564248,-122.325306\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.cellToLatLng(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.cellToLatLng(599686042433355775) AS value"); assertEquals("\"37.345793,-121.976376\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3Validate(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.h3Validate(599686042433355775) AS value"); assertEquals(599686042433355775L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.h3ValidateString('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.h3ValidateString('85283473fffffff') AS value"); assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3ValidateString('zzz1234a') AS value"); + result = session.run("RETURN neo4jh3.h3ValidateString('zzz1234a') AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3Validate(337) AS value"); + result = session.run("RETURN neo4jh3.h3Validate(337) AS value"); assertEquals(-1L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.h3Validate(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.h3Validate(599686042433355775) AS value"); assertEquals(599686042433355775L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3Validate(371) AS value"); + result = session.run("RETURN neo4jh3.h3Validate(371) AS value"); assertEquals(-1L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3ValidateString('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.h3ValidateString('85283473fffffff') AS value"); assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3ValidateString('notvalidstring') AS value"); + result = session.run("RETURN neo4jh3.h3ValidateString('notvalidstring') AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.compactString(['85283473fffffff', '85283447fffffff', '8528347bfffffff', '85283463fffffff', '85283477fffffff', '8528340ffffffff', '8528340bfffffff', '85283457fffffff', '85283443fffffff', '8528344ffffffff', '852836b7fffffff', '8528346bfffffff', '8528346ffffffff', '85283467fffffff', '8528342bfffffff', '8528343bfffffff', '85283407fffffff', '85283403fffffff', '8528341bfffffff']) yield value return value limit 1"); + result = session.run("call neo4jh3.compactString(['85283473fffffff', '85283447fffffff', '8528347bfffffff', '85283463fffffff', '85283477fffffff', '8528340ffffffff', '8528340bfffffff', '85283457fffffff', '85283443fffffff', '8528344ffffffff', '852836b7fffffff', '8528346bfffffff', '8528346ffffffff', '85283467fffffff', '8528342bfffffff', '8528343bfffffff', '85283407fffffff', '85283403fffffff', '8528341bfffffff']) yield value return value limit 1"); assertEquals("\"85283447fffffff\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 5) yield value return value limit 1"); + result=session.run("call neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 5) yield value return value limit 1"); assertEquals(599686030622195711L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 1) yield value return value limit 1"); + result=session.run("call neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 1) yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.uncompactString(['85283447fffffff','8528340ffffffff','8528340bfffffff','85283457fffffff','85283443fffffff','8528344ffffffff','852836b7fffffff','8528342bfffffff','8528343bfffffff','85283407fffffff','85283403fffffff','8528341bfffffff','8428347ffffffff'],5) yield value return value limit 1"); + result = session.run("call neo4jh3.uncompactString(['85283447fffffff','8528340ffffffff','8528340bfffffff','85283457fffffff','85283443fffffff','8528344ffffffff','852836b7fffffff','8528342bfffffff','8528343bfffffff','85283407fffffff','85283403fffffff','8528341bfffffff','8428347ffffffff'],5) yield value return value limit 1"); assertEquals("\"85283447fffffff\"",result.single().get(0).toString()); - result = session.run("RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddressString( 37.8199, -122.4783, 13) AS value"); assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3HexAddressString( 97.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddressString( 97.8199, -122.4783, 13) AS value"); assertEquals("\"-3\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 16) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddressString( 37.8199, -122.4783, 16) AS value"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddress( 37.8199, -122.4783, 13) AS value"); assertEquals(635714569676958015L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 16) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddress( 37.8199, -122.4783, 16) AS value"); assertEquals(-2L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -222.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.h3HexAddress( 37.8199, -222.4783, 13) AS value"); assertEquals(-4L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3tostring(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.h3tostring(599686042433355775) AS value"); assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3tostring(22) AS value"); + result = session.run("RETURN neo4jh3.h3tostring(22) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.stringToH3('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.stringToH3('85283473fffffff') AS value"); assertEquals(599686042433355775L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.stringToH3('invalidhex') AS value"); + result = session.run("RETURN neo4jh3.stringToH3('invalidhex') AS value"); assertEquals(-1L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3ResolutionString('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.h3ResolutionString('85283473fffffff') AS value"); assertEquals(5L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3ResolutionString('notavalidhex') AS value"); + result = session.run("RETURN neo4jh3.h3ResolutionString('notavalidhex') AS value"); assertEquals(-1L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3Resolution(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.h3Resolution(599686042433355775) AS value"); assertEquals(5L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3Resolution(337) AS value"); + result = session.run("RETURN neo4jh3.h3Resolution(337) AS value"); assertEquals(-1L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.latlongash3String( 37.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3String( 37.8199, -122.4783, 13) AS value"); assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.latlongash3String( 107.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3String( 107.8199, -122.4783, 13) AS value"); assertEquals("\"-3\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.latlongash3String( 17.8199, -222.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3String( 17.8199, -222.4783, 13) AS value"); assertEquals("\"-4\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.latlongash3String( 17.8199, -122.4783, 22) AS value"); + result = session.run("RETURN neo4jh3.latlongash3String( 17.8199, -122.4783, 22) AS value"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.latlongash3( 37.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3( 37.8199, -122.4783, 13) AS value"); assertEquals(635714569676958015L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.latlongash3( 107.8199, -122.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3( 107.8199, -122.4783, 13) AS value"); assertEquals(-3L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.latlongash3( 17.8199, -222.4783, 13) AS value"); + result = session.run("RETURN neo4jh3.latlongash3( 17.8199, -222.4783, 13) AS value"); assertEquals(-4L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.latlongash3( 17.8199, -122.4783, 22) AS value"); + result = session.run("RETURN neo4jh3.latlongash3( 17.8199, -122.4783, 22) AS value"); assertEquals(-2L, result.single().get("value").asLong(),0); - result = session.run("return com.neo4jh3.h3RingsForDistance(6,7) as value"); + result = session.run("return neo4jh3.h3RingsForDistance(6,7) as value"); assertEquals(3, result.single().get("value").asInt()); - result = session.run("return com.neo4jh3.gridDistanceString('85283473fffffff','8528342bfffffff') as value"); + result = session.run("return neo4jh3.gridDistanceString('85283473fffffff','8528342bfffffff') as value"); assertEquals(2L,result.single().get("value").asLong(),0); - result = session.run("return com.neo4jh3.gridDistance(599686030622195711,599686015589810175) as value"); + result = session.run("return neo4jh3.gridDistance(599686030622195711,599686015589810175) as value"); assertEquals(2L,result.single().get("value").asLong(),0); - result = session.run("return com.neo4jh3.gridDistance(1234,599686015589810175) as value"); + result = session.run("return neo4jh3.gridDistance(1234,599686015589810175) as value"); assertEquals(-1L,result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.toparentString('892830926cfffff', 6) AS value"); + result = session.run("RETURN neo4jh3.toparentString('892830926cfffff', 6) AS value"); assertEquals("862830927ffffff", result.single().get("value").asString()); - result = session.run("RETURN com.neo4jh3.toparentString('892830926cfffff', 26) AS value"); + result = session.run("RETURN neo4jh3.toparentString('892830926cfffff', 26) AS value"); assertEquals("-2", result.single().get("value").asString()); - result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 3) AS value"); + result = session.run("RETURN neo4jh3.toparent(604197150066212863, 3) AS value"); assertEquals(590686371182542847L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 17) AS value"); + result = session.run("RETURN neo4jh3.toparent(604197150066212863, 17) AS value"); assertEquals(-2L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 13) AS value"); + result = session.run("RETURN neo4jh3.toparent(604197150066212863, 13) AS value"); assertEquals(-2L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.toparent(12345, 13) AS value"); + result = session.run("RETURN neo4jh3.toparent(12345, 13) AS value"); assertEquals(-1L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.cellToLatLng( 635714569676958015) AS value"); + result = session.run("RETURN neo4jh3.cellToLatLng( 635714569676958015) AS value"); assertEquals("\"37.819895,-122.478297\"", result.single().get("value").toString()); /* - result = session.run("RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value"); + result = session.run("RETURN neo4jh3.cellToLatLngString('892830926cfffff') AS value"); assertEquals("\"37.56424780593244,-122.3253058831214\"", result.single().get("value").toString()); */ - result = session.run("RETURN com.neo4jh3.cellToLatLngString('123') AS value"); + result = session.run("RETURN neo4jh3.cellToLatLngString('123') AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.cellToLatLng(123) AS value"); + result = session.run("RETURN neo4jh3.cellToLatLng(123) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("return com.neo4jh3.distanceBetweenHexes(3111,599686015589810175) as value"); + result = session.run("return neo4jh3.distanceBetweenHexes(3111,599686015589810175) as value"); assertEquals(-1.0,result.single().get("value").asDouble(),0); - result = session.run("return com.neo4jh3.distanceBetweenHexesString('8a2989352777fff','8a498935223ffff') as value"); + result = session.run("return neo4jh3.distanceBetweenHexesString('8a2989352777fff','8a498935223ffff') as value"); assertEquals(2360.820388,result.single().get("value").asDouble(),0); - result = session.run("return com.neo4jh3.distanceBetweenHexesString('123','8a498935223ffff') as value"); + result = session.run("return neo4jh3.distanceBetweenHexesString('123','8a498935223ffff') as value"); assertEquals(-1.0,result.single().get("value").asDouble(),0); - //result = session.run("return com.neo4jh3.cellToLatLng('8a2989352717fff') as value"); + //result = session.run("return neo4jh3.cellToLatLng('8a2989352717fff') as value"); //assertEquals("39.678106484915,-120.23540752726865",result.single().get("value").asString()); - result = session.run("RETURN com.neo4jh3.maxChild(599686042433355775, 10) AS value"); + result = session.run("RETURN neo4jh3.maxChild(599686042433355775, 10) AS value"); assertEquals(622204040416821247L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.maxChild(599686042433355775, 20) AS value"); + result = session.run("RETURN neo4jh3.maxChild(599686042433355775, 20) AS value"); assertEquals(-2L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.maxChild(123, 10) AS value"); + result = session.run("RETURN neo4jh3.maxChild(123, 10) AS value"); assertEquals(-1L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.minChild(599686042433355775, 10) AS value"); + result = session.run("RETURN neo4jh3.minChild(599686042433355775, 10) AS value"); assertEquals(622204039496499199L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.minChild(599686042433355775, 23) AS value"); + result = session.run("RETURN neo4jh3.minChild(599686042433355775, 23) AS value"); assertEquals(-2L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.minChild(123, 10) AS value"); + result = session.run("RETURN neo4jh3.minChild(123, 10) AS value"); assertEquals(-1L, result.single().get("value").asLong()); - result = session.run("RETURN com.neo4jh3.maxChildString('85283473fffffff', 10) AS value"); + result = session.run("RETURN neo4jh3.maxChildString('85283473fffffff', 10) AS value"); assertEquals("\"8a2834736db7fff\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.maxChildString('123', 10) AS value"); + result = session.run("RETURN neo4jh3.maxChildString('123', 10) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.maxChildString('85283473fffffff', 20) AS value"); + result = session.run("RETURN neo4jh3.maxChildString('85283473fffffff', 20) AS value"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.minChildString('85283473fffffff', 10) AS value"); + result = session.run("RETURN neo4jh3.minChildString('85283473fffffff', 10) AS value"); assertEquals("\"8a2834700007fff\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.minChildString('123', 10) AS value"); + result = session.run("RETURN neo4jh3.minChildString('123', 10) AS value"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.minChildString('85283473fffffff', 20) AS value"); + result = session.run("RETURN neo4jh3.minChildString('85283473fffffff', 20) AS value"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.h3ResolutionString('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.h3ResolutionString('85283473fffffff') AS value"); assertEquals(5L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.h3Resolution(599686042433355775) AS value"); + result = session.run("RETURN neo4jh3.h3Resolution(599686042433355775) AS value"); assertEquals(5L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.angleBetweenPoints(40.123,-78.111,40.555,-78.910) AS value"); + result = session.run("RETURN neo4jh3.angleBetweenPoints(40.123,-78.111,40.555,-78.910) AS value"); assertEquals(305.607560, result.single().get("value").asDouble(),0); /* Procedures */ - result=session.run("call com.neo4jh3.gridDisk(599686042433355775,1) yield value return value limit 1"); + result = session.run("call neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value limit 1"); + assertEquals(613196571542028287L,result.single().get(0).asLong()); + + result = session.run("call neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result = session.run("call neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value limit 1"); + assertEquals("\"8828308703fffff\"",result.single().get(0).toString()); + + result = session.run("call neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result=session.run("call neo4jh3.gridDisk(599686042433355775,1) yield value return value limit 1"); assertEquals(599686042433355775L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.gridDisk(123,1) yield value return value limit 1"); + result=session.run("call neo4jh3.gridDisk(123,1) yield value return value limit 1"); assertEquals(-1L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.gridDisk(599686042433355775,-3) yield value return value limit 1"); + result=session.run("call neo4jh3.gridDisk(599686042433355775,-3) yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.gridDiskString('85283473fffffff',1) yield value return value limit 1"); + result=session.run("call neo4jh3.gridDiskString('85283473fffffff',1) yield value return value limit 1"); assertEquals("\"85283473fffffff\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.gridDiskString('85283473fffffff',-3) yield value return value limit 1"); + result=session.run("call neo4jh3.gridDiskString('85283473fffffff',-3) yield value return value limit 1"); assertEquals("\"-2\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.gridDiskString('12345',1) yield value return value limit 1"); + result=session.run("call neo4jh3.gridDiskString('12345',1) yield value return value limit 1"); assertEquals("\"-1\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.tochildren(12345,1) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildren(12345,1) yield value return value limit 1"); assertEquals(-1L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.tochildren(599686042433355775,0) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildren(599686042433355775,0) yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.tochildren(599686042433355775,6) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildren(599686042433355775,6) yield value return value limit 1"); assertEquals(604189641121202175L,result.single().get(0).asLong()); - result=session.run("call com.neo4jh3.tochildrenString('12345',1) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildrenString('12345',1) yield value return value limit 1"); assertEquals("\"-1\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.tochildrenString('85283473fffffff',0) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildrenString('85283473fffffff',0) yield value return value limit 1"); assertEquals("\"-2\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.tochildrenString('85283473fffffff',6) yield value return value limit 1"); + result=session.run("call neo4jh3.tochildrenString('85283473fffffff',6) yield value return value limit 1"); assertEquals("\"862834707ffffff\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); assertEquals(608692971759468543L,result.single().get(0).asLong(),0); - result=session.run("call com.neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong(),0); - result=session.run("call com.neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); assertEquals("\"872830866ffffff\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); assertEquals("\"-2\"",result.single().get(0).toString()); - result=session.run("call com.neo4jh3.polygonIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); assertEquals(608692975685337087L, result.single().get(0).asLong(),0); - result=session.run("call com.neo4jh3.polygonIntersectionString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.polygonIntersectionString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); assertEquals("\"872830950ffffff\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.multilineash3('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value limit 1"); assertEquals(631243922688246783L, result.single().get(0).asLong(),0); - result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.multilineash3('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong(),0); - result = session.run("call com.neo4jh3.multilineash3String('ZZZ((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',12, 'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.multilineash3String('ZZZ((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',12, 'lonlat') yield value return value limit 1"); assertEquals("\"-1\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797 ), (-74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.multilineash3String('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797 ), (-74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); assertEquals("\"-2\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); + result = session.run("call neo4jh3.multilineash3String('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); assertEquals("\"8c2a100800925ff\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING(( -73.99311 40.73669), ( -73.99265 40.73733), ( -74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); + result = session.run("call neo4jh3.multilineash3String('MULTILINESTRING(( -73.99311 40.73669), ( -73.99265 40.73733), ( -74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); assertEquals("\"8c2a100800925ff\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.lineash3String('ZZZ((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.lineash3String('ZZZ((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); assertEquals("\"-1\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.lineash3String('LINESTRING((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.lineash3String('LINESTRING((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); assertEquals("\"87283409affffff\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.lineash3('ZZZ((-121.915080 37.271355), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.lineash3('ZZZ((-121.915080 37.271355), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); assertEquals(-1L, result.single().get(0).asLong(),0); - result = session.run("call com.neo4jh3.lineash3('LINESTRING((73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), (-74.00265431029018 40.93733046783797 ))',12, 'lonlat') yield value return value limit 1"); + result = session.run("call neo4jh3.lineash3('LINESTRING((73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), (-74.00265431029018 40.93733046783797 ))',12, 'lonlat') yield value return value limit 1"); assertEquals(631243922688264703L, result.single().get(0).asLong(),0); /* Geography tests */ - result = session.run("RETURN com.neo4jh3.pointash3('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); + result = session.run("RETURN neo4jh3.pointash3('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); assertEquals(635714569676958015L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.pointash3('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); + result = session.run("RETURN neo4jh3.pointash3('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); assertEquals(635714569676958015L, result.single().get("value").asLong(),0); - result = session.run("RETURN com.neo4jh3.pointash3('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); + result = session.run("RETURN neo4jh3.pointash3('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); assertEquals(-2L,result.single().get(0).asLong(),0); - result = session.run("RETURN com.neo4jh3.pointash3String('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); + result = session.run("RETURN neo4jh3.pointash3String('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.pointash3String('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); + result = session.run("RETURN neo4jh3.pointash3String('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.pointash3String('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); + result = session.run("RETURN neo4jh3.pointash3String('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.ispentagon(590112357393367039) AS value"); + result = session.run("RETURN neo4jh3.ispentagon(590112357393367039) AS value"); assertEquals(true, result.single().get("value").asBoolean()); - result = session.run("RETURN com.neo4jh3.ispentagon(12345) AS value"); + result = session.run("RETURN neo4jh3.ispentagon(12345) AS value"); assertEquals(false, result.single().get("value").asBoolean()); - result = session.run("RETURN com.neo4jh3.ispentagonString('85283473fffffff') AS value"); + result = session.run("RETURN neo4jh3.ispentagonString('85283473fffffff') AS value"); assertEquals(false, result.single().get("value").asBoolean()); - result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); assertEquals(635714569676958015L, result.single().get("value").asLong(),0); - result = session.run("call com.neo4jh3.gridpathlatlon(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlon(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); assertEquals(-3L, result.single().get("value").asLong(),0); - result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); assertEquals(-2L, result.single().get("value").asLong(),0); - result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); assertEquals(-4L, result.single().get("value").asLong(),0); - result = session.run("call com.neo4jh3.gridpathlatlonString(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlonString(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); assertEquals("\"-3\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); assertEquals("\"-4\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + result = session.run("call neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); - result=session.run("call com.neo4jh3.linepolyIntersection(['37.271355,-121.915080','37.353926,-121.862223','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798','37.271355,-121.915080'],[],'LINESTRING(( 37.271355 -121.915080), (37.353926 -121.862223))',7,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.linepolyIntersection(['37.271355,-121.915080','37.353926,-121.862223','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798','37.271355,-121.915080'],[],'LINESTRING(( 37.271355 -121.915080), (37.353926 -121.862223))',7,'latlon') yield value return value limit 1"); assertEquals(608693241537101823L, result.single().get(0).asLong(),0); - result=session.run("call com.neo4jh3.linepolyIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],'LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',27,'latlon') yield value return value limit 1"); + result=session.run("call neo4jh3.linepolyIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],'LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',27,'latlon') yield value return value limit 1"); assertEquals(-2L, result.single().get(0).asLong(),0); - result = session.run("call com.neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546,-84.36414611386687 33.71303657522174,-84.36409515189553 33.71303657522174,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); + result = session.run("call neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546,-84.36414611386687 33.71303657522174,-84.36409515189553 33.71303657522174,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); assertEquals(636217124138601599L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546, -84.36414611386687 33.71303657522174 ,-84.36409515189553 33.71303657522174 ,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); + result = session.run("call neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546, -84.36414611386687 33.71303657522174 ,-84.36409515189553 33.71303657522174 ,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); assertEquals(636217124138601599L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); + result = session.run("call neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); assertEquals(635758222702368959L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',19) yield value return value limit 1"); + result = session.run("call neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',19) yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.polygonash3String('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); + result = session.run("call neo4jh3.polygonash3String('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); assertEquals("\"8d2aabc333558bf\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); + result = session.run("call neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); assertEquals(-2L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return value limit 1"); + result = session.run("call neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return value limit 1"); assertEquals(613240230178193407L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return count(value)"); + result = session.run("call neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return count(value)"); assertEquals(162L,result.single().get(0).asLong()); - result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); + result = session.run("call neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); assertEquals("\"-2\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value limit 1"); + result = session.run("call neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value limit 1"); assertEquals("\"882a100f35fffff\"", result.single().get("value").toString()); - result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return count(value)"); + result = session.run("call neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return count(value)"); assertEquals(5L,result.single().get(0).asLong()); } diff --git a/src/test/java/com/neo4jh3/UberH3Test.java b/src/test/java/com/neo4jh3/UberH3Test.java new file mode 100644 index 0000000..15ace42 --- /dev/null +++ b/src/test/java/com/neo4jh3/UberH3Test.java @@ -0,0 +1,519 @@ +package com.neo4jh3; + +import org.assertj.core.api.Assertions; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.neo4j.driver.Driver; +import org.neo4j.driver.GraphDatabase; +import org.neo4j.driver.Result; +import org.neo4j.driver.Session; +import org.neo4j.harness.Neo4j; +import org.neo4j.harness.Neo4jBuilders; + +import com.neo4jh3.uber.Neo4jH3; +import com.neo4jh3.uber.Uberh3; +import com.uber.h3core.H3CoreLoader; + + +public class UberH3Test { + private static Driver driver; + private static Neo4j embeddedDatabaseServer; + + @Test + public void should_return_hex_address() throws InterruptedException { + embeddedDatabaseServer = Neo4jBuilders.newInProcessBuilder() + .withDisabledServer() + .withProcedure(Uberh3.class) + .withFunction(Uberh3.class) + .build(); + driver = GraphDatabase.driver(embeddedDatabaseServer.boltURI()); + + try (Session session = driver.session()) { + Result result = null; + + /* + result = session.run("call com.neo4jh3.compactNumber(['85283473fffffff','8528342bfffffff']) yield value return value limit 1"); + assertEquals(599686042433355775L,result.single().get(0).asLong()); + */ + if (System.getProperty("os.name").toLowerCase().equalsIgnoreCase("mac os x")){ + result = session.run("return com.neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); + assertEquals(17.870163, result.single().get("value").asDouble(),0); + + result = session.run("RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value"); + assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); + assertEquals("\"POLYGON ((-121.91508 37.271356, -121.862223 37.353926, -121.92355 37.428341, -122.037735 37.420129, -122.090429 37.337556, -122.029101 37.263198, -121.91508 37.271356))\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkt(111) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswktString('822d57fffffffff') AS value"); + assertEquals("\"POLYGON ((38.777546 44.198571, 39.938746 42.736298, 42.150674 42.631271, 43.258395 44.047542, 42.146575 45.539505, 39.897167 45.559577, 38.777546 44.198571))\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswktString('111') AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centeraswkt(599686042433355775) AS value"); + assertEquals("\"POINT (-121.976376 37.345793)\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkb(599686042433355775) AS value"); + assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); + assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centerasgeojson(599686042433355775) AS value"); + assertEquals("\"{\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-121.976376,37.345793]}\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centerasgeojsonString('8009fffffffffff') AS value"); + assertEquals("\"{\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[10.536199,64.7]}\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centerasgeojsonString('1234') AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centerasgeojson(1234) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + } + + if (System.getProperty("os.name").toLowerCase().startsWith("wind")){ + result = session.run("return com.neo4jh3.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); + assertEquals(17.870163466857125,result.single().get("value").asDouble(),0); + + result = session.run("RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value"); + assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); + assertEquals("\"POLYGON ((-121.91508 37.271356, -121.862223 37.353926, -121.92355 37.428341, -122.037735 37.420129, -122.090429 37.337556, -122.029101 37.263198, -121.91508 37.271356))\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centeraswkt(599686042433355775) AS value"); + assertEquals("\"POINT (-121.976376 37.345793)\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswktString('8009fffffffffff') AS value"); + assertEquals("\"POLYGON ((-10.444978 63.095054, 5.523647 55.706768, 25.082722 58.401545, 31.83128 68.929958, 0.32561 73.310224, -10.444978 63.095054))\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkb(599686042433355775) AS value"); + assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); + assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); + assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); + + } + + result = session.run("RETURN com.neo4jh3.version() AS value"); + assertEquals("\"5.23.0\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value"); + assertEquals("\"37.564248,-122.325306\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.cellToLatLng(599686042433355775) AS value"); + assertEquals("\"37.345793,-121.976376\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3Validate(599686042433355775) AS value"); + assertEquals(599686042433355775L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.h3ValidateString('85283473fffffff') AS value"); + assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3ValidateString('zzz1234a') AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3Validate(337) AS value"); + assertEquals(-1L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.h3Validate(599686042433355775) AS value"); + assertEquals(599686042433355775L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3Validate(371) AS value"); + assertEquals(-1L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3ValidateString('85283473fffffff') AS value"); + assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3ValidateString('notvalidstring') AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.compactString(['85283473fffffff', '85283447fffffff', '8528347bfffffff', '85283463fffffff', '85283477fffffff', '8528340ffffffff', '8528340bfffffff', '85283457fffffff', '85283443fffffff', '8528344ffffffff', '852836b7fffffff', '8528346bfffffff', '8528346ffffffff', '85283467fffffff', '8528342bfffffff', '8528343bfffffff', '85283407fffffff', '85283403fffffff', '8528341bfffffff']) yield value return value limit 1"); + assertEquals("\"85283447fffffff\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 5) yield value return value limit 1"); + assertEquals(599686030622195711L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.uncompact([599686030622195711,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647,595182446027210751], 1) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.uncompactString(['85283447fffffff','8528340ffffffff','8528340bfffffff','85283457fffffff','85283443fffffff','8528344ffffffff','852836b7fffffff','8528342bfffffff','8528343bfffffff','85283407fffffff','85283403fffffff','8528341bfffffff','8428347ffffffff'],5) yield value return value limit 1"); + assertEquals("\"85283447fffffff\"",result.single().get(0).toString()); + + result = session.run("RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 13) AS value"); + assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3HexAddressString( 97.8199, -122.4783, 13) AS value"); + assertEquals("\"-3\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 16) AS value"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 13) AS value"); + assertEquals(635714569676958015L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 16) AS value"); + assertEquals(-2L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3HexAddress( 37.8199, -222.4783, 13) AS value"); + assertEquals(-4L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3tostring(599686042433355775) AS value"); + assertEquals("\"85283473fffffff\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.h3tostring(22) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.stringToH3('85283473fffffff') AS value"); + assertEquals(599686042433355775L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.stringToH3('invalidhex') AS value"); + assertEquals(-1L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3ResolutionString('85283473fffffff') AS value"); + assertEquals(5L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3ResolutionString('notavalidhex') AS value"); + assertEquals(-1L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3Resolution(599686042433355775) AS value"); + assertEquals(5L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3Resolution(337) AS value"); + assertEquals(-1L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.latlongash3String( 37.8199, -122.4783, 13) AS value"); + assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.latlongash3String( 107.8199, -122.4783, 13) AS value"); + assertEquals("\"-3\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.latlongash3String( 17.8199, -222.4783, 13) AS value"); + assertEquals("\"-4\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.latlongash3String( 17.8199, -122.4783, 22) AS value"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.latlongash3( 37.8199, -122.4783, 13) AS value"); + assertEquals(635714569676958015L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.latlongash3( 107.8199, -122.4783, 13) AS value"); + assertEquals(-3L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.latlongash3( 17.8199, -222.4783, 13) AS value"); + assertEquals(-4L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.latlongash3( 17.8199, -122.4783, 22) AS value"); + assertEquals(-2L, result.single().get("value").asLong(),0); + + result = session.run("return com.neo4jh3.h3RingsForDistance(6,7) as value"); + assertEquals(3, result.single().get("value").asInt()); + + result = session.run("return com.neo4jh3.gridDistanceString('85283473fffffff','8528342bfffffff') as value"); + assertEquals(2L,result.single().get("value").asLong(),0); + + result = session.run("return com.neo4jh3.gridDistance(599686030622195711,599686015589810175) as value"); + assertEquals(2L,result.single().get("value").asLong(),0); + + result = session.run("return com.neo4jh3.gridDistance(1234,599686015589810175) as value"); + assertEquals(-1L,result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.toparentString('892830926cfffff', 6) AS value"); + assertEquals("862830927ffffff", result.single().get("value").asString()); + + result = session.run("RETURN com.neo4jh3.toparentString('892830926cfffff', 26) AS value"); + assertEquals("-2", result.single().get("value").asString()); + + result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 3) AS value"); + assertEquals(590686371182542847L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 17) AS value"); + assertEquals(-2L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.toparent(604197150066212863, 13) AS value"); + assertEquals(-2L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.toparent(12345, 13) AS value"); + assertEquals(-1L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.cellToLatLng( 635714569676958015) AS value"); + assertEquals("\"37.819895,-122.478297\"", result.single().get("value").toString()); + + /* + result = session.run("RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value"); + assertEquals("\"37.56424780593244,-122.3253058831214\"", result.single().get("value").toString()); + */ + + result = session.run("RETURN com.neo4jh3.cellToLatLngString('123') AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.cellToLatLng(123) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("return com.neo4jh3.distanceBetweenHexes(3111,599686015589810175) as value"); + assertEquals(-1.0,result.single().get("value").asDouble(),0); + + result = session.run("return com.neo4jh3.distanceBetweenHexesString('8a2989352777fff','8a498935223ffff') as value"); + assertEquals(2360.820388,result.single().get("value").asDouble(),0); + + result = session.run("return com.neo4jh3.distanceBetweenHexesString('123','8a498935223ffff') as value"); + assertEquals(-1.0,result.single().get("value").asDouble(),0); + + //result = session.run("return com.neo4jh3.cellToLatLng('8a2989352717fff') as value"); +//assertEquals("39.678106484915,-120.23540752726865",result.single().get("value").asString()); + result = session.run("RETURN com.neo4jh3.maxChild(599686042433355775, 10) AS value"); + assertEquals(622204040416821247L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.maxChild(599686042433355775, 20) AS value"); + assertEquals(-2L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.maxChild(123, 10) AS value"); + assertEquals(-1L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.minChild(599686042433355775, 10) AS value"); + assertEquals(622204039496499199L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.minChild(599686042433355775, 23) AS value"); + assertEquals(-2L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.minChild(123, 10) AS value"); + assertEquals(-1L, result.single().get("value").asLong()); + + result = session.run("RETURN com.neo4jh3.maxChildString('85283473fffffff', 10) AS value"); + assertEquals("\"8a2834736db7fff\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.maxChildString('123', 10) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.maxChildString('85283473fffffff', 20) AS value"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.minChildString('85283473fffffff', 10) AS value"); + assertEquals("\"8a2834700007fff\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.minChildString('123', 10) AS value"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.minChildString('85283473fffffff', 20) AS value"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + + result = session.run("RETURN com.neo4jh3.h3ResolutionString('85283473fffffff') AS value"); + assertEquals(5L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.h3Resolution(599686042433355775) AS value"); + assertEquals(5L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.angleBetweenPoints(40.123,-78.111,40.555,-78.910) AS value"); + assertEquals(305.607560, result.single().get("value").asDouble(),0); + + /* Procedures */ + + result = session.run("call com.neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value limit 1"); + assertEquals(613196571542028287L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.coverage(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],8,'lonlat') yield value return value limit 1"); + assertEquals("\"8828308703fffff\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.coverageString(['-122.481889,37.826683','122.479487,37.808548','-122.481889,37.826683','-122.479487,37.808548','-122.474150,37.808904','-122.476510,37.826935','-122.481889,37.826683'],17,'lonlat') yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.gridDisk(599686042433355775,1) yield value return value limit 1"); + assertEquals(599686042433355775L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.gridDisk(123,1) yield value return value limit 1"); + assertEquals(-1L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.gridDisk(599686042433355775,-3) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.gridDiskString('85283473fffffff',1) yield value return value limit 1"); + assertEquals("\"85283473fffffff\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.gridDiskString('85283473fffffff',-3) yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.gridDiskString('12345',1) yield value return value limit 1"); + assertEquals("\"-1\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.tochildren(12345,1) yield value return value limit 1"); + assertEquals(-1L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.tochildren(599686042433355775,0) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.tochildren(599686042433355775,6) yield value return value limit 1"); + assertEquals(604189641121202175L,result.single().get(0).asLong()); + + result=session.run("call com.neo4jh3.tochildrenString('12345',1) yield value return value limit 1"); + assertEquals("\"-1\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.tochildrenString('85283473fffffff',0) yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.tochildrenString('85283473fffffff',6) yield value return value limit 1"); + assertEquals("\"862834707ffffff\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + assertEquals(608692971759468543L,result.single().get(0).asLong(),0); + + result=session.run("call com.neo4jh3.polygonToCells(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong(),0); + + result=session.run("call com.neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + assertEquals("\"872830866ffffff\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.polygonToCellsString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],20,'latlon') yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result=session.run("call com.neo4jh3.polygonIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + assertEquals(608692975685337087L, result.single().get(0).asLong(),0); + + result=session.run("call com.neo4jh3.polygonIntersectionString(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],['37.9866,-123.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],7,'latlon') yield value return value limit 1"); + assertEquals("\"872830950ffffff\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value limit 1"); + assertEquals(631243922688246783L, result.single().get(0).asLong(),0); + + result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong(),0); + + result = session.run("call com.neo4jh3.multilineash3String('ZZZ((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), ( -74.00265431029018 40.93733046783797))',12, 'lonlat') yield value return value limit 1"); + assertEquals("\"-1\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((-73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797 ), (-74.00265431029018 40.93733046783797))',17, 'lonlat') yield value return value limit 1"); + assertEquals("\"-2\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((-73.99311 40.73669), (-73.99265 40.73733), (-74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); + assertEquals("\"8c2a100800925ff\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING(( -73.99311 40.73669), ( -73.99265 40.73733), ( -74.00265 40.93733))',12,'lonlat') yield value return value order by value limit 1"); + assertEquals("\"8c2a100800925ff\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.lineash3String('ZZZ((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.lineash3String('LINESTRING((-121.915080 37.271355 ), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + assertEquals("\"87283409affffff\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.lineash3('ZZZ((-121.915080 37.271355), (-121.862223 37.353926))',7,'lonlat') yield value return value limit 1"); + assertEquals(-1L, result.single().get(0).asLong(),0); + + result = session.run("call com.neo4jh3.lineash3('LINESTRING((73.99311953429248 40.736691045913472), (-73.99265431029018 40.73733046783797), (-74.00265431029018 40.93733046783797 ))',12, 'lonlat') yield value return value limit 1"); + assertEquals(631243922688264703L, result.single().get(0).asLong(),0); + + /* Geography tests */ + result = session.run("RETURN com.neo4jh3.pointash3('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); + assertEquals(635714569676958015L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.pointash3('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); + assertEquals(635714569676958015L, result.single().get("value").asLong(),0); + + result = session.run("RETURN com.neo4jh3.pointash3('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); + assertEquals(-2L,result.single().get(0).asLong(),0); + + result = session.run("RETURN com.neo4jh3.pointash3String('POINT(37.8199 -122.4783)',13, 'latlon') AS value"); + assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.pointash3String('POINT(-122.4783 37.8199)',13, 'lonlat') AS value"); + assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.pointash3String('POINT(-122.4783 37.8199)',16, 'lonlat') AS value"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("RETURN com.neo4jh3.ispentagon(590112357393367039) AS value"); + assertEquals(true, result.single().get("value").asBoolean()); + + result = session.run("RETURN com.neo4jh3.ispentagon(12345) AS value"); + assertEquals(false, result.single().get("value").asBoolean()); + + result = session.run("RETURN com.neo4jh3.ispentagonString('85283473fffffff') AS value"); + assertEquals(false, result.single().get("value").asBoolean()); + + result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + assertEquals(635714569676958015L, result.single().get("value").asLong(),0); + + result = session.run("call com.neo4jh3.gridpathlatlon(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + assertEquals(-3L, result.single().get("value").asLong(),0); + + result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); + assertEquals(-2L, result.single().get("value").asLong(),0); + + result = session.run("call com.neo4jh3.gridpathlatlon(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); + assertEquals(-4L, result.single().get("value").asLong(),0); + + result = session.run("call com.neo4jh3.gridpathlatlonString(97.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + assertEquals("\"-3\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 23) yield value return value limit 1"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -222.5, 13) yield value return value limit 1"); + assertEquals("\"-4\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.gridpathlatlonString(37.8199, -122.4783, 47.8199, -122.5, 13) yield value return value limit 1"); + assertEquals("\"8d283087022a93f\"", result.single().get("value").toString()); + + result=session.run("call com.neo4jh3.linepolyIntersection(['37.271355,-121.915080','37.353926,-121.862223','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798','37.271355,-121.915080'],[],'LINESTRING(( 37.271355 -121.915080), (37.353926 -121.862223))',7,'latlon') yield value return value limit 1"); + assertEquals(608693241537101823L, result.single().get(0).asLong(),0); + + result=session.run("call com.neo4jh3.linepolyIntersection(['37.7866,-122.3805','37.7198,-122.3544','37.7076,-122.5123','37.7835,-122.5247','37.8151,-122.4798'],[],'LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',27,'latlon') yield value return value limit 1"); + assertEquals(-2L, result.single().get(0).asLong(),0); + + result = session.run("call com.neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546,-84.36414611386687 33.71303657522174,-84.36409515189553 33.71303657522174,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); + assertEquals(636217124138601599L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.polygonash3('POLYGON((-84.3641541604937 33.71316821215546, -84.36414611386687 33.71303657522174 ,-84.36409515189553 33.71303657522174 ,-84.36410319852232 33.71317267442025,-84.3641541604937 33.71316821215546))',13) yield value return value limit 1"); + assertEquals(636217124138601599L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); + assertEquals(635758222702368959L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.polygonash3('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',19) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.polygonash3String('POLYGON((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420))',13) yield value return value limit 1"); + assertEquals("\"8d2aabc333558bf\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return value limit 1"); + assertEquals(613240230178193407L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.multipolygonash3('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',8) yield value return count(value)"); + assertEquals(162L,result.single().get(0).asLong()); + + result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-77.436031 38.471420, -77.395123 38.536569, -77.294124 38.511703, -77.310611 38.395709, -77.436031 38.471420)))',19) yield value return value limit 1"); + assertEquals("\"-2\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return value limit 1"); + assertEquals("\"882a100f35fffff\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.multipolygonash3String('MULTIPOLYGON(((-73.927881 40.769855, -73.915189 40.763915,-73.923600 40.753839, -73.944151 40.759309, -73.927881 40.769855)),((-73.945007 40.796650, -73.944668 40.791605, -73.946504 40.789007, -73.949935 40.790397)))',8) yield value return count(value)"); + assertEquals(5L,result.single().get(0).asLong()); + + } + driver.close(); + embeddedDatabaseServer.close(); + + } +}