use crate::impl_from_str;
use crate::temporal::interpolation::TInterpolation;
use crate::temporal::{tinstant::TInstant, tsequence::TSequence};
use core::fmt;
use std::{ffi::CString, hash::Hash, mem, ptr, str::FromStr};
use crate::temporal::tsequence_set::TSequenceSet;
use crate::{
boxes::STBox,
collections::base::{impl_collection, Collection},
errors::ParseError,
factory,
temporal::{
tbool::{TBool, TBoolInstant, TBoolSequence, TBoolSequenceSet},
temporal::{
impl_always_and_ever_value_equality_functions, impl_simple_traits_for_temporal,
SimplifiableTemporal, Temporal,
},
},
utils::to_meos_timestamp,
MeosEnum,
};
use chrono::{DateTime, TimeZone};
use geos::Geometry;
use super::tpoint::{
create_set_of_geometries, geometry_to_gserialized, gserialized_to_geometry, impl_tpoint_traits,
TPointTrait,
};
pub struct TGeomPointInstant {
_inner: ptr::NonNull<meos_sys::TInstant>,
}
impl_tpoint_traits!(TGeomPointInstant, Instant, false, Geom);
impl TInstant for TGeomPointInstant {
fn from_inner(inner: *mut meos_sys::TInstant) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
fn inner_as_tinstant(&self) -> *const meos_sys::TInstant {
self._inner.as_ptr()
}
fn from_value_and_timestamp<Tz: TimeZone>(value: Self::Type, timestamp: DateTime<Tz>) -> Self {
Self::from_inner(unsafe {
meos_sys::tpointinst_make(
geometry_to_gserialized(&value),
to_meos_timestamp(×tamp),
)
})
}
}
impl<Tz: TimeZone> From<(Geometry, DateTime<Tz>)> for TGeomPointInstant {
fn from((value, timestamp): (Geometry, DateTime<Tz>)) -> Self {
Self::from_value_and_timestamp(value, timestamp)
}
}
impl TPointTrait<false> for TGeomPointInstant {}
pub struct TGeomPointSequence {
_inner: ptr::NonNull<meos_sys::TSequence>,
}
impl TGeomPointSequence {
pub fn direction(&self) -> f64 {
let mut result = 0.;
let _ = unsafe { meos_sys::tpoint_direction(self.inner(), ptr::addr_of_mut!(result)) };
result
}
}
impl_tpoint_traits!(TGeomPointSequence, Sequence, false, Geom);
impl TSequence for TGeomPointSequence {
fn from_inner(inner: *mut meos_sys::TSequence) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
fn inner_mut_as_tsequence(&self) -> *mut meos_sys::TSequence {
self._inner.as_ptr()
}
}
impl TPointTrait<false> for TGeomPointSequence {}
pub struct TGeomPointSequenceSet {
_inner: ptr::NonNull<meos_sys::TSequenceSet>,
}
impl TGeomPointSequenceSet {
pub fn direction(&self) -> f64 {
let mut result = 0.;
let _ = unsafe { meos_sys::tpoint_direction(self.inner(), ptr::addr_of_mut!(result)) };
result
}
}
impl_tpoint_traits!(TGeomPointSequenceSet, SequenceSet, false, Geom);
impl TSequenceSet for TGeomPointSequenceSet {
fn from_inner(inner: *mut meos_sys::TSequenceSet) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
}
impl TPointTrait<false> for TGeomPointSequenceSet {}
#[derive(Debug)]
pub enum TGeomPoint {
Instant(TGeomPointInstant),
Sequence(TGeomPointSequence),
SequenceSet(TGeomPointSequenceSet),
}
impl_from_str!(TGeomPoint);
impl TPointTrait<false> for TGeomPoint {}
impl MeosEnum for TGeomPoint {
fn from_instant(inner: *mut meos_sys::TInstant) -> Self {
Self::Instant(TGeomPointInstant::from_inner(inner))
}
fn from_sequence(inner: *mut meos_sys::TSequence) -> Self {
Self::Sequence(TGeomPointSequence::from_inner(inner))
}
fn from_sequence_set(inner: *mut meos_sys::TSequenceSet) -> Self {
Self::SequenceSet(TGeomPointSequenceSet::from_inner(inner))
}
fn from_mfjson(mfjson: &str) -> Self {
let cstr = CString::new(mfjson).unwrap();
factory::<Self>(unsafe { meos_sys::tint_from_mfjson(cstr.as_ptr()) })
}
}
impl FromIterator<TGeomPointInstant> for TGeomPointSequence {
fn from_iter<T: IntoIterator<Item = TGeomPointInstant>>(iter: T) -> Self {
let vec: Vec<TGeomPointInstant> = iter.into_iter().collect();
Self::new(&vec, TInterpolation::Linear)
}
}
impl<'a> FromIterator<&'a TGeomPointInstant> for TGeomPointSequence {
fn from_iter<T: IntoIterator<Item = &'a TGeomPointInstant>>(iter: T) -> Self {
let vec: Vec<&TGeomPointInstant> = iter.into_iter().collect();
Self::new(&vec, TInterpolation::Linear)
}
}
impl<Tz: TimeZone> FromIterator<(Geometry, DateTime<Tz>)> for TGeomPointSequence {
fn from_iter<T: IntoIterator<Item = (Geometry, DateTime<Tz>)>>(iter: T) -> Self {
iter.into_iter()
.map(Into::<TGeomPointInstant>::into)
.collect()
}
}
impl Collection for TGeomPoint {
impl_collection!(tspatial, Geometry);
fn contains(&self, element: &Self::Type) -> bool {
unsafe {
meos_sys::contains_tspatial_stbox(
self.inner(),
meos_sys::geo_to_stbox(geometry_to_gserialized(element)),
)
}
}
}
impl_simple_traits_for_temporal!(TGeomPoint);
impl SimplifiableTemporal for TGeomPoint {}
impl Temporal for TGeomPoint {
type TI = TGeomPointInstant;
type TS = TGeomPointSequence;
type TSS = TGeomPointSequenceSet;
type TBB = STBox;
type Enum = TGeomPoint;
type TBoolType = TBool;
impl_always_and_ever_value_equality_functions!(geo, geometry_to_gserialized);
fn from_inner_as_temporal(inner: *mut meos_sys::Temporal) -> Self {
factory::<Self>(inner)
}
fn inner(&self) -> *const meos_sys::Temporal {
match self {
TGeomPoint::Instant(value) => value.inner(),
TGeomPoint::Sequence(value) => value.inner(),
TGeomPoint::SequenceSet(value) => value.inner(),
}
}
fn bounding_box(&self) -> Self::TBB {
STBox::from_inner(unsafe { meos_sys::tspatial_to_stbox(self.inner()) })
}
fn values(&self) -> Vec<Self::Type> {
let mut count = 0;
unsafe {
let values = meos_sys::tgeo_values(self.inner(), ptr::addr_of_mut!(count));
std::slice::from_raw_parts(values, count as usize)
.iter()
.map(|&gs| gserialized_to_geometry(gs))
.map(Result::unwrap)
.collect()
}
}
fn start_value(&self) -> Self::Type {
gserialized_to_geometry(unsafe { meos_sys::tgeo_start_value(self.inner()) }).unwrap()
}
fn end_value(&self) -> Self::Type {
gserialized_to_geometry(unsafe { meos_sys::tgeo_end_value(self.inner()) }).unwrap()
}
fn value_at_timestamp<Tz: TimeZone>(&self, timestamp: DateTime<Tz>) -> Option<Self::Type> {
let mut result: mem::MaybeUninit<*mut meos_sys::GSERIALIZED> = mem::MaybeUninit::uninit();
unsafe {
let success = meos_sys::tgeo_value_at_timestamptz(
self.inner(),
to_meos_timestamp(×tamp),
true,
result.as_mut_ptr(),
);
if success {
Some(gserialized_to_geometry(result.assume_init()).unwrap())
} else {
None
}
}
}
fn at_value(&self, value: &Self::Type) -> Option<Self::Enum> {
let result =
unsafe { meos_sys::tpoint_at_value(self.inner(), geometry_to_gserialized(value)) };
if result.is_null() {
None
} else {
Some(factory::<Self::Enum>(result))
}
}
fn at_values(&self, values: &[Self::Type]) -> Option<Self::Enum> {
unsafe {
let set = create_set_of_geometries(values);
let result = meos_sys::temporal_at_values(self.inner(), set);
if result.is_null() {
None
} else {
Some(factory::<Self::Enum>(result))
}
}
}
fn minus_value(&self, value: Self::Type) -> Self::Enum {
factory::<Self::Enum>(unsafe {
meos_sys::tpoint_minus_value(self.inner(), geometry_to_gserialized(&value))
})
}
fn minus_values(&self, values: &[Self::Type]) -> Self::Enum {
factory::<Self::Enum>(unsafe {
let set = create_set_of_geometries(values);
meos_sys::temporal_minus_values(self.inner(), set)
})
}
fn temporal_equal_value(&self, value: &Self::Type) -> Self::TBoolType {
Self::TBoolType::from_inner_as_temporal(unsafe {
meos_sys::teq_tgeo_geo(self.inner(), geometry_to_gserialized(value))
})
}
fn temporal_not_equal_value(&self, value: &Self::Type) -> Self::TBoolType {
Self::TBoolType::from_inner_as_temporal(unsafe {
meos_sys::tne_tgeo_geo(self.inner(), geometry_to_gserialized(value))
})
}
}