| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <cmath> |
| #include <cstring> |
| |
| #include "parquet/geospatial/util_internal.h" |
| #include "parquet/test_util.h" |
| |
| namespace parquet::geospatial { |
| |
| TEST(TestGeometryUtil, TestBoundingBox) { |
| BoundingBox box; |
| EXPECT_EQ(box, BoundingBox({kInf, kInf, kInf, kInf}, {-kInf, -kInf, -kInf, -kInf})); |
| EXPECT_EQ(box.ToString(), |
| "BoundingBox\n x: [inf, -inf]\n y: [inf, -inf]\n z: [inf, -inf]\n m: " |
| "[inf, -inf]\n"); |
| |
| BoundingBox box_xyzm({-1, -2, -3, -4}, {1, 2, 3, 4}); |
| BoundingBox box_xy({-10, -20, kInf, kInf}, {10, 20, -kInf, -kInf}); |
| BoundingBox box_xyz({kInf, kInf, -30, kInf}, {-kInf, -kInf, 30, -kInf}); |
| BoundingBox box_xym({kInf, kInf, kInf, -40}, {-kInf, -kInf, -kInf, 40}); |
| |
| box_xyzm.Merge(box_xy); |
| EXPECT_EQ(box_xyzm, BoundingBox({-10, -20, -3, -4}, {10, 20, 3, 4})); |
| EXPECT_EQ(box_xyzm.ToString(), |
| "BoundingBox\n x: [-10, 10]\n y: [-20, 20]\n z: [-3, 3]\n m: " |
| "[-4, 4]\n"); |
| |
| box_xyzm.Merge(box_xyz); |
| EXPECT_EQ(box_xyzm, BoundingBox({-10, -20, -30, -4}, {10, 20, 30, 4})); |
| |
| box_xyzm.Merge(box_xym); |
| EXPECT_EQ(box_xyzm, BoundingBox({-10, -20, -30, -40}, {10, 20, 30, 40})); |
| |
| double nan_dbl = std::numeric_limits<double>::quiet_NaN(); |
| BoundingBox box_nan({nan_dbl, nan_dbl, nan_dbl, nan_dbl}, |
| {nan_dbl, nan_dbl, nan_dbl, nan_dbl}); |
| box_xyzm.Merge(box_nan); |
| for (int i = 0; i < 4; i++) { |
| EXPECT_TRUE(std::isnan(box_xyzm.min[i])); |
| EXPECT_TRUE(std::isnan(box_xyzm.max[i])); |
| } |
| |
| box_xyzm.Reset(); |
| EXPECT_EQ(box_xyzm, BoundingBox()); |
| } |
| |
| TEST(TestGeometryUtil, TestBoundingBoxEquals) { |
| BoundingBox box_a({-1, -2, -3, -4}, {1, 2, 3, 4}); |
| BoundingBox box_b({-1, -2, -3, -4}, {1, 2, 3, 4}); |
| |
| for (int i = 0; i < 4; i++) { |
| // Set one min component to another value and ensure inequality |
| box_b.min[i] = -1000; |
| EXPECT_NE(box_a, box_b); |
| |
| // Reset the min component and ensure equality |
| box_b.min = box_a.min; |
| EXPECT_EQ(box_a, box_b); |
| |
| // Set one max component to another value and ensure inequality |
| box_b.max[i] = -1000; |
| EXPECT_NE(box_a, box_b); |
| |
| // Reset the max component and ensure equality |
| box_b.max = box_a.max; |
| EXPECT_EQ(box_a, box_b); |
| } |
| } |
| |
| struct WKBTestCase { |
| WKBTestCase() = default; |
| WKBTestCase(GeometryType geometry_type, Dimensions dimensions, |
| const std::vector<uint8_t>& wkb, const std::vector<double>& box_values = {}) |
| : geometry_type(geometry_type), dimensions(dimensions), wkb(wkb) { |
| std::array<double, 4> mins = {kInf, kInf, kInf, kInf}; |
| std::array<double, 4> maxes{-kInf, -kInf, -kInf, -kInf}; |
| |
| if (dimensions == Dimensions::kXYM) { |
| mins = {box_values[0], box_values[1], kInf, box_values[2]}; |
| maxes = {box_values[3], box_values[4], -kInf, box_values[5]}; |
| } else { |
| size_t coord_size = box_values.size() / 2; |
| for (uint32_t i = 0; i < coord_size; i++) { |
| mins[i] = box_values[i]; |
| maxes[i] = box_values[coord_size + i]; |
| } |
| } |
| |
| box = BoundingBox(mins, maxes); |
| } |
| WKBTestCase(const WKBTestCase& other) = default; |
| |
| GeometryType geometry_type; |
| Dimensions dimensions; |
| std::vector<uint8_t> wkb; |
| BoundingBox box; |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, const WKBTestCase& obj) { |
| uint32_t iso_wkb_geometry_type = |
| static_cast<int>(obj.dimensions) * 1000 + static_cast<int>(obj.geometry_type); |
| os << "WKBTestCase<" << iso_wkb_geometry_type << ">"; |
| return os; |
| } |
| |
| class WKBTestFixture : public ::testing::TestWithParam<WKBTestCase> { |
| protected: |
| WKBTestCase test_case; |
| }; |
| |
| TEST_P(WKBTestFixture, TestWKBBounderBounds) { |
| auto item = GetParam(); |
| |
| WKBGeometryBounder bounder; |
| EXPECT_EQ(bounder.Bounds(), BoundingBox()); |
| |
| ASSERT_NO_THROW(bounder.MergeGeometry(item.wkb)); |
| |
| EXPECT_EQ(bounder.Bounds(), item.box); |
| uint32_t wkb_type = |
| static_cast<int>(item.dimensions) * 1000 + static_cast<int>(item.geometry_type); |
| EXPECT_THAT(bounder.GeometryTypes(), ::testing::ElementsAre(::testing::Eq(wkb_type))); |
| |
| bounder.Reset(); |
| EXPECT_EQ(bounder.Bounds(), BoundingBox()); |
| EXPECT_TRUE(bounder.GeometryTypes().empty()); |
| } |
| |
| TEST_P(WKBTestFixture, TestWKBBounderErrorForTruncatedInput) { |
| auto item = GetParam(); |
| WKBGeometryBounder bounder; |
| |
| // Make sure an error occurs for any version of truncated input to the bounder |
| for (size_t i = 0; i < item.wkb.size(); i++) { |
| SCOPED_TRACE(i); |
| ASSERT_THROW(bounder.MergeGeometry({item.wkb.data(), i}), ParquetException); |
| } |
| } |
| |
| TEST_P(WKBTestFixture, TestWKBBounderErrorForInputWithTooManyBytes) { |
| auto item = GetParam(); |
| WKBGeometryBounder bounder; |
| |
| std::vector<uint8_t> wkb_with_extra_byte(item.wkb.size() + 1); |
| std::memcpy(wkb_with_extra_byte.data(), item.wkb.data(), item.wkb.size()); |
| wkb_with_extra_byte[item.wkb.size()] = 0x00; |
| |
| ASSERT_THROW(bounder.MergeGeometry(wkb_with_extra_byte), ParquetException); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| TestGeometryUtil, WKBTestFixture, |
| ::testing::Values( |
| // POINT EMPTY |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXY, |
| {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f}, |
| {kInf, kInf, -kInf, -kInf}), |
| // POINT (30 10) |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXY, |
| {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40}, |
| {30, 10, 30, 10}), |
| // POINT Z (30 10 40) |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXYZ, |
| {0x01, 0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {30, 10, 40, 30, 10, 40}), |
| // POINT M (30 10 300) |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXYM, |
| {0x01, 0xd1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 300, 30, 10, 300}), |
| // POINT ZM (30 10 40 300) |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXYZM, |
| {0x01, 0xb9, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 40, 300, 30, 10, 40, 300}), |
| // POINT (30 10) (big endian) |
| WKBTestCase(GeometryType::kPoint, Dimensions::kXY, |
| {0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x40, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {30, 10, 30, 10}), |
| // LINESTRING EMPTY |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXY, |
| {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // LINESTRING (30 10, 10 30, 40 40) |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXY, |
| {0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {10, 10, 40, 40}), |
| // LINESTRING Z (30 10 40, 10 30 40, 40 40 80) |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXYZ, |
| {0x01, 0xea, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x54, 0x40}, |
| {10, 10, 40, 40, 40, 80}), |
| // LINESTRING M (30 10 300, 10 30 300, 40 40 1600) |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXYM, |
| {0x01, 0xd2, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, |
| 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x99, 0x40}, |
| {10, 10, 300, 40, 40, 1600}), |
| // LINESTRING ZM (30 10 40 300, 10 30 40 300, 40 40 80 1600) |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXYZM, |
| {0x01, 0xba, 0x0b, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x99, 0x40}, |
| {10, 10, 40, 300, 40, 40, 80, 1600}), |
| // LINESTRING (30 10, 10 30, 40 40) (big endian) |
| WKBTestCase(GeometryType::kLinestring, Dimensions::kXY, |
| {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x40, |
| 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, |
| 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {10, 10, 40, 40}), |
| // POLYGON EMPTY |
| WKBTestCase(GeometryType::kPolygon, Dimensions::kXY, |
| {0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10)) |
| WKBTestCase(GeometryType::kPolygon, Dimensions::kXY, |
| {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x40}, |
| {10, 10, 40, 40}), |
| // POLYGON Z ((30 10 40, 40 40 80, 20 40 60, 10 20 30, 30 10 40)) |
| WKBTestCase( |
| GeometryType::kPolygon, Dimensions::kXYZ, |
| {0x01, 0xeb, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x44, 0x40}, |
| {10, 10, 30, 40, 40, 80}), |
| // POLYGON M ((30 10 300, 40 40 1600, 20 40 800, 10 20 200, 30 10 300)) |
| WKBTestCase( |
| GeometryType::kPolygon, Dimensions::kXYM, |
| {0x01, 0xd3, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0xc0, 0x72, 0x40}, |
| {10, 10, 200, 40, 40, 1600}), |
| // POLYGON ZM ((30 10 40 300, 40 40 80 1600, 20 40 60 800, 10 20 30 200, 30 10 40 |
| // 300)) |
| WKBTestCase( |
| GeometryType::kPolygon, Dimensions::kXYZM, |
| {0x01, 0xbb, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0xc0, 0x72, 0x40}, |
| {10, 10, 30, 200, 40, 40, 80, 1600}), |
| // MULTIPOINT EMPTY |
| WKBTestCase(GeometryType::kMultiPoint, Dimensions::kXY, |
| {0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // MULTIPOINT ((30 10)) |
| WKBTestCase(GeometryType::kMultiPoint, Dimensions::kXY, |
| {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40}, |
| {30, 10, 30, 10}), |
| // MULTIPOINT Z ((30 10 40)) |
| WKBTestCase(GeometryType::kMultiPoint, Dimensions::kXYZ, |
| {0x01, 0xec, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {30, 10, 40, 30, 10, 40}), |
| // MULTIPOINT M ((30 10 300)) |
| WKBTestCase(GeometryType::kMultiPoint, Dimensions::kXYM, |
| {0x01, 0xd4, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xd1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 300, 30, 10, 300}), |
| // MULTIPOINT ZM ((30 10 40 300)) |
| WKBTestCase(GeometryType::kMultiPoint, Dimensions::kXYZM, |
| {0x01, 0xbc, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xb9, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 40, 300, 30, 10, 40, 300}), |
| // MULTILINESTRING EMPTY |
| WKBTestCase(GeometryType::kMultiLinestring, Dimensions::kXY, |
| {0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // MULTILINESTRING ((30 10, 10 30, 40 40)) |
| WKBTestCase(GeometryType::kMultiLinestring, Dimensions::kXY, |
| {0x01, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {10, 10, 40, 40}), |
| // MULTILINESTRING Z ((30 10 40, 10 30 40, 40 40 80)) |
| WKBTestCase( |
| GeometryType::kMultiLinestring, Dimensions::kXYZ, |
| {0x01, 0xed, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xea, 0x03, 0x00, |
| 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40}, |
| {10, 10, 40, 40, 40, 80}), |
| // MULTILINESTRING M ((30 10 300, 10 30 300, 40 40 1600)) |
| WKBTestCase( |
| GeometryType::kMultiLinestring, Dimensions::kXYM, |
| {0x01, 0xd5, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd2, 0x07, 0x00, |
| 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x40}, |
| {10, 10, 300, 40, 40, 1600}), |
| // MULTILINESTRING ZM ((30 10 40 300, 10 30 40 300, 40 40 80 1600)) |
| WKBTestCase( |
| GeometryType::kMultiLinestring, Dimensions::kXYZM, |
| {0x01, 0xbd, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xba, 0x0b, 0x00, |
| 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x40}, |
| {10, 10, 40, 300, 40, 40, 80, 1600}), |
| // MULTIPOLYGON EMPTY |
| WKBTestCase(GeometryType::kMultiPolygon, Dimensions::kXY, |
| {0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // MULTIPOLYGON (((30 10, 40 40, 20 40, 10 20, 30 10))) |
| WKBTestCase( |
| GeometryType::kMultiPolygon, Dimensions::kXY, |
| {0x01, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40}, |
| {10, 10, 40, 40}), |
| // MULTIPOLYGON Z (((30 10 40, 40 40 80, 20 40 60, 10 20 30, 30 10 40))) |
| WKBTestCase( |
| GeometryType::kMultiPolygon, Dimensions::kXYZ, |
| {0x01, 0xee, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xeb, 0x03, 0x00, |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x4e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {10, 10, 30, 40, 40, 80}), |
| // MULTIPOLYGON M (((30 10 300, 40 40 1600, 20 40 800, 10 20 200, 30 10 300))) |
| WKBTestCase( |
| GeometryType::kMultiPolygon, Dimensions::kXYM, |
| {0x01, 0xd6, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x07, 0x00, |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x99, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {10, 10, 200, 40, 40, 1600}), |
| // MULTIPOLYGON ZM (((30 10 40 300, 40 40 80 1600, 20 40 60 800, 10 20 30 200, 30 |
| // 10 40 300))) |
| WKBTestCase(GeometryType::kMultiPolygon, Dimensions::kXYZM, |
| {0x01, 0xbe, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xbb, |
| 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x40, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, |
| 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {10, 10, 30, 200, 40, 40, 80, 1600}), |
| // GEOMETRYCOLLECTION EMPTY |
| WKBTestCase(GeometryType::kGeometryCollection, Dimensions::kXY, |
| {0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| {kInf, kInf, -kInf, -kInf}), |
| // GEOMETRYCOLLECTION (POINT (30 10)) |
| WKBTestCase(GeometryType::kGeometryCollection, Dimensions::kXY, |
| {0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40}, |
| {30, 10, 30, 10}), |
| // GEOMETRYCOLLECTION Z (POINT Z (30 10 40)) |
| WKBTestCase(GeometryType::kGeometryCollection, Dimensions::kXYZ, |
| {0x01, 0xef, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40}, |
| {30, 10, 40, 30, 10, 40}), |
| // GEOMETRYCOLLECTION M (POINT M (30 10 300)) |
| WKBTestCase(GeometryType::kGeometryCollection, Dimensions::kXYM, |
| {0x01, 0xd7, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xd1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 300, 30, 10, 300}), |
| // GEOMETRYCOLLECTION ZM (POINT ZM (30 10 40 300)) |
| WKBTestCase(GeometryType::kGeometryCollection, Dimensions::kXYZM, |
| {0x01, 0xbf, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
| 0xb9, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40}, |
| {30, 10, 40, 300, 30, 10, 40, 300}))); |
| |
| struct MakeWKBPointTestCase { |
| std::vector<double> xyzm; |
| bool has_z{}; |
| bool has_m{}; |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, const MakeWKBPointTestCase& obj) { |
| os << "MakeWKBPointTestCase<has_z=" << obj.has_z << ", has_m=" << obj.has_m << ">"; |
| return os; |
| } |
| |
| class MakeWKBPointTestFixture : public testing::TestWithParam<MakeWKBPointTestCase> {}; |
| |
| TEST_P(MakeWKBPointTestFixture, MakeWKBPoint) { |
| const auto& param = GetParam(); |
| std::string wkb = test::MakeWKBPoint(param.xyzm, param.has_z, param.has_m); |
| WKBGeometryBounder bounder; |
| ASSERT_NO_THROW(bounder.MergeGeometry(wkb)); |
| const BoundingBox::XYZM& mins = bounder.Bounds().min; |
| EXPECT_DOUBLE_EQ(param.xyzm[0], mins[0]); |
| EXPECT_DOUBLE_EQ(param.xyzm[1], mins[1]); |
| if (param.has_z) { |
| EXPECT_DOUBLE_EQ(param.xyzm[2], mins[2]); |
| } else { |
| EXPECT_TRUE(std::isinf(mins[2])); |
| } |
| if (param.has_m) { |
| EXPECT_DOUBLE_EQ(param.xyzm[3], mins[3]); |
| } else { |
| EXPECT_TRUE(std::isinf(mins[3])); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| TestGeometryUtil, MakeWKBPointTestFixture, |
| ::testing::Values(MakeWKBPointTestCase{{30, 10, 40, 300}, false, false}, |
| MakeWKBPointTestCase{{30, 10, 40, 300}, true, false}, |
| MakeWKBPointTestCase{{30, 10, 40, 300}, false, true}, |
| MakeWKBPointTestCase{{30, 10, 40, 300}, true, true})); |
| |
| } // namespace parquet::geospatial |