Kontinuation commented on code in PR #615: URL: https://github.com/apache/sedona-db/pull/615#discussion_r2896344656
########## rust/sedona-raster-functions/src/crs_utils.rs: ########## @@ -0,0 +1,428 @@ +// 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. + +use std::sync::{Arc, LazyLock}; + +use datafusion_common::{exec_datafusion_err, DataFusionError, Result}; +use sedona_geometry::transform::{transform, CrsEngine}; +use sedona_proj::transform::with_global_proj_engine; +use sedona_schema::crs::{deserialize_crs, lnglat, CoordinateReferenceSystem}; +use wkb::reader::read_wkb; + +/// Cached default CRS (WGS84 longitude/latitude). Initialized once on first access. +static DEFAULT_CRS: LazyLock<Arc<dyn CoordinateReferenceSystem + Send + Sync>> = + LazyLock::new(|| lnglat().expect("lnglat() should always succeed")); + +/// Run a closure with the active CRS engine, abstracting away the engine choice. +/// +/// We keep this API engine-agnostic to allow future engines beyond PROJ; the +/// current implementation uses PROJ via `with_global_proj_engine`. +pub fn with_crs_engine<R, F: FnMut(&dyn CrsEngine) -> Result<R>>(mut func: F) -> Result<R> { + with_global_proj_engine(|engine| func(engine)) +} + +/// Resolve an optional CRS string to a concrete CRS object. +/// +/// - If `crs_str` is `Some` and deserializes to a known CRS, that CRS is returned. +/// - Otherwise (None, empty, "0", etc.), the default WGS84 lnglat CRS is returned. +pub fn resolve_crs( + crs_str: Option<&str>, +) -> Result<Arc<dyn CoordinateReferenceSystem + Send + Sync>> { + if let Some(crs_str) = crs_str { + let crs = deserialize_crs(crs_str)?; + Ok(crs.unwrap_or_else(|| DEFAULT_CRS.clone())) + } else { + Ok(DEFAULT_CRS.clone()) + } +} + +/// Return a reference to the default CRS (WGS84 longitude/latitude). +/// +/// This is a zero-cost accessor backed by a `LazyLock` static — no allocation +/// or atomic ref-count increment on each call. +pub fn default_crs() -> &'static (dyn CoordinateReferenceSystem + Send + Sync) { + DEFAULT_CRS.as_ref() +} + +/// Transform a geometry encoded as WKB from one CRS to another. +/// +/// This is a utility used by raster/spatial functions to reproject a geometry +/// without leaking PROJ engine details into call sites. +/// +/// **Behavior** +/// - If `from_crs` and `to_crs` are equal, returns the original WKB (clone) without decoding. +/// - Otherwise, builds a PROJ pipeline and transforms all coordinates. +/// +/// **Errors** +/// - Returns an error if WKB parsing fails, PROJ cannot build the CRS-to-CRS transform, +/// or if the coordinate transformation itself fails. +pub fn crs_transform_wkb( + wkb: &[u8], + from_crs: &dyn CoordinateReferenceSystem, + to_crs: &dyn CoordinateReferenceSystem, +) -> Result<Vec<u8>> { Review Comment: Moved the CRS equivalence check before calling this function. This will eliminate one allocation and WKB buffer copying when CRSes are equivalent. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
