diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc1ee4..5f06aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG - Neo4jH3 +## 5.12 2023-10-20 +* [Added] Tested through Neo4j 5.12 +* [Added] Added com.neo4jh3.polygonIntersection and com.neo4jh3.polygonIntersectionString to return the h3 addresses that are in the intersection between two polygons +* [Added] Added dependency on org.apache.commons.commons-math3 for decimal rounding +* [Updated] Updated com.neo4jh3.cellToLatLng, com.neo4jh3.cellToLatLngString, com.neo4jh3.centeraswkb, com.neo4jh3.centeraswkbString, com.neo4jh3.centeraswkt, com.neo4jh3.centeraswktString, com.neo4jh3.boundaryaswkt, com.neo4jh3.boundaryaswktString, com.neo4jh3.boundaryaswkb, com.neo4jh3.boundaryaswkbString, com.neo4jh3.centerasgeojson, com.neo4jh3.centerasgeojsonString, com.neo4jh3.boundaryasgeojson and com.neo4jh3.boundaryasgeojsonString to return results in lon / lat format at 6 decimal precision. +* [Updated] - Multiple fixes within the Documentation.md file + + + ## 5.11 2023-08-18 * [Added] Tested through Neo4j 5.11 * [Updated] Updated the com.neo4jh3.pointash3String and com.neo4jh3.pointash3 functions to take a 3rd parameter to indicate if the point is in lat/lon format or lon/lat format. diff --git a/Documentation.md b/Documentation.md index 0ccdbd2..cff31ac 100644 --- a/Documentation.md +++ b/Documentation.md @@ -104,7 +104,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.boundaryasgeojson(599686042433355775) AS value - {"type":"Polygon","coordinates":[[[-121.91508032706,37.271355866732],[-121.86222328902,37.353926450852],[-121.9235499963,37.428341186094],[-122.03773496427 37.420128677678],[-122.09042892904,37.337556084353],[-122.02910130919,37.263197974618],[-121.91508032706,37.271355866732]]]} + {"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 com.neo4jh3.boundaryasgeojson(1234) AS value -1 @@ -126,7 +126,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.boundaryasgeojsonString('8009fffffffffff') AS value - {"type":"Polygon","coordinates":[[[-10.444977544778,63.095054077525],[5.5236465492903,55.706768465152],[25.082722326708,58.401544870353],[31.831280499087,68.92995788194],[0.32561035194326,73.310223685444],[-10.444977544778,63.095054077525]]]} + {"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 com.neo4jh3.boundaryasgeojsonString('1234') AS value -1 @@ -203,7 +203,7 @@ If h3XellIdExpr is an invalid h3 address, the function returns -1. ### Example RETURN com.neo4jh3.cellToLatLng(635714569676958015) AS value - 37.81989535912348,-122.47829651373911 + 37.819895,-122.478297 RETURN com.neo4jh3.cellToLatLng(123) AS value -1 @@ -212,7 +212,7 @@ If h3XellIdExpr is an invalid h3 address, the function returns -1. Returns the center latitude and longitude of the input H3 cell. ### Syntax -RETURN com.neo4jh3.cellToLatLng( h3CellIdExpr ) AS value; +RETURN com.neo4jh3.cellToLatLngString( h3CellIdExpr ) AS value; ### Arguments * h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. @@ -225,7 +225,7 @@ If h3XellIdExpr is an invalid h3 address, the function returns -1. ### Example RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value - 37.56424780593244,-122.3253058831214 + 37.564248,-122.325306 RETURN com.neo4jh3.cellToLatLngString('notavalidhex') AS value -1 @@ -247,7 +247,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centerasgeojson(599686042433355775) AS value - {"type":"Point","coordinates":[-121.97637597255,37.345793375368]} + {"type":"Point","coordinates":[-121.976376,37.345793]} RETURN com.neo4jh3.centerasgeojson(1234) AS value -1 @@ -270,9 +270,9 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centerasgeojsonString('8009fffffffffff') AS value - {"type":"Point","coordinates":[64.70000013,10.53619908]} + {"type":"Point","coordinates":[10.536199,64.7]} - RETURN com.neo4jh3.centerasgeojsonString(1234) AS value + RETURN com.neo4jh3.centerasgeojsonString('1234') AS value -1 ## com.neo4jh3.centeraswkt( h3CellIdExpr ) @@ -292,7 +292,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centeraswkt(599686042433355775) AS value - POINT ( 37.34579337536848 -121.9763759725512 ) + POINT (-121.976376 37.345793) RETURN com.neo4jh3.centeraswkt(1234) AS value -1 @@ -314,7 +314,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value - POINT ( 64.70000012793487 10.53619907546767 ) + POINT (10.536199 64.7) RETURN com.neo4jh3.centeraswktString('1234') AS value -1 @@ -336,7 +336,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value - 00000000014042AC42F51330C7C05E7E7CF1A5AD49 + 0000000001C05E7E7CF1C3265B4042AC42F1ED17C6 RETURN com.neo4jh3.centeraswkb(1234) AS value -1 @@ -358,7 +358,7 @@ If h3CellIdExpr is invalid, the function returns -1 ### Example RETURN com.neo4jh3.centeraswkbString('8009fffffffffff') AS value - 000000000140502CCCCD562B4540251288AF6A8EE3 + 000000000140251288ACE24BBA40502CCCCCCCCCCD RETURN com.neo4jh3.centeraswkbString('1234') AS value -1 @@ -475,13 +475,13 @@ A value of the type of LONG representing, as a hexadecimal string, the H3 cell I * If longitudeExpr is not a valid longitude, the function returns -4. ### Example - RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.h3HexAddress(37.8199, -122.4783, 13) AS value 635714569676958015 - RETURN com.neo4jh3.h3HexAddress( 37.8199, -122.4783, 16) AS value + RETURN com.neo4jh3.h3HexAddress(37.8199, -122.4783, 16) AS value -2 - RETURN com.neo4jh3.h3HexAddress( 97.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.h3HexAddress(97.8199, -122.4783, 13) AS value -3 @@ -505,13 +505,13 @@ A value of the type of STRING representing, as a hexadecimal string, the H3 cell * If longitudeExpr is not a valid longitude, the function returns -4. ### Example - RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.h3HexAddressString(37.8199, -122.4783, 13) AS value 8d283087022a93f - RETURN com.neo4jh3.h3HexAddressString( 37.8199, -122.4783, 16) AS value + RETURN com.neo4jh3.h3HexAddressString(37.8199, -122.4783, 16) AS value -2 - RETURN com.neo4jh3.h3HexAddressString( 97.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.h3HexAddressString(97.8199, -122.4783, 13) AS value -3 ## com.neo4jh3.h3tostring( h3CellIdExpr ) @@ -602,6 +602,26 @@ If h3CellIdExpr is not a valid H3 cell ID, the function returns 0. RETURN com.neo4jh3.h3Validate(123411) AS value; -1 +## com.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 com.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 com.neo4jh3.h3ValidateString('85283447fffffff') AS value; + '85283447fffffff' + + RETURN com.neo4jh3.h3ValidateString('123411') AS value; + "-1" + + ## com.neo4jh3.ispentagon( h3CellIdExpr ) Returns true if the input LONG corresponds to a pentagonal H3 cell or not. @@ -635,9 +655,31 @@ If h3CellIdExpr is not a valid H3 cell ID, the function returns false; ### Example + RETURN com.neo4jh3.ispentagonString('830800fffffffff') AS value; + true + RETURN com.neo4jh3.ispentagonString('85283473fffffff') AS value; false +## com.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 com.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 com.neo4jh3.h3Validate(590112357393367039) AS value; + 590112357393367039 + + RETURN com.neo4jh3.h3Validate(1110) AS value; + -1 + ## com.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. @@ -679,16 +721,16 @@ A value of the type of LONG representing, as a hexadecimal string, the H3 cell I ### Example - RETURN com.neo4jh3.latlongash3( 37.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.latlongash3(37.8199, -122.4783, 13) AS value 635714569676958015 - RETURN com.neo4jh3.latlongash3( 37.8199, -122.4783, 16) AS value + RETURN com.neo4jh3.latlongash3(37.8199, -122.4783, 16) AS value -2 - RETURN com.neo4jh3.latlongash3( 97.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.latlongash3(97.8199, -122.4783, 13) AS value -3 - RETURN com.neo4jh3.latlongash3( 67.8199, -222.4783, 13) AS value + RETURN com.neo4jh3.latlongash3(67.8199, -222.4783, 13) AS value -4 ## com.neo4jh3.latlongash3String( latitude, longitude, resolution ) @@ -711,73 +753,18 @@ A value of the type of STRING representing, as a hexadecimal string, the H3 cell * If longitudeExpr is not a valid longitude, the function returns -4. * ### Example - RETURN com.neo4jh3.latlongash3String( 37.8199, -122.4783, 13) AS value + RETURN com.neo4jh3.latlongash3String(37.8199, -122.4783, 13) AS value 8d283087022a93f - RETURN com.neo4jh3.latlongash3String( 37.8199, -122.4783, 16) AS value + RETURN com.neo4jh3.latlongash3String(37.8199, -122.4783, 16) AS value -2 - RETURN com.neo4jh3.latlongash3String( 97.8199, -222.4783, 13) AS value + RETURN com.neo4jh3.latlongash3String(97.8199, -122.4783, 13) AS value -3 - RETURN com.neo4jh3.latlongash3String( 97.8199, -222.4783, 13) AS value + RETURN com.neo4jh3.latlongash3String(67.8199, -222.4783, 13) AS value -4 -## com.neo4jh3.lineash3( geographyExpr, resolutionExpr ) -Returns the H3 cell ID (as a LONG) corresponding to the provided LINESTRING at the specified resolution. - -### Syntax -RETURN com.neo4jh3.lineash3( 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 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 com.neo4jh3.lineash3('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',13) AS value - 635714810904422079 - - RETURN com.neo4jh3.lineash3('zzz(37.8199 -122.4783)',13) AS value - -1 - - RETURN com.neo4jh3.lineash3('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) AS value - -2 - -## com.neo4jh3.lineash3String( geographyExpr, resolutionExpr ) -Returns the H3 cell ID (as a STRING) corresponding to the provided LINESTRING at the specified resolution. - -### Syntax -RETURN com.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 the H3 cell ID (as a LONG) 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 point, the function returns -1 - -If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 - -### Example - RETURN com.neo4jh3.lineash3String('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',13) AS value - 8d283409a69a6bf - - RETURN com.neo4jh3.lineash3String('zzz(37.8199 -122.4783)',13) AS value - -1 - - RETURN com.neo4jh3.lineash3String('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) AS value - -2 ## com.neo4jh3.maxChild( h3CellIdExpr, resolutionExpr ) Returns the child of minimum value of the input H3 cell at the specified resolution. @@ -810,7 +797,7 @@ If resolutionExpr is an invalid h3 resolution, the function returns -2. Returns the child of maximum value of the input H3 cell at the specified resolution. ### Syntax -RETURN com.neo4jh3.maxChild( h3CellIdExpr, resolutionExpr ) AS value +RETURN com.neo4jh3.maxChildString( h3CellIdExpr, resolutionExpr ) AS value ### Arguments * h3CellId1Expr: A hexadecimal STRING expression representing an H3 cell ID. @@ -825,13 +812,13 @@ If resolutionExpr is an invalid h3 resolution, the function returns -2. ### Example RETURN com.neo4jh3.maxChildString('85283473fffffff', 10) AS value - 8a2834736db7fff + '8a2834736db7fff' RETURN com.neo4jh3.maxChildString('123',10) AS value - -1 + '-1' RETURN com.neo4jh3.maxChildString('85283473fffffff',27) AS value - -2 + '-2' ## com.neo4jh3.minChild( h3CellIdExpr, resolutionExpr ) Returns the child of minimum value of the input H3 cell at the specified resolution. @@ -879,69 +866,13 @@ If resolutionExpr is an invalid resolution or smaller than h3_resolution(h3CellI ### Example RETURN com.neo4jh3.minChildString('85283473fffffff', 10) AS value - 8a2834700007fff + '8a2834700007fff' RETURN com.neo4jh3.minChildString('123',10) AS value - -1 + '-1' RETURN com.neo4jh3.minChildString('85283473fffffff',27) AS value - -2 - -## com.neo4jh3.multilineash3( geographyExpr, resolutionExpr ) -Returns the H3 cell ID (as a LONG) corresponding to the provided MULTILINESTRING at the specified resolution. - -### Syntax -RETURN com.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. - -### 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 com.neo4jh3.multilineash3('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',13) AS value - 635714810904422079 - - RETURN com.neo4jh3.multilineash3('zzz(37.8199 -122.4783)',13) AS value - -1 - - RETURN com.neo4jh3.multilineash3('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) AS value - -2 - -## com.neo4jh3.multilineash3String( geographyExpr, resolutionExpr ) -Returns the H3 cell ID (as a STRING) corresponding to the provided MULTILINESTRING at the specified resolution. - -### Syntax -RETURN com.neo4jh3.multilineash3String( 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. - -### Returns -Returns the H3 cell ID (as a LONG) 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 point, the function returns -1 - -If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 - -### Example - RETURN com.neo4jh3.multilineash3String('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',13) AS value - 8d283409a69a6bf - - RETURN com.neo4jh3.multilineash3String('zzz(37.8199 -122.4783)',13) AS value - -1 - - RETURN com.neo4jh3.multilineash3String('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) AS value - -2 + '-2' ## com.neo4jh3.pointash3( geographyExpr, resolutionExpr, LatLonOrder ) Returns the H3 cell ID (as a LONG) corresponding to the provided point at the specified resolution. @@ -1031,11 +962,11 @@ Returns the H3 cells that are within (grid) distance k of the origin cell. The s CALL com.neo4jh3.gridDisk( h3CellIdExpr, kExpr ) yield value return value; ### Arguments -* h3CellIdExpr: A STRING expression representing an H3 cell ID. +* 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 values of the same type as the type of the h3CellIdExpr expression, 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. +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 @@ -1062,7 +993,7 @@ CALL com.neo4jh3.gridDiskString( h3CellIdExpr, kExpr ) yield value return value; * kExpr: An INTEGER expression representing the grid distance. kExpr must be non-negative. ### Returns -A list of values of the same type as the type of the h3CellIdExpr expression, 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. +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 @@ -1079,6 +1010,119 @@ If kExpr < 0, the function returns -2 CALL com.neo4jh3.gridDiskString('85283473fffffff',-1) yield value return value; -2 +## com.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 com.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 point, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call com.neo4jh3.lineash3('LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + 608693213150052351,608693229507837951,608693241537101823,608693229038075903,608693229038075903,608693228954189823 + + call com.neo4jh3.lineash3('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + -1 + + call com.neo4jh3.lineash3('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) yield value return value + -2 + +## com.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 com.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 point, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + call com.neo4jh3.lineash3String('LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + '87283409affffff','872834469ffffff','872834736ffffff','87283444dffffff','87283444dffffff','872834448ffffff' + + call com.neo4jh3.lineash3String('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + -1 + + call com.neo4jh3.lineash3String('LINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',16) yield value return value + -2 + +## com.neo4jh3.multilineash3( geographyExpr, resolutionExpr ) +Returns the H3 cell ID (as a LONG) corresponding to the provided MULTILINESTRING at the specified resolution. + +### Syntax +RETURN com.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. + +### 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 + CALL com.neo4jh3.multilineash3('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',6) yield value return value; + 604189629981130751, 604189629444259839, 604189629444259839 + + call com.neo4jh3.multilineash3('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + -1 + + call com.neo4jh3.multilineash3('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17) yield value return value + -2 + +## com.neo4jh3.multilineash3String( geographyExpr, resolutionExpr ) +Returns the H3 cell ID (as a STRING) corresponding to the provided MULTILINESTRING at the specified resolution. + +### Syntax +call com.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. + +### 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 point, the function returns -1 + +If resolutionExpr is smaller than 0 or larger than 15, the function returns -2 + +### Example + CALL com.neo4jh3.multilineash3String('MULTILINESTRING((37.2713558667319 -121.91508032705622), (37.353926450852256 -121.86222328902491))',6) yield value return value; + '86283446fffffff', '86283444fffffff', '86283444fffffff' + + call com.neo4jh3.multilineash3String('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value + '-1' + + call com.neo4jh3.multilineash3String('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17) yield value return value + '-2' + + ## com.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. @@ -1145,7 +1189,7 @@ An LIST of H3 cell IDs of the same type as the values in the input LIST expressi ### Example - CALL com.neo4jh3.compact([599686042433355775,599686030622195711,599686044580839423,599686038138388479,599686043507097599,599686015589810175,599686014516068351,599686034917163007,599686029548453887,599686032769679359,599686198125920255,599686040285872127,599686041359613951,599686039212130303,599686023106002943,599686027400970239,599686013442326527,599686012368584703,599686018811035647]); + CALL com.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 ## com.neo4jh3.compactString( h3CellIdsExpr ) @@ -1164,7 +1208,7 @@ An LIST of H3 cell IDs of the same type as the values in the input LIST expressi ### Example - CALL com.neo4jh3.compactString(['85283473fffffff', '85283447fffffff', '8528347bfffffff', '85283463fffffff', '85283477fffffff', '8528340ffffffff', '8528340bfffffff', '85283457fffffff', '85283443fffffff', '8528344ffffffff', '852836b7fffffff', '8528346bfffffff', '8528346ffffffff', '85283467fffffff', '8528342bfffffff', '8528343bfffffff', '85283407fffffff', '85283403fffffff', '8528341bfffffff']); + 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; "85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff" @@ -1185,7 +1229,7 @@ Returns the line of indexes as LONG values between h3CellId1Expr and h3CellId2Ex If h3CellId1Expr or h3CellId2Expr is an invalid h3 address, the function returns -1. ### Example - CALL com.neo4jh3.gridpathcell(599686030622195711, 599686015589810175) yield value return collect(value); + CALL com.neo4jh3.gridpathcell(599686030622195711, 599686015589810175) yield value return value; 599686030622195711, 599686014516068351, 599686015589810175 CALL com.neo4jh3.gridpathcell(604189641121202175,604189642126508543) yield value return value; @@ -1232,9 +1276,10 @@ CALL com.neo4jh3.gridpathlatlon( latitude1, longitude1, latitude2, longitude2, r Returns the line of indexes as LONG values between the two points ### Error conditions -If latitude1 or latitude2 are invalid, the procedure returns -3 -If longitude1 or longitude2 are invalid, the procedure returns -4 -If resolutionExpr is invalid, the procedure returns -2 +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 com.neo4jh3.gridpathlatlon(37.2,-119.2,38.2,-119.2,5) yield value return value; @@ -1266,23 +1311,77 @@ CALL com.neo4jh3.gridpathlatlonString( latitude1, longitude1, latitude2, longitu Returns the line of indexes as STRING values between the two points ### Error conditions -If latitude1 or latitude2 are invalid, the procedure returns -3 -If longitude1 or longitude2 are invalid, the procedure returns -4 -If resolutionExpr is invalid, the procedure returns -2 +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 com.neo4jh3.gridpathlatlonString(37.2,-119.2,38.2,-119.2,5) yield value return value; "8529ab53fffffff", "8529ab43fffffff", "8529ab4ffffffff", "85298cb7fffffff", "85298ca7fffffff", "85298ddbfffffff", "85298dcbfffffff" CALL com.neo4jh3.gridpathlatlonString(37.2,-119.2,38.2,-119.2,17) yield value return value; - -2 + "-2" CALL com.neo4jh3.gridpathlatlonString(97.2,-119.2,38.2,-119.2,5) yield value return collect(value); - -3 + "-3" CALL com.neo4jh3.gridpathlatlonString(37.2,-219.2,38.2,-119.2,5) yield value return collect(value); - -4 + "-4" +## com.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 com.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 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 + 608692975685337087, 608692970668949503, 608692975920218111, 608692975718891519, 608692975903440895, 608692975467233279, 608692975702114303, 608692975886663679, 608692975450456063, 608692975735668735 + + call com.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 + +## com.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 com.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 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 + "872830950ffffff", "872830825ffffff", "87283095effffff", "872830952ffffff", "87283095dffffff", "872830943ffffff", "872830951ffffff", "87283095cffffff", "872830942ffffff", "872830953ffffff" + + call com.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" + ## com.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. @@ -1327,8 +1426,8 @@ If resolutionExpr is smaller than the maximum resolution of the H3 cell in the i "85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "85283463fffffff", "85283467fffffff", "8528346bfffffff", "8528346ffffffff", "85283473fffffff", "85283477fffffff", "8528347bfffffff" - CALL com.neo4jh3.uncompactString(["85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff"],0) yield value return value; - -2 + CALL com.neo4jh3.uncompactString(["85283447fffffff", "8528340ffffffff", "8528340bfffffff", "85283457fffffff", "85283443fffffff", "8528344ffffffff", "852836b7fffffff", "8528342bfffffff", "8528343bfffffff", "85283407fffffff", "85283403fffffff", "8528341bfffffff", "8428347ffffffff"],0) yield value return value; + "-2" ## com.neo4jh3.tochildren( h3CellIdExpr, resolutionExpr ) Returns an array of the children H3 cells of the input H3 cell at the specified resolution. @@ -1341,7 +1440,7 @@ CALL com.neo4jh3.tochildren(h3CellIdExpr, resolutionExpr) yield value return val * 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 values of values of the same type as the type of the h3CellIdExpr expression, corresponding to the children H3 cell IDs of the input H3 cell at the specified resolution. +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 @@ -1368,7 +1467,7 @@ CALL com.neo4jh3.tochildrenString(h3CellIdExpr, resolutionExpr) yield value retu * 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 values of values of the same type as the type of the h3CellIdExpr expression, corresponding to the children H3 cell IDs of the input H3 cell at the specified resolution. +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 @@ -1378,10 +1477,10 @@ If h3CellIdExpr is invalid, the function returns -1 862834707ffffff,86283470fffffff,862834717ffffff,86283471fffffff,862834727ffffff,86283472fffffff,862834737ffffff CALL com.neo4jh3.tochildrenString('1234',1) yield value return value; - -1 + "-1" CALL com.neo4jh3. tochildrenString('85283473fffffff',-1) yield value return value; - -2 + "-2" ## Error Codes * -1 or "-1" : Invalid H3 Address diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 01af812..1bd8637 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.neo4jh3 neo4jh3 - 5.10.0 + 5.11.0 @@ -55,7 +55,7 @@ org.neo4j neo4j - 5.10.0 + 5.11.0 provided @@ -130,12 +130,16 @@ neo4j-capabilities org.neo4j + + neo4j-slf4j-provider + org.neo4j + org.neo4j.test neo4j-harness - 5.10.0 + 5.11.0 test @@ -206,10 +210,11 @@ - 5.10.0 + 5.11.0 4.1 1.2 3.13.0 + 3.6.1 4.1.1 diff --git a/pom.xml b/pom.xml index 8e35b34..bca2fb1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,14 +6,24 @@ com.neo4jh3 neo4jh3 - 5.11.0 + 5.12.0 - 5.11.0 + 5.12.0 1.2 3.13.0 4.1.1 4.1 + 3.6.1 + 17 + ${java.version} + 3.4.1 + 3.10.1 + 3.22.0 + 3.0.0-M7 + + + @@ -30,18 +40,18 @@ provided - - org.apache.commons - commons-csv - ${csv.version} - - org.apache.commons commons-lang3 ${lang3.version} + + org.apache.commons + commons-math3 + ${commons.math.version} + + mil.nga.sf sf-wkt @@ -60,6 +70,18 @@ 3.3.1 + + com.uber + h3 + ${uber.version} + + + + org.apache.commons + commons-collections4 + ${commons.version} + + - 17 - 17 - - + maven-enforcer-plugin + 3.0.0 + + + enforce + + enforce + + validate + + + + ${java.version} + + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + maven-shade-plugin - 2.4.3 + ${maven-shade-plugin.version} package @@ -143,6 +172,7 @@ shade + false *:* diff --git a/src/main/java/com/neo4jh3/uber/Uberh3.java b/src/main/java/com/neo4jh3/uber/Uberh3.java index 3bb6f3c..02a9792 100755 --- a/src/main/java/com/neo4jh3/uber/Uberh3.java +++ b/src/main/java/com/neo4jh3/uber/Uberh3.java @@ -7,20 +7,16 @@ import mil.nga.sf.Geometry; import mil.nga.sf.Point; import mil.nga.sf.geojson.FeatureConverter; -import mil.nga.sf.util.ByteWriter; -import mil.nga.sf.util.TextReader; 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.Transaction; import org.neo4j.procedure.*; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -475,7 +471,7 @@ public String cellToLatLng(@Name("hexAddress") Long hexAddress) throws Interrupt } if (h3.isValidCell(hexAddress)){ LatLng tmpGeoCoord = h3.cellToLatLng(hexAddress); - return String.valueOf(tmpGeoCoord.lat) + "," + String.valueOf(tmpGeoCoord.lng); + return String.valueOf(Precision.round(tmpGeoCoord.lat,6)) + "," + String.valueOf(Precision.round(tmpGeoCoord.lng,6)); } else { return "-1"; } @@ -493,7 +489,7 @@ public String cellToLatLngString(@Name("hexAddress") String hexAddress) throws I if (h3.isValidCell(hexAddress)){ LatLng tmpGeoCoord = h3.cellToLatLng(hexAddress); - return String.valueOf(tmpGeoCoord.lat) + "," + String.valueOf(tmpGeoCoord.lng); + return String.valueOf(Precision.round(tmpGeoCoord.lat,6)) + "," + String.valueOf(Precision.round(tmpGeoCoord.lng,6)); } else { return "-1"; } @@ -695,9 +691,7 @@ public Long pointash3( try { if (h3Resolution > 0 && h3Resolution <= 15) { Geometry geometry = GeometryReader.readGeometry(wktString); - System.out.println(geometry.getEnvelope().getMinX()); - System.out.println(geometry.getEnvelope().getMinY()); - + if (latlonorder.equalsIgnoreCase("latlon")){ if (geometry.getGeometryType().toString().equalsIgnoreCase("Point")){ h3Address=h3.latLngToCell(geometry.getEnvelope().getMinX(), geometry.getEnvelope().getMinY(), h3Resolution); @@ -756,160 +750,18 @@ public String pointash3String( return h3Address; } - @Procedure(name = "com.neo4jh3.multilineash3", mode = Mode.READ) - @Description("com.neo4jh3.multilineash3(wktString, resolution) - Provides the distance in grid cells between the two indexes.") - public Stream multilineash3( - @Name("wktString") String wktString, - @Name("h3Res") Long h3Res) throws InterruptedException + @UserFunction(name = "com.neo4jh3.version") + @Description("com.neo4jh3.version() - Returns the version of the plugin.") + public String neo4jH3Version() throws InterruptedException { - List listh3Address = new ArrayList(); - List gpCells = new ArrayList(); - Long h3Address = 0L; - 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 = ""; - + String h3Version = "5.11.0"; 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("MULTILINESTRING((", ""); - mls = mls.replace(" (",""); - mls = mls.replace(")",""); - mls = mls.replace("(",""); - String[] latlonPairs = mls.split(","); - for (int i = 0; i < latlonPairs.length; i++) { - if (i > 0){ - fromLat = Double.valueOf(latlonPairs[i-1].split(" ")[0]); - fromLon = Double.valueOf(latlonPairs[i-1].split(" ")[1]); - toLat = Double.valueOf(latlonPairs[i].split(" ")[0]); - toLon = Double.valueOf(latlonPairs[i].split(" ")[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){ - - } - - } - } - } else { - listh3Address = Collections.singletonList(-2L); - - } - } catch (Exception e) { - //System.out.println(e); - listh3Address = Collections.singletonList(-1L); - // TODO Auto-generated catch block - //e.printStackTrace(); - } - return listh3Address.stream().map(H3LongAddress::of); + return h3Version; } - // New Geo Procedures - @Procedure(name = "com.neo4jh3.multilineash3String", mode = Mode.READ) - @Description("com.neo4jh3.multilineash3String(wktString, resolution) - Provides the distance in grid cells between the two indexes.") - public Stream multilineash3String( - @Name("wktString") String wktString, - @Name("h3Res") Long h3Res) 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"); - } - - 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(","); - for (int i = 0; i < latlonPairs.length; i++) { - if (i > 0){ - fromLat = Double.valueOf(latlonPairs[i-1].split(" ")[0]); - fromLon = Double.valueOf(latlonPairs[i-1].split(" ")[1]); - toLat = Double.valueOf(latlonPairs[i].split(" ")[0]); - toLon = Double.valueOf(latlonPairs[i].split(" ")[1]); - 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"); - // TODO Auto-generated catch block - //e.printStackTrace(); - } - return listh3Address.stream().map(H3StringAddress::of); - } - - @Procedure(name = "com.neo4jh3.lineash3", mode = Mode.READ) + @Procedure(name = "com.neo4jh3.lineash3", mode = Mode.READ) @Description("com.neo4jh3.lineash3(wktString, resolution) - Provides the distance in grid cells between the two indexes.") public Stream lineash3( @Name("wktString") String wktString, @@ -917,7 +769,6 @@ public Stream lineash3( { List listh3Address = new ArrayList(); List gpCells = new ArrayList(); - Long h3Address = 0L; Long h3StartAddress = 0L; Long h3MidAddress = 0L; Long h3EndAddress = 0L; @@ -1060,7 +911,161 @@ public Stream lineash3String( //e.printStackTrace(); } return listh3Address.stream().map(H3StringAddress::of); - } + } + + @Procedure(name = "com.neo4jh3.multilineash3", mode = Mode.READ) + @Description("com.neo4jh3.multilineash3(wktString, resolution) - Provides the distance in grid cells between the two indexes.") + public Stream multilineash3( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) throws InterruptedException + { + List listh3Address = new ArrayList(); + List gpCells = new ArrayList(); + Long h3Address = 0L; + 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"); + } + + 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(","); + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + fromLat = Double.valueOf(latlonPairs[i-1].split(" ")[0]); + fromLon = Double.valueOf(latlonPairs[i-1].split(" ")[1]); + toLat = Double.valueOf(latlonPairs[i].split(" ")[0]); + toLon = Double.valueOf(latlonPairs[i].split(" ")[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){ + + } + + } + } + } else { + listh3Address = Collections.singletonList(-2L); + + } + } catch (Exception e) { + //System.out.println(e); + listh3Address = Collections.singletonList(-1L); + // TODO Auto-generated catch block + //e.printStackTrace(); + } + return listh3Address.stream().map(H3LongAddress::of); + } + + // New Geo Procedures + @Procedure(name = "com.neo4jh3.multilineash3String", mode = Mode.READ) + @Description("com.neo4jh3.multilineash3String(wktString, resolution) - Provides the distance in grid cells between the two indexes.") + public Stream multilineash3String( + @Name("wktString") String wktString, + @Name("h3Res") Long h3Res) 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"); + } + + 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(","); + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + fromLat = Double.valueOf(latlonPairs[i-1].split(" ")[0]); + fromLon = Double.valueOf(latlonPairs[i-1].split(" ")[1]); + toLat = Double.valueOf(latlonPairs[i].split(" ")[0]); + toLon = Double.valueOf(latlonPairs[i].split(" ")[1]); + 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"); + // TODO Auto-generated catch block + //e.printStackTrace(); + } + return listh3Address.stream().map(H3StringAddress::of); + } + // Geography Functions @UserFunction(name = "com.neo4jh3.centeraswkb") @@ -1077,9 +1082,9 @@ public String centeraswkb( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point =new Point(false, false, lng, lat); byte[] bytes = GeometryWriter.writeGeometry(point); String hex = ""; for (byte i : bytes) { @@ -1111,9 +1116,9 @@ public String centeraswkbString( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point =new Point(false, false, lng, lat); byte[] bytes = GeometryWriter.writeGeometry(point); String hex = ""; for (byte i : bytes) { @@ -1144,9 +1149,9 @@ public String centeraswkt( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point =new Point(false, false, lng, lat); geoJsonString = mil.nga.sf.wkt.GeometryWriter.writeGeometry(point); } else { @@ -1174,9 +1179,9 @@ public String centeraswktString( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + Double lat = Precision.round(centerPoint.lat,6); + Double lng = Precision.round(centerPoint.lng,6); + Point point =new Point(false, false, lng, lat); geoJsonString = mil.nga.sf.wkt.GeometryWriter.writeGeometry(point); } else { @@ -1215,10 +1220,10 @@ public String boundaryaswkt( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1260,10 +1265,10 @@ public String boundaryaswktString( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1305,10 +1310,10 @@ public String boundaryaswkb( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1355,10 +1360,10 @@ public String boundaryaswkbString( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1394,9 +1399,9 @@ public String centerasgeojson( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + 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 { @@ -1424,9 +1429,9 @@ public String centerasgeojsonString( try { if (h3.isValidCell(hexAddress)){ centerPoint = h3.cellToLatLng(hexAddress); - Double lat = centerPoint.lat; - Double lng = centerPoint.lng; - Point point = new Point(false, false, lat, lng); + 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"; @@ -1465,10 +1470,10 @@ public String boundaryasgeojson( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1510,10 +1515,10 @@ public String boundaryasgeojsonString( LatLng thisHex = it.next(); if (i < 1){ - tpfirst = new Point(false, false, thisHex.lat, thisHex.lng); + tpfirst = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); //ring.addPoint(tpfirst); } - Point tp = new Point(false, false, thisHex.lat, thisHex.lng); + Point tp = new Point(false, false, Precision.round(thisHex.lng,6), Precision.round(thisHex.lat,6)); ring.addPoint(tp); i++; } @@ -1796,6 +1801,201 @@ public Stream polygonToCellsString(@Name("polyEdges") List 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 = "com.neo4jh3.polygonIntersectionString", mode = Mode.READ) + @Description("CALL com.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 = "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 { @@ -2060,6 +2260,132 @@ public Stream unCompact(@Name("listCells") List listCells, } +@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 = ""; + + 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(","); + for (int i = 0; i < latlonPairs.length; i++) { + if (i > 0){ + fromLat = Double.valueOf(latlonPairs[i-1].split(" ")[0]); + fromLon = Double.valueOf(latlonPairs[i-1].split(" ")[1]); + toLat = Double.valueOf(latlonPairs[i].split(" ")[0]); + toLon = Double.valueOf(latlonPairs[i].split(" ")[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); + // TODO Auto-generated catch block + //e.printStackTrace(); + } + return hexListFinal.stream().map(H3LongAddress::of); +} + + // Uncompact @Procedure(name = "com.neo4jh3.uncompactString", mode = Mode.READ) @Description("CALL com.neo4jh3.uncompactString(listCells, h3Resolution)") @@ -2099,6 +2425,8 @@ public Stream uncompactString(@Name("listCells") List l } } + + private static double distance(double lat1, double lon1, double lat2, double lon2, String unit) { if ((lat1 == lat2) && (lon1 == lon2)) { return 0; @@ -2117,6 +2445,7 @@ private static double distance(double lat1, double lon1, double lat2, double lon return (dist); } } + } diff --git a/src/test/java/com/neo4jh3/Neo4jH3Test.java b/src/test/java/com/neo4jh3/Neo4jH3Test.java index fe8828e..14517cc 100644 --- a/src/test/java/com/neo4jh3/Neo4jH3Test.java +++ b/src/test/java/com/neo4jh3/Neo4jH3Test.java @@ -12,7 +12,6 @@ import org.neo4j.driver.GraphDatabase; import org.neo4j.driver.Result; import org.neo4j.driver.Session; -import org.neo4j.driver.Values; import org.neo4j.harness.Neo4j; import org.neo4j.harness.Neo4jBuilders; @@ -45,76 +44,91 @@ public void should_return_hex_address() throws InterruptedException { assertEquals(599686042433355775L,result.single().get(0).asLong()); */ if (System.getProperty("os.name").toLowerCase().equalsIgnoreCase("mac os x")){ - 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.distanceBetweenHexes(599686042433355775,599686015589810175) as value"); String myResult = result.single().get("value").toString(); + myResult = myResult.substring(0, 11); assertEquals("17.87016346",myResult); //assertEquals(17.870163466857925,result.single().get("value").asDouble(),0); result = session.run("RETURN com.neo4jh3.centeraswkb(599686042433355775) AS value"); - assertEquals("\"00000000014042AC42F51330C7C05E7E7CF1A5AD49\"", result.single().get("value").toString()); + assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); - assertEquals("\"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))\"", result.single().get("value").toString()); + 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 (37.34579337536848 -121.9763759725512)\"", 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('8009fffffffffff') AS value"); - assertEquals("\"POLYGON ((63.09505407752544 -10.444977544778336, 55.706768465152265 5.523646549290317, 58.40154487035269 25.082722326707884, 68.92995788193983 31.831280499087388, 73.31022368544396 0.32561035194326043, 63.09505407752544 -10.444977544778336))\"", 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("\"000000000300000001000000074042A2BBC9FE987BC05E7A90AD137AD84042AD4D7641CCC6C05E772EAA970D8A4042B6D3E24CE70DC05E7B1B717195834042B5C6C6C95E70C05E826A3FE95D384042AB3509AB6E52C05E85C9966B36CB4042A1B078A2ADECC05E81DCCBBCCF794042A2BBC9FE987BC05E7A90AD137AD8\"", result.single().get("value").toString()); + assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); - assertEquals("\"00000000030000000100000006404F8C2ABB65295FC024E3D418C48DFE404BDA776399D62840161836CD0F75ED404D3365D283054B4039152D4A57DC0140513B846E1065B2403FD4CECC7D6205405253DAB471DB4A3FD4D6CCCD35766F404F8C2ABB65295FC024E3D418C48DFE\"", result.single().get("value").toString()); + assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); - assertEquals("\"POINT (64.70000012793487 10.53619907546767)\"", result.single().get("value").toString()); + assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); - assertEquals("\"00000000030000000100000006404F8C2ABB65295FC024E3D418C48DFE404BDA776399D62840161836CD0F75ED404D3365D283054B4039152D4A57DC0140513B846E1065B2403FD4CECC7D6205405253DAB471DB4A3FD4D6CCCD35766F404F8C2ABB65295FC024E3D418C48DFE\"", result.single().get("value").toString()); + 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.cellToLatLngString('892830926cfffff') AS value"); - assertEquals("\"37.56424780593243,-122.32530588312142\"", result.single().get("value").toString()); - 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("\"00000000014042AC42F51330C6C05E7E7CF1A5AD49\"", result.single().get("value").toString()); + assertEquals("\"0000000001C05E7E7CF1C3265B4042AC42F1ED17C6\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswkt(599686042433355775) AS value"); - assertEquals("\"POLYGON ((37.2713558667319 -121.91508032705622, 37.353926450852256 -121.86222328902491, 37.42834118609436 -121.92354999630156, 37.42012867767779 -122.03773496427027, 37.33755608435299 -122.090428929044, 37.26319797461824 -122.02910130919001, 37.2713558667319 -121.91508032705622))\"", result.single().get("value").toString()); + 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 (37.34579337536847 -121.9763759725512)\"", result.single().get("value").toString()); + assertEquals("\"POINT (-121.976376 37.345793)\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswktString('8009fffffffffff') AS value"); - assertEquals("\"POLYGON ((63.095054077525454 -10.444977544778325, 55.70676846515226 5.523646549290313, 58.4015448703527 25.082722326707874, 68.92995788193983 31.83128049908738, 73.31022368544396 0.32561035194326043, 63.095054077525454 -10.444977544778325))\"", result.single().get("value").toString()); + 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("\"000000000300000001000000074042A2BBC9FE987BC05E7A90AD137AD84042AD4D7641CCC6C05E772EAA970D8A4042B6D3E24CE70EC05E7B1B717195834042B5C6C6C95E71C05E826A3FE95D384042AB3509AB6E53C05E85C9966B36CD4042A1B078A2ADECC05E81DCCBBCCF7B4042A2BBC9FE987BC05E7A90AD137AD8\"", result.single().get("value").toString()); + assertEquals("\"00000000030000000100000007C05E7A90ABB44E514042A2BBCB1CC964C05E772EA960B6FA4042AD4D72799A20C05E7B1B71758E224042B6D3E0BD449AC05E826A400FBA884042B5C6C97D8CF4C05E85C996B7670A4042AB3508F648C7C05E81DCCA70D1FA4042A1B078D92FB2C05E7A90ABB44E514042A2BBCB1CC964\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); - assertEquals("\"00000000030000000100000006404F8C2ABB652961C024E3D418C48DF8404BDA776399D62740161836CD0F75E9404D3365D283054D4039152D4A57DBFE40513B846E1065B2403FD4CECC7D6203405253DAB471DB4A3FD4D6CCCD35766F404F8C2ABB652961C024E3D418C48DF8\"", result.single().get("value").toString()); + assertEquals("\"00000000030000000100000006C024E3D4280AE105404F8C2ABABEAD4F40161836EB4E9814404BDA775FB2EDFE4039152D44DCA8E3404D3365D3996FA8403FD4CEC41DD1A240513B846E8F29D43FD4D6CB5350092D405253DAB5C39BCCC024E3D4280AE105404F8C2ABABEAD4F\"", result.single().get("value").toString()); result = session.run("RETURN com.neo4jh3.centeraswktString('8009fffffffffff') AS value"); - assertEquals("\"POINT (64.70000012793487 10.53619907546767)\"", result.single().get("value").toString()); + assertEquals("\"POINT (10.536199 64.7)\"", result.single().get("value").toString()); - result = session.run("RETURN com.neo4jh3.boundaryaswkbString('8009fffffffffff') AS value"); - assertEquals("\"00000000030000000100000006404F8C2ABB652961C024E3D418C48DF8404BDA776399D62740161836CD0F75E9404D3365D283054D4039152D4A57DBFE40513B846E1065B2403FD4CECC7D6203405253DAB471DB4A3FD4D6CCCD35766F404F8C2ABB652961C024E3D418C48DF8\"", result.single().get("value").toString()); - - } + + result = session.run("RETURN com.neo4jh3.version() AS value"); + assertEquals("\"5.11.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()); @@ -249,7 +263,7 @@ public void should_return_hex_address() throws InterruptedException { assertEquals(-1L, result.single().get("value").asLong()); result = session.run("RETURN com.neo4jh3.cellToLatLng( 635714569676958015) AS value"); - assertEquals("\"37.81989535912348,-122.47829651373911\"", result.single().get("value").toString()); + assertEquals("\"37.819895,-122.478297\"", result.single().get("value").toString()); /* result = session.run("RETURN com.neo4jh3.cellToLatLngString('892830926cfffff') AS value"); @@ -366,21 +380,36 @@ public void should_return_hex_address() throws InterruptedException { 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((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',12) yield value return value limit 1"); assertEquals(631243922688264703L, result.single().get(0).asLong(),0); result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',12) yield value return value limit 1"); assertEquals("\"8c2a100d27549ff\"",result.single().get(0).toString()); + result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17) yield value return value limit 1"); + assertEquals(-2L,result.single().get(0).asLong(),0); + result = session.run("call com.neo4jh3.multilineash3String('ZZZ((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',12) yield value return value limit 1"); assertEquals("\"-1\"",result.single().get(0).toString()); result = session.run("call com.neo4jh3.multilineash3String('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17) yield value return value limit 1"); assertEquals("\"-2\"",result.single().get(0).toString()); + + result = session.run("call com.neo4jh3.lineash3String('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value limit 1"); + assertEquals("\"-1\"", result.single().get("value").toString()); + + result = session.run("call com.neo4jh3.lineash3String('LINESTRING((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value limit 1"); + assertEquals("\"87283409affffff\"",result.single().get(0).toString()); - result = session.run("call com.neo4jh3.multilineash3('MULTILINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',17) yield value return value limit 1"); - assertEquals(-2L,result.single().get(0).asLong(),0); - + result = session.run("call com.neo4jh3.lineash3('ZZZ((37.271355 -121.915080), (37.353926 -121.862223))',7) yield value return value limit 1"); + assertEquals(-1L, result.single().get(0).asLong(),0); + result = session.run("call com.neo4jh3.lineash3('LINESTRING((40.736691045913472 73.99311953429248), (40.73733046783797 -73.99265431029018) , (40.93733046783797 -74.00265431029018))',12) yield value return value limit 1"); assertEquals(631243922688264703L, result.single().get(0).asLong(),0); @@ -436,6 +465,12 @@ public void should_return_hex_address() throws InterruptedException { 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); + } driver.close(); embeddedDatabaseServer.close();