common_function/scalars/geo/
measure.rs1use common_error::ext::{BoxedError, PlainError};
16use common_error::status_code::StatusCode;
17use common_query::error::{self, Result};
18use common_query::prelude::{Signature, TypeSignature};
19use datafusion::logical_expr::Volatility;
20use datatypes::prelude::ConcreteDataType;
21use datatypes::scalars::ScalarVectorBuilder;
22use datatypes::vectors::{Float64VectorBuilder, MutableVector, VectorRef};
23use derive_more::Display;
24use geo::algorithm::line_measures::metric_spaces::Euclidean;
25use geo::{Area, Distance, Haversine};
26use geo_types::Geometry;
27use snafu::ResultExt;
28
29use crate::function::{Function, FunctionContext};
30use crate::scalars::geo::helpers::{ensure_columns_len, ensure_columns_n};
31use crate::scalars::geo::wkt::parse_wkt;
32
33#[derive(Clone, Debug, Default, Display)]
35#[display("{}", self.name())]
36pub struct STDistance;
37
38impl Function for STDistance {
39 fn name(&self) -> &str {
40 "st_distance"
41 }
42
43 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
44 Ok(ConcreteDataType::float64_datatype())
45 }
46
47 fn signature(&self) -> Signature {
48 Signature::new(
49 TypeSignature::Exact(vec![
50 ConcreteDataType::string_datatype(),
51 ConcreteDataType::string_datatype(),
52 ]),
53 Volatility::Stable,
54 )
55 }
56
57 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
58 ensure_columns_n!(columns, 2);
59
60 let wkt_this_vec = &columns[0];
61 let wkt_that_vec = &columns[1];
62
63 let size = wkt_this_vec.len();
64 let mut results = Float64VectorBuilder::with_capacity(size);
65
66 for i in 0..size {
67 let wkt_this = wkt_this_vec.get(i).as_string();
68 let wkt_that = wkt_that_vec.get(i).as_string();
69
70 let result = match (wkt_this, wkt_that) {
71 (Some(wkt_this), Some(wkt_that)) => {
72 let geom_this = parse_wkt(&wkt_this)?;
73 let geom_that = parse_wkt(&wkt_that)?;
74
75 Some(Euclidean::distance(&geom_this, &geom_that))
76 }
77 _ => None,
78 };
79
80 results.push(result);
81 }
82
83 Ok(results.to_vector())
84 }
85}
86
87#[derive(Clone, Debug, Default, Display)]
89#[display("{}", self.name())]
90pub struct STDistanceSphere;
91
92impl Function for STDistanceSphere {
93 fn name(&self) -> &str {
94 "st_distance_sphere_m"
95 }
96
97 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
98 Ok(ConcreteDataType::float64_datatype())
99 }
100
101 fn signature(&self) -> Signature {
102 Signature::new(
103 TypeSignature::Exact(vec![
104 ConcreteDataType::string_datatype(),
105 ConcreteDataType::string_datatype(),
106 ]),
107 Volatility::Stable,
108 )
109 }
110
111 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
112 ensure_columns_n!(columns, 2);
113
114 let wkt_this_vec = &columns[0];
115 let wkt_that_vec = &columns[1];
116
117 let size = wkt_this_vec.len();
118 let mut results = Float64VectorBuilder::with_capacity(size);
119
120 for i in 0..size {
121 let wkt_this = wkt_this_vec.get(i).as_string();
122 let wkt_that = wkt_that_vec.get(i).as_string();
123
124 let result = match (wkt_this, wkt_that) {
125 (Some(wkt_this), Some(wkt_that)) => {
126 let geom_this = parse_wkt(&wkt_this)?;
127 let geom_that = parse_wkt(&wkt_that)?;
128
129 match (geom_this, geom_that) {
130 (Geometry::Point(this), Geometry::Point(that)) => {
131 Some(Haversine::distance(this, that))
132 }
133 _ => {
134 Err(BoxedError::new(PlainError::new(
135 "Great circle distance between non-point objects are not supported for now.".to_string(),
136 StatusCode::Unsupported,
137 ))).context(error::ExecuteSnafu)?
138 }
139 }
140 }
141 _ => None,
142 };
143
144 results.push(result);
145 }
146
147 Ok(results.to_vector())
148 }
149}
150
151#[derive(Clone, Debug, Default, Display)]
153#[display("{}", self.name())]
154pub struct STArea;
155
156impl Function for STArea {
157 fn name(&self) -> &str {
158 "st_area"
159 }
160
161 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
162 Ok(ConcreteDataType::float64_datatype())
163 }
164
165 fn signature(&self) -> Signature {
166 Signature::new(
167 TypeSignature::Exact(vec![ConcreteDataType::string_datatype()]),
168 Volatility::Stable,
169 )
170 }
171
172 fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
173 ensure_columns_n!(columns, 1);
174
175 let wkt_vec = &columns[0];
176
177 let size = wkt_vec.len();
178 let mut results = Float64VectorBuilder::with_capacity(size);
179
180 for i in 0..size {
181 let wkt = wkt_vec.get(i).as_string();
182
183 let result = if let Some(wkt) = wkt {
184 let geom = parse_wkt(&wkt)?;
185 Some(geom.unsigned_area())
186 } else {
187 None
188 };
189
190 results.push(result);
191 }
192
193 Ok(results.to_vector())
194 }
195}