| /* | |
| * 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. | |
| */ | |
| #pragma once | |
| /// \file iceberg/geospatial.h | |
| /// \brief Geospatial bounds and intersection utilities. | |
| #include <cstdint> | |
| #include <optional> | |
| #include <span> | |
| #include <vector> | |
| #include "iceberg/iceberg_export.h" | |
| #include "iceberg/result.h" | |
| #include "iceberg/type_fwd.h" | |
| namespace iceberg { | |
| /// \brief A point used as a lower or upper geospatial column bound. | |
| class ICEBERG_EXPORT GeospatialBound { | |
| public: | |
| /// \brief Create a two-dimensional bound. | |
| static GeospatialBound XY(double x, double y); | |
| /// \brief Create a bound with a Z coordinate. | |
| static GeospatialBound XYZ(double x, double y, double z); | |
| /// \brief Create a bound with an M coordinate. | |
| static GeospatialBound XYM(double x, double y, double m); | |
| /// \brief Create a bound with Z and M coordinates. | |
| static GeospatialBound XYZM(double x, double y, double z, double m); | |
| /// \brief Return the X coordinate. | |
| double x() const { return x_; } | |
| /// \brief Return the Y coordinate. | |
| double y() const { return y_; } | |
| /// \brief Return the optional Z coordinate. | |
| const std::optional<double>& z() const { return z_; } | |
| /// \brief Return the optional M coordinate. | |
| const std::optional<double>& m() const { return m_; } | |
| /// \brief Decode a little-endian geospatial bound. | |
| static Result<GeospatialBound> Deserialize(std::span<const uint8_t> bytes); | |
| /// \brief Encode this bound using little-endian encoding. | |
| std::vector<uint8_t> Serialize() const; | |
| friend bool operator==(const GeospatialBound&, const GeospatialBound&) = default; | |
| private: | |
| GeospatialBound(double x, double y, std::optional<double> z, std::optional<double> m); | |
| double x_; | |
| double y_; | |
| std::optional<double> z_; | |
| std::optional<double> m_; | |
| }; | |
| /// \brief A pair of lower and upper geospatial column bounds. | |
| class ICEBERG_EXPORT BoundingBox { | |
| public: | |
| /// \brief Create a bounding box from lower and upper bounds. | |
| BoundingBox(GeospatialBound lower, GeospatialBound upper); | |
| /// \brief Return the lower bound. | |
| const GeospatialBound& lower() const { return lower_; } | |
| /// \brief Return the upper bound. | |
| const GeospatialBound& upper() const { return upper_; } | |
| /// \brief Decode a bounding box from separate lower and upper encodings. | |
| static Result<BoundingBox> Deserialize(std::span<const uint8_t> lower, | |
| std::span<const uint8_t> upper); | |
| /// \brief Decode a bounding box from Iceberg's combined encoding. | |
| static Result<BoundingBox> Deserialize(std::span<const uint8_t> bytes); | |
| /// \brief Encode this bounding box using Iceberg's combined encoding. | |
| std::vector<uint8_t> Serialize() const; | |
| friend bool operator==(const BoundingBox&, const BoundingBox&) = default; | |
| private: | |
| GeospatialBound lower_; | |
| GeospatialBound upper_; | |
| }; | |
| /// \brief Check whether two bounding boxes intersect for an Iceberg geospatial type. | |
| /// | |
| /// Returns an error for invalid boxes or a non-geospatial type. | |
| ICEBERG_EXPORT Result<bool> GeospatialBoundsIntersect(const Type& type, | |
| const BoundingBox& lhs, | |
| const BoundingBox& rhs); | |
| } // namespace iceberg |