From af2642e0004ca4ffe9c7267053a6e06090044c02 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sat, 23 Sep 2023 22:44:22 -0400 Subject: [PATCH] Add QuickInfo support (#70) * Expose getQuickInfo method * Cleanup JNI; add more tests * Update SBT extras script * CHANGELOG.md update * Fix tests * Bump MacOS PDAL version up to 2.5.6 --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 3 + core/src/main/scala/io/pdal/Pipeline.scala | 1 + .../quick-info-with-metadata-mac.json | 157 ++++++++++++++++++ .../resources/quick-info-with-metadata.json | 34 ++++ core/src/test/resources/quick-info.json | 16 ++ .../src/test/scala/io/pdal/PipelineSpec.scala | 11 ++ .../scala/io/pdal/TestEnvironmentSpec.scala | 4 + native/src/JavaPipeline.cpp | 115 +++++++++++-- native/src/include/JavaPipeline.hpp | 4 +- native/src/include/io_pdal_Pipeline.h | 8 + native/src/io_pdal_Pipeline.cpp | 14 ++ native/src/io_pdal_PointLayout.cpp | 8 +- native/src/io_pdal_PointView.cpp | 25 +-- project/build.properties | 2 +- sbt | 17 +- 16 files changed, 382 insertions(+), 39 deletions(-) create mode 100644 core/src/test/resources/quick-info-with-metadata-mac.json create mode 100644 core/src/test/resources/quick-info-with-metadata.json create mode 100644 core/src/test/resources/quick-info.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d89dd20..87ac103 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: os: [macos-latest] java: [8] distribution: [temurin] - pdal: [2.5.0] + pdal: [2.5.6] runs-on: ${{ matrix.os }} steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index e2ddb80..367941e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## Added +* Add QuickInfo support [#70](https://github.com/PDAL/java/pull/70) (@pomadchin) + ## [2.5.0] - 2023-02-25 ## Added * PDAL 2.5.1 [#65](https://github.com/pdal/java/pull/65) (@pomadchin) diff --git a/core/src/main/scala/io/pdal/Pipeline.scala b/core/src/main/scala/io/pdal/Pipeline.scala index 43986a1..21225ed 100644 --- a/core/src/main/scala/io/pdal/Pipeline.scala +++ b/core/src/main/scala/io/pdal/Pipeline.scala @@ -37,6 +37,7 @@ class Pipeline(val json: String, val logLevel: Int) extends Native { @native def getPipeline(): String @native def getMetadata(): String @native def getSchema(): String + @native def getQuickInfo(): String @native def validate(): Boolean @native def setLogLevel(i: Int): Unit @native def getLogLevel(): Int diff --git a/core/src/test/resources/quick-info-with-metadata-mac.json b/core/src/test/resources/quick-info-with-metadata-mac.json new file mode 100644 index 0000000..7ce7f0a --- /dev/null +++ b/core/src/test/resources/quick-info-with-metadata-mac.json @@ -0,0 +1,157 @@ +{ + "readers.las": + { + "bounds": + { + "maxx": 638982.55, + "maxy": 853535.43, + "maxz": 586.38, + "minx": 635619.85, + "miny": 848899.7, + "minz": 406.59 + }, + "dimensions": "X, Y, Z, Intensity, ReturnNumber, NumberOfReturns, ScanDirectionFlag, EdgeOfFlightLine, Classification, ScanAngleRank, UserData, PointSourceId, GpsTime, Red, Green, Blue", + "num_points": 1065, + "srs": + { + "compoundwkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]", + "horizontal": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]", + "isgeocentric": false, + "isgeographic": false, + "json": { + "type": "ProjectedCRS", + "name": "NAD83(HARN) / Oregon LCC (m)", + "base_crs": { + "name": "NAD83(HARN)", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "NAD83 (High Accuracy Reference Network)", + "ellipsoid": { + "name": "GRS 1980", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257222101 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4152 + } + }, + "conversion": { + "name": "unnamed", + "method": { + "name": "Lambert Conic Conformal (2SP)", + "id": { + "authority": "EPSG", + "code": 9802 + } + }, + "parameters": [ + { + "name": "Latitude of false origin", + "value": 41.75, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8821 + } + }, + { + "name": "Longitude of false origin", + "value": -120.5, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8822 + } + }, + { + "name": "Latitude of 1st standard parallel", + "value": 43, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8823 + } + }, + { + "name": "Latitude of 2nd standard parallel", + "value": 45.5, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8824 + } + }, + { + "name": "Easting at false origin", + "value": 400000, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8826 + } + }, + { + "name": "Northing at false origin", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8827 + } + } + ] + }, + "coordinate_system": { + "subtype": "Cartesian", + "axis": [ + { + "name": "Easting", + "abbreviation": "", + "direction": "east", + "unit": "metre" + }, + { + "name": "Northing", + "abbreviation": "", + "direction": "north", + "unit": "metre" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 2993 + } + }, + "prettycompoundwkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",\n GEOGCS[\"NAD83(HARN)\",\n DATUM[\"NAD83_High_Accuracy_Reference_Network\",\n SPHEROID[\"GRS 1980\",6378137,298.257222101,\n AUTHORITY[\"EPSG\",\"7019\"]],\n AUTHORITY[\"EPSG\",\"6152\"]],\n PRIMEM[\"Greenwich\",0,\n AUTHORITY[\"EPSG\",\"8901\"]],\n UNIT[\"degree\",0.0174532925199433,\n AUTHORITY[\"EPSG\",\"9122\"]],\n AUTHORITY[\"EPSG\",\"4152\"]],\n PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n PARAMETER[\"latitude_of_origin\",41.75],\n PARAMETER[\"central_meridian\",-120.5],\n PARAMETER[\"standard_parallel_1\",43],\n PARAMETER[\"standard_parallel_2\",45.5],\n PARAMETER[\"false_easting\",400000],\n PARAMETER[\"false_northing\",0],\n UNIT[\"metre\",1,\n AUTHORITY[\"EPSG\",\"9001\"]],\n AXIS[\"Easting\",EAST],\n AXIS[\"Northing\",NORTH],\n AUTHORITY[\"EPSG\",\"2993\"]]", + "prettywkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",\n GEOGCS[\"NAD83(HARN)\",\n DATUM[\"NAD83_High_Accuracy_Reference_Network\",\n SPHEROID[\"GRS 1980\",6378137,298.257222101,\n AUTHORITY[\"EPSG\",\"7019\"]],\n AUTHORITY[\"EPSG\",\"6152\"]],\n PRIMEM[\"Greenwich\",0,\n AUTHORITY[\"EPSG\",\"8901\"]],\n UNIT[\"degree\",0.0174532925199433,\n AUTHORITY[\"EPSG\",\"9122\"]],\n AUTHORITY[\"EPSG\",\"4152\"]],\n PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n PARAMETER[\"latitude_of_origin\",41.75],\n PARAMETER[\"central_meridian\",-120.5],\n PARAMETER[\"standard_parallel_1\",43],\n PARAMETER[\"standard_parallel_2\",45.5],\n PARAMETER[\"false_easting\",400000],\n PARAMETER[\"false_northing\",0],\n UNIT[\"metre\",1,\n AUTHORITY[\"EPSG\",\"9001\"]],\n AXIS[\"Easting\",EAST],\n AXIS[\"Northing\",NORTH],\n AUTHORITY[\"EPSG\",\"2993\"]]", + "proj4": "+proj=lcc +lat_0=41.75 +lon_0=-120.5 +lat_1=43 +lat_2=45.5 +x_0=400000 +y_0=0 +ellps=GRS80 +units=m +no_defs", + "units": + { + "horizontal": "metre", + "vertical": "" + }, + "vertical": "", + "wkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]" + } + } +} diff --git a/core/src/test/resources/quick-info-with-metadata.json b/core/src/test/resources/quick-info-with-metadata.json new file mode 100644 index 0000000..efb78cd --- /dev/null +++ b/core/src/test/resources/quick-info-with-metadata.json @@ -0,0 +1,34 @@ +{ + "readers.las": + { + "bounds": + { + "maxx": 638982.55, + "maxy": 853535.43, + "maxz": 586.38, + "minx": 635619.85, + "miny": 848899.7, + "minz": 406.59 + }, + "dimensions": "X, Y, Z, Intensity, ReturnNumber, NumberOfReturns, ScanDirectionFlag, EdgeOfFlightLine, Classification, ScanAngleRank, UserData, PointSourceId, GpsTime, Red, Green, Blue", + "num_points": 1065, + "srs": + { + "compoundwkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]", + "horizontal": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]", + "isgeocentric": false, + "isgeographic": false, + "json": "{\n \"type\": \"ProjectedCRS\",\n \"name\": \"NAD83(HARN) / Oregon LCC (m)\",\n \"base_crs\": {\n \"name\": \"NAD83(HARN)\",\n \"datum\": {\n \"type\": \"GeodeticReferenceFrame\",\n \"name\": \"NAD83 (High Accuracy Reference Network)\",\n \"ellipsoid\": {\n \"name\": \"GRS 1980\",\n \"semi_major_axis\": 6378137,\n \"inverse_flattening\": 298.257222101\n }\n },\n \"coordinate_system\": {\n \"subtype\": \"ellipsoidal\",\n \"axis\": [\n {\n \"name\": \"Geodetic latitude\",\n \"abbreviation\": \"Lat\",\n \"direction\": \"north\",\n \"unit\": \"degree\"\n },\n {\n \"name\": \"Geodetic longitude\",\n \"abbreviation\": \"Lon\",\n \"direction\": \"east\",\n \"unit\": \"degree\"\n }\n ]\n },\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 4152\n }\n },\n \"conversion\": {\n \"name\": \"unnamed\",\n \"method\": {\n \"name\": \"Lambert Conic Conformal (2SP)\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 9802\n }\n },\n \"parameters\": [\n {\n \"name\": \"Latitude of false origin\",\n \"value\": 41.75,\n \"unit\": \"degree\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8821\n }\n },\n {\n \"name\": \"Longitude of false origin\",\n \"value\": -120.5,\n \"unit\": \"degree\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8822\n }\n },\n {\n \"name\": \"Latitude of 1st standard parallel\",\n \"value\": 43,\n \"unit\": \"degree\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8823\n }\n },\n {\n \"name\": \"Latitude of 2nd standard parallel\",\n \"value\": 45.5,\n \"unit\": \"degree\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8824\n }\n },\n {\n \"name\": \"Easting at false origin\",\n \"value\": 400000,\n \"unit\": \"metre\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8826\n }\n },\n {\n \"name\": \"Northing at false origin\",\n \"value\": 0,\n \"unit\": \"metre\",\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 8827\n }\n }\n ]\n },\n \"coordinate_system\": {\n \"subtype\": \"Cartesian\",\n \"axis\": [\n {\n \"name\": \"Easting\",\n \"abbreviation\": \"\",\n \"direction\": \"east\",\n \"unit\": \"metre\"\n },\n {\n \"name\": \"Northing\",\n \"abbreviation\": \"\",\n \"direction\": \"north\",\n \"unit\": \"metre\"\n }\n ]\n },\n \"id\": {\n \"authority\": \"EPSG\",\n \"code\": 2993\n }\n}", + "prettycompoundwkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",\n GEOGCS[\"NAD83(HARN)\",\n DATUM[\"NAD83_High_Accuracy_Reference_Network\",\n SPHEROID[\"GRS 1980\",6378137,298.257222101,\n AUTHORITY[\"EPSG\",\"7019\"]],\n AUTHORITY[\"EPSG\",\"6152\"]],\n PRIMEM[\"Greenwich\",0,\n AUTHORITY[\"EPSG\",\"8901\"]],\n UNIT[\"degree\",0.0174532925199433,\n AUTHORITY[\"EPSG\",\"9122\"]],\n AUTHORITY[\"EPSG\",\"4152\"]],\n PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n PARAMETER[\"latitude_of_origin\",41.75],\n PARAMETER[\"central_meridian\",-120.5],\n PARAMETER[\"standard_parallel_1\",43],\n PARAMETER[\"standard_parallel_2\",45.5],\n PARAMETER[\"false_easting\",400000],\n PARAMETER[\"false_northing\",0],\n UNIT[\"metre\",1,\n AUTHORITY[\"EPSG\",\"9001\"]],\n AXIS[\"Easting\",EAST],\n AXIS[\"Northing\",NORTH],\n AUTHORITY[\"EPSG\",\"2993\"]]", + "prettywkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",\n GEOGCS[\"NAD83(HARN)\",\n DATUM[\"NAD83_High_Accuracy_Reference_Network\",\n SPHEROID[\"GRS 1980\",6378137,298.257222101,\n AUTHORITY[\"EPSG\",\"7019\"]],\n AUTHORITY[\"EPSG\",\"6152\"]],\n PRIMEM[\"Greenwich\",0,\n AUTHORITY[\"EPSG\",\"8901\"]],\n UNIT[\"degree\",0.0174532925199433,\n AUTHORITY[\"EPSG\",\"9122\"]],\n AUTHORITY[\"EPSG\",\"4152\"]],\n PROJECTION[\"Lambert_Conformal_Conic_2SP\"],\n PARAMETER[\"latitude_of_origin\",41.75],\n PARAMETER[\"central_meridian\",-120.5],\n PARAMETER[\"standard_parallel_1\",43],\n PARAMETER[\"standard_parallel_2\",45.5],\n PARAMETER[\"false_easting\",400000],\n PARAMETER[\"false_northing\",0],\n UNIT[\"metre\",1,\n AUTHORITY[\"EPSG\",\"9001\"]],\n AXIS[\"Easting\",EAST],\n AXIS[\"Northing\",NORTH],\n AUTHORITY[\"EPSG\",\"2993\"]]", + "proj4": "+proj=lcc +lat_0=41.75 +lon_0=-120.5 +lat_1=43 +lat_2=45.5 +x_0=400000 +y_0=0 +ellps=GRS80 +units=m +no_defs", + "units": + { + "horizontal": "metre", + "vertical": "" + }, + "vertical": "", + "wkt": "PROJCS[\"NAD83(HARN) / Oregon LCC (m)\",GEOGCS[\"NAD83(HARN)\",DATUM[\"NAD83_High_Accuracy_Reference_Network\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6152\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4152\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",41.75],PARAMETER[\"central_meridian\",-120.5],PARAMETER[\"standard_parallel_1\",43],PARAMETER[\"standard_parallel_2\",45.5],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"2993\"]]" + } + } +} diff --git a/core/src/test/resources/quick-info.json b/core/src/test/resources/quick-info.json new file mode 100644 index 0000000..7ce2f01 --- /dev/null +++ b/core/src/test/resources/quick-info.json @@ -0,0 +1,16 @@ +{ + "readers.las": + { + "bounds": + { + "maxx": 638982.55, + "maxy": 853535.43, + "maxz": 586.38, + "minx": 635619.85, + "miny": 848899.7, + "minz": 406.59 + }, + "dimensions": "X, Y, Z, Intensity, ReturnNumber, NumberOfReturns, ScanDirectionFlag, EdgeOfFlightLine, Classification, ScanAngleRank, UserData, PointSourceId, GpsTime, Red, Green, Blue", + "num_points": 1065 + } +} diff --git a/core/src/test/scala/io/pdal/PipelineSpec.scala b/core/src/test/scala/io/pdal/PipelineSpec.scala index 9758a2b..b9e0435 100644 --- a/core/src/test/scala/io/pdal/PipelineSpec.scala +++ b/core/src/test/scala/io/pdal/PipelineSpec.scala @@ -186,6 +186,17 @@ class PipelineSpec extends TestEnvironmentSpec { parser.parse(pipeline.getMetadata()) shouldBe metadataJson } + it("should get quickInfo") { + val p = Pipeline(json) + parser.parse(p.getQuickInfo()) shouldBe quickInfoJson + } + + it("should get quickInfo with metadata") { + val p = Pipeline(json) + p.execute() + parser.parse(p.getQuickInfo()) should be(quickInfoWithMetadataJson).or(be(quickInfoWithMetadataMacJson)) + } + it("should extract mesh in iterative fashion") { pipelineDelaunay.validate() should be(true) pipelineDelaunay.execute() diff --git a/core/src/test/scala/io/pdal/TestEnvironmentSpec.scala b/core/src/test/scala/io/pdal/TestEnvironmentSpec.scala index b45acbc..01fdb22 100644 --- a/core/src/test/scala/io/pdal/TestEnvironmentSpec.scala +++ b/core/src/test/scala/io/pdal/TestEnvironmentSpec.scala @@ -56,6 +56,10 @@ trait TestEnvironmentSpec extends AnyFunSpec with Matchers with BeforeAndAfterAl val jsonExpectedJson: Either[ParsingFailure, Json] = parser.parse(getJson("/las-expected.json")) val schemaJson: Either[ParsingFailure, Json] = parser.parse(getJson("/schema.json")) val metadataJson: Either[ParsingFailure, Json] = parser.parse(getJson("/metadata.json")) + val quickInfoJson: Either[ParsingFailure, Json] = parser.parse(getJson("/quick-info.json")) + val quickInfoWithMetadataJson: Either[ParsingFailure, Json] = parser.parse(getJson("/quick-info-with-metadata.json")) + val quickInfoWithMetadataMacJson: Either[ParsingFailure, Json] = + parser.parse(getJson("/quick-info-with-metadata-mac.json")) val proj4String = "+proj=lcc +lat_0=41.75 +lon_0=-120.5 +lat_1=43 +lat_2=45.5 +x_0=400000 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs" diff --git a/native/src/JavaPipeline.cpp b/native/src/JavaPipeline.cpp index fae5474..ae3ed74 100644 --- a/native/src/JavaPipeline.cpp +++ b/native/src/JavaPipeline.cpp @@ -36,29 +36,38 @@ #include #endif +using pdal::LogPtr; +using pdal::MetadataNode; +using pdal::PointId; using pdal::PointViewSet; +using pdal::PointTableRef; +using pdal::Stage; using pdal::point_count_t; +using std::string; +using std::stringstream; +using std::vector; + namespace libpdaljava { void CountPointTable::reset() { - for (pdal::PointId idx = 0; idx < numPoints(); idx++) + for (PointId idx = 0; idx < numPoints(); idx++) if (!skip(idx)) m_count++; FixedPointTable::reset(); } -PipelineExecutor::PipelineExecutor(std::string const& json, int level) +PipelineExecutor::PipelineExecutor(string const& json, int level) { setLogLevel(level); - pdal::LogPtr log(pdal::Log::makeLog("javapipeline", &m_logStream)); + LogPtr log(pdal::Log::makeLog("javapipeline", &m_logStream)); log->setLevel(m_logLevel); m_manager.setLog(log); - std::stringstream strm; + stringstream strm; strm << json; m_manager.readPipeline(strm); @@ -71,10 +80,10 @@ bool PipelineExecutor::validate() return true; } -pdal::point_count_t PipelineExecutor::execute() +point_count_t PipelineExecutor::execute() { - pdal::point_count_t count = m_manager.execute(); + point_count_t count = m_manager.execute(); m_executed = true; return count; } @@ -95,10 +104,10 @@ const PointViewSet& PipelineExecutor::views() const return m_manager.views(); } -std::string PipelineExecutor::getSrsWKT2() const +string PipelineExecutor::getSrsWKT2() const { - std::string output(""); - pdal::PointTableRef pointTable = m_manager.pointTable(); + string output(""); + PointTableRef pointTable = m_manager.pointTable(); pdal::SpatialReference srs = pointTable.spatialReference(); output = srs.getWKT(); @@ -106,41 +115,111 @@ std::string PipelineExecutor::getSrsWKT2() const return output; } -std::string PipelineExecutor::getPipeline() const +string PipelineExecutor::getPipeline() const { - std::stringstream strm; + stringstream strm; pdal::PipelineWriter::writePipeline(m_manager.getStage(), strm); return strm.str(); } -std::string PipelineExecutor::getMetadata() const +string PipelineExecutor::getMetadata() const { if (!m_executed) throw java_error("Pipeline has not been executed!"); - std::stringstream strm; - pdal::MetadataNode root = m_manager.getMetadata().clone("metadata"); + stringstream strm; + MetadataNode root = m_manager.getMetadata().clone("metadata"); pdal::Utils::toJSON(root, strm); return strm.str(); } -std::string PipelineExecutor::getSchema() const +string PipelineExecutor::getSchema() const { if (!m_executed) throw java_error("Pipeline has not been executed!"); - std::stringstream strm; - pdal::MetadataNode root = pointTable().layout()->toMetadata().clone("schema"); + stringstream strm; + MetadataNode root = pointTable().layout()->toMetadata().clone("schema"); pdal::Utils::toJSON(root, strm); return strm.str(); } +MetadataNode computePreview(pdal::Stage* stage) +{ + if (!stage) + throw java_error("no valid stage in QuickInfo"); + + stage->preview(); + + pdal::QuickInfo qi = stage->preview(); + if (!qi.valid()) + throw java_error("No summary data available for stage '" + stage->getName()+"'" ); + + stringstream strm; + MetadataNode summary(stage->getName()); + summary.add("num_points", qi.m_pointCount); + if (qi.m_srs.valid()) + { + MetadataNode srs = qi.m_srs.toMetadata(); + summary.add(srs); + } + if (qi.m_bounds.valid()) + { + MetadataNode bounds = pdal::Utils::toMetadata(qi.m_bounds); + summary.add(bounds.clone("bounds")); + } + + string dims; + auto di = qi.m_dimNames.begin(); + + while (di != qi.m_dimNames.end()) + { + dims += *di; + ++di; + if (di != qi.m_dimNames.end()) + dims += ", "; + } + if (dims.size()) + summary.add("dimensions", dims); + pdal::Utils::toJSON(summary, strm); + return summary; +} + + +string PipelineExecutor::getQuickInfo() const +{ + + pdal::Stage* stage(nullptr); + vector stages = m_manager.stages(); + vector previewStages; + + for (auto const& s: stages) + { + auto n = s->getName(); + auto v = pdal::Utils::split2(n,'.'); + if (v.size() > 0) + if (pdal::Utils::iequals(v[0], "readers")) + previewStages.push_back(s); + } + + MetadataNode summary; + for (auto const& stage: previewStages) + { + MetadataNode n = computePreview(stage); + summary.add(n); + } + + stringstream strm; + pdal::Utils::toJSON(summary, strm); + return strm.str(); +} + void PipelineExecutor::setLogStream(std::ostream& strm) { - pdal::LogPtr log(pdal::Log::makeLog("javapipeline", &strm)); + LogPtr log(pdal::Log::makeLog("javapipeline", &strm)); log->setLevel(m_logLevel); m_manager.setLog(log); } diff --git a/native/src/include/JavaPipeline.hpp b/native/src/include/JavaPipeline.hpp index 400db82..4ede172 100644 --- a/native/src/include/JavaPipeline.hpp +++ b/native/src/include/JavaPipeline.hpp @@ -33,9 +33,11 @@ #pragma once +#include #include #include -#include +#include +#include #include #include diff --git a/native/src/include/io_pdal_Pipeline.h b/native/src/include/io_pdal_Pipeline.h index 0fa38d8..660feac 100644 --- a/native/src/include/io_pdal_Pipeline.h +++ b/native/src/include/io_pdal_Pipeline.h @@ -71,6 +71,14 @@ JNIEXPORT jstring JNICALL Java_io_pdal_Pipeline_getMetadata JNIEXPORT jstring JNICALL Java_io_pdal_Pipeline_getSchema (JNIEnv *, jobject); +/* + * Class: io_pdal_Pipeline + * Method: getQuickInfo + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_io_pdal_Pipeline_getQuickInfo + (JNIEnv *, jobject); + /* * Class: io_pdal_Pipeline * Method: validate diff --git a/native/src/io_pdal_Pipeline.cpp b/native/src/io_pdal_Pipeline.cpp index 693a526..0138b50 100644 --- a/native/src/io_pdal_Pipeline.cpp +++ b/native/src/io_pdal_Pipeline.cpp @@ -159,6 +159,20 @@ JNIEXPORT jstring JNICALL Java_io_pdal_Pipeline_getSchema } } +JNIEXPORT jstring JNICALL Java_io_pdal_Pipeline_getQuickInfo + (JNIEnv *env, jobject obj) +{ + try + { + PipelineExecutor *p = getHandle(env, obj); + return env->NewStringUTF(p->getQuickInfo().c_str()); + } + catch(const pdal_error &pe) + { + return throwExecutionException(env, pe.what()); + } +} + JNIEXPORT jboolean JNICALL Java_io_pdal_Pipeline_validate (JNIEnv *env, jobject obj) { diff --git a/native/src/io_pdal_PointLayout.cpp b/native/src/io_pdal_PointLayout.cpp index 41d0f79..d45a834 100644 --- a/native/src/io_pdal_PointLayout.cpp +++ b/native/src/io_pdal_PointLayout.cpp @@ -41,6 +41,8 @@ using pdal::PointLayout; using pdal::DimTypeList; using pdal::DimType; +using std::string; + JNIEXPORT jobjectArray JNICALL Java_io_pdal_PointLayout_dimTypes (JNIEnv *env, jobject obj) { @@ -72,7 +74,7 @@ JNIEXPORT jobjectArray JNICALL Java_io_pdal_PointLayout_dimTypes JNIEXPORT jobject JNICALL Java_io_pdal_PointLayout_findDimType (JNIEnv *env, jobject obj, jstring jstr) { - std::string fid = std::string(env->GetStringUTFChars(jstr, 0)); + string fid = string(env->GetStringUTFChars(jstr, 0)); PointLayout *pl = getHandle(env, obj); DimType dt = pl->findDimType(fid); jstring id = env->NewStringUTF(pl->dimName(dt.m_id).c_str()); @@ -88,7 +90,7 @@ JNIEXPORT jobject JNICALL Java_io_pdal_PointLayout_findDimType JNIEXPORT jlong JNICALL Java_io_pdal_PointLayout_dimSize__Ljava_lang_String_2 (JNIEnv *env, jobject obj, jstring jstr) { - std::string fid = std::string(env->GetStringUTFChars(jstr, 0)); + string fid = string(env->GetStringUTFChars(jstr, 0)); PointLayout *pl = getHandle(env, obj); return pl->dimSize(pl->findDim(fid)); @@ -97,7 +99,7 @@ JNIEXPORT jlong JNICALL Java_io_pdal_PointLayout_dimSize__Ljava_lang_String_2 JNIEXPORT jlong JNICALL Java_io_pdal_PointLayout_dimPackedOffset__Ljava_lang_String_2 (JNIEnv *env, jobject obj, jstring jstr) { - std::string fid = std::string(env->GetStringUTFChars(jstr, 0)); + string fid = string(env->GetStringUTFChars(jstr, 0)); PointLayout *pl = getHandle(env, obj); DimType dimType = pl->findDimType(fid); DimTypeList dims = pl->dimTypes(); diff --git a/native/src/io_pdal_PointView.cpp b/native/src/io_pdal_PointView.cpp index 9f49ea0..55f6f48 100644 --- a/native/src/io_pdal_PointView.cpp +++ b/native/src/io_pdal_PointView.cpp @@ -58,13 +58,16 @@ using pdal::Triangle; using pdal::DimType; using pdal::pdal_error; +using std::size_t; +using std::string; + /// Converts JavaArray of DimTypes (In Java interpretation DimType is a pair of strings) /// into DimTypeList (vector of DimTypes), puts dim size into bufSize /// \param[in] env JNI environment /// \param[in] dims JavaArray of DimTypes /// \param[in] bufSize Dims sum size /// \param[in] dimTypes Vector of DimTypes -void convertDimTypeJavaArrayToVector(JNIEnv *env, jobjectArray dims, std::size_t *pointSize, DimTypeList *dimTypes, PointLayoutPtr pl) +void convertDimTypeJavaArrayToVector(JNIEnv *env, jobjectArray dims, size_t *pointSize, DimTypeList *dimTypes, PointLayoutPtr pl) { for (jint i = 0; i < env->GetArrayLength(dims); i++) { @@ -74,7 +77,7 @@ void convertDimTypeJavaArrayToVector(JNIEnv *env, jobjectArray dims, std::size_t jfieldID ftype = env->GetFieldID(cDimType, "type", "Ljava/lang/String;"); jstring jid = reinterpret_cast(env->GetObjectField(jDimType, fid)); - DimType dimType = pl->findDimType(std::string(env->GetStringUTFChars(jid, 0))); + DimType dimType = pl->findDimType(string(env->GetStringUTFChars(jid, 0))); *pointSize += pl->dimSize(dimType.m_id); dimTypes->insert(dimTypes->begin() + i, dimType); @@ -87,9 +90,9 @@ void convertDimTypeJavaArrayToVector(JNIEnv *env, jobjectArray dims, std::size_t /// \param[in] dims List of dimensions/types to retrieve. /// \param[in] idx Index of point to get. /// \param[in] buf Pointer to buffer to fill. -void appendPackedPoint(PointViewPtr pv, const DimTypeList& dims, PointId idx, std::size_t pointSize, char *buf) +void appendPackedPoint(PointViewPtr pv, const DimTypeList& dims, PointId idx, size_t pointSize, char *buf) { - std::size_t from = idx * pointSize; + size_t from = idx * pointSize; if(from >= pv->size() * pointSize) return; buf += from; pv->getPackedPoint(dims, idx, buf); @@ -141,7 +144,7 @@ JNIEXPORT jstring JNICALL Java_io_pdal_PointView_getCrsWKT__Z PointViewRawPtr *pvrp = getHandle(env, obj); PointViewPtr pv = pvrp->shared_pointer; - std::string wkt = pv->spatialReference().getWKT(); + string wkt = pv->spatialReference().getWKT(); if(pretty) wkt = SpatialReference::prettyWkt(wkt); @@ -157,7 +160,7 @@ JNIEXPORT jbyteArray JNICALL Java_io_pdal_PointView_getPackedPoint__J_3Lio_pdal_ PointLayoutPtr pl = pv->layout(); // we need to calculate buffer size - std::size_t pointSize = 0; + size_t pointSize = 0; DimTypeList dimTypes; // calculate result buffer length (for one point) and get dimTypes @@ -184,14 +187,14 @@ JNIEXPORT jbyteArray JNICALL Java_io_pdal_PointView_getPackedPoints___3Lio_pdal_ PointLayoutPtr pl = pv->layout(); // we need to calculate buffer size - std::size_t pointSize = 0; + size_t pointSize = 0; DimTypeList dimTypes; // calculate result buffer length (for one point) and get dimTypes convertDimTypeJavaArrayToVector(env, dims, &pointSize, &dimTypes, pl); // reading all points - std::size_t bufSize = pointSize * pv->size(); + size_t bufSize = pointSize * pv->size(); char *buf = new char[bufSize]; for (PointId idx = 0; idx < pv->size(); idx++) @@ -212,7 +215,7 @@ JNIEXPORT jobject JNICALL Java_io_pdal_PointView_getTriangularMesh__Ljava_lang_S { PointViewRawPtr *pvrp = getHandle(env, obj); PointViewPtr pv = pvrp->shared_pointer; - std::string cname = std::string(env->GetStringUTFChars(name, 0)); + string cname = string(env->GetStringUTFChars(name, 0)); TriangularMesh *m = pv->mesh(cname); @@ -236,7 +239,7 @@ JNIEXPORT jobject JNICALL Java_io_pdal_PointView_getTriangularMesh__Ljava_lang_S JNIEXPORT jdoubleArray JNICALL Java_io_pdal_PointView_rasterizeTriangularMesh___3DIILio_pdal_DimType_2Ljava_lang_String_2 (JNIEnv *env, jobject obj, jdoubleArray extent, jint cols, jint rows, jobject jDimType, jstring name) { - std::string cname = std::string(env->GetStringUTFChars(name, 0)); + string cname = string(env->GetStringUTFChars(name, 0)); PointViewRawPtr *pvrp = getHandle(env, obj); PointViewPtr pv = pvrp->shared_pointer; @@ -253,7 +256,7 @@ JNIEXPORT jdoubleArray JNICALL Java_io_pdal_PointView_rasterizeTriangularMesh___ jstring jid = reinterpret_cast(env->GetObjectField(jDimType, fid)); PointLayoutPtr pl = pv->layout(); - DimType dimType = pl->findDimType(std::string(env->GetStringUTFChars(jid, 0))); + DimType dimType = pl->findDimType(string(env->GetStringUTFChars(jid, 0))); Id dimId = dimType.m_id; int size = mesh->size(); diff --git a/project/build.properties b/project/build.properties index 46e43a9..2743082 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.2 +sbt.version=1.9.6 diff --git a/sbt b/sbt index 1880b90..5c0c3bd 100755 --- a/sbt +++ b/sbt @@ -34,11 +34,11 @@ set -o pipefail -declare -r sbt_release_version="1.8.0" -declare -r sbt_unreleased_version="1.8.0" +declare -r sbt_release_version="1.9.6" +declare -r sbt_unreleased_version="1.9.6" -declare -r latest_213="2.13.10" -declare -r latest_212="2.12.17" +declare -r latest_213="2.13.12" +declare -r latest_212="2.12.18" declare -r latest_211="2.11.12" declare -r latest_210="2.10.7" declare -r latest_29="2.9.3" @@ -388,10 +388,12 @@ usage() { set_sbt_version cat < Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted -script Run the specified file as a scala script + # sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version) -sbt-version use the specified version of sbt (default: $sbt_release_version) -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version @@ -416,6 +419,7 @@ are not special. -sbt-jar use the specified jar as the sbt launcher -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) -sbt-launch-repo repo url for downloading sbt launcher jar (default: $(url_base "$sbt_version")) + # scala version (default: as chosen by sbt) -28 use $latest_28 -29 use $latest_29 @@ -426,8 +430,10 @@ are not special. -scala-home use the scala build at the specified directory -scala-version use the specified version of scala -binary-version use the specified scala version when searching for dependencies + # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) -java-home alternate JAVA_HOME + # passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution # The default set is used if JVM_OPTS is unset and no -jvm-opts file is found $(default_jvm_opts) @@ -437,12 +443,14 @@ are not special. -jvm-opts file containing jvm args (if not given, .jvmopts in project root is used if present) -Dkey=val pass -Dkey=val directly to the jvm -J-X pass option -X directly to the jvm (-J is stripped) + # passing options to sbt, OR to this runner SBT_OPTS environment variable holding either the sbt args directly, or the reference to a file containing sbt args if given path is prepended by '@' (e.g. '@/etc/sbtopts') Note: "@"-file is overridden by local '.sbtopts' or '-sbt-opts' argument. -sbt-opts file containing sbt args (if not given, .sbtopts in project root is used if present) -S-X add -X to sbt's scalacOptions (-S is stripped) + # passing options exclusively to this runner SBTX_OPTS environment variable holding either the sbt-extras args directly, or the reference to a file containing sbt-extras args if given path is prepended by '@' (e.g. '@/etc/sbtxopts') @@ -595,6 +603,7 @@ fi $(pwd) doesn't appear to be an sbt project. If you want to start sbt anyway, run: $0 -sbt-create + EOM exit 1 }