Skip to content

Commit

Permalink
Merge pull request #32 from geo-engine/ocl
Browse files Browse the repository at this point in the history
first version of OpenCL support for operations on rasters (and soon f…
  • Loading branch information
ChristianBeilschmidt authored Oct 12, 2020
2 parents db977d1 + 3fe3ae0 commit 0d336c9
Show file tree
Hide file tree
Showing 22 changed files with 3,473 additions and 48 deletions.
446 changes: 446 additions & 0 deletions datatypes/src/collections/batch_builder.rs

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions datatypes/src/collections/data_types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::collections::{
DataCollection, MultiLineStringCollection, MultiPointCollection, MultiPolygonCollection,
};
use serde::{Deserialize, Serialize};

/// An enum that contains all possible vector data types
Expand All @@ -9,3 +12,50 @@ pub enum VectorDataType {
MultiLineString,
MultiPolygon,
}

#[derive(Debug)]
pub enum TypedFeatureCollection {
Data(DataCollection),
MultiPoint(MultiPointCollection),
MultiLineString(MultiLineStringCollection),
MultiPolygon(MultiPolygonCollection),
}

impl TypedFeatureCollection {
pub fn vector_data_type(&self) -> VectorDataType {
match self {
TypedFeatureCollection::Data(_) => VectorDataType::Data,
TypedFeatureCollection::MultiPoint(_) => VectorDataType::MultiPoint,
TypedFeatureCollection::MultiLineString(_) => VectorDataType::MultiLineString,
TypedFeatureCollection::MultiPolygon(_) => VectorDataType::MultiPolygon,
}
}

pub fn get_points(self) -> Option<MultiPointCollection> {
if let TypedFeatureCollection::MultiPoint(points) = self {
return Some(points);
}
None
}

pub fn get_lines(self) -> Option<MultiLineStringCollection> {
if let TypedFeatureCollection::MultiLineString(lines) = self {
return Some(lines);
}
None
}

pub fn get_polygons(self) -> Option<MultiPolygonCollection> {
if let TypedFeatureCollection::MultiPolygon(polygons) = self {
return Some(polygons);
}
None
}

pub fn get_data(self) -> Option<DataCollection> {
if let TypedFeatureCollection::Data(data) = self {
return Some(data);
}
None
}
}
5 changes: 5 additions & 0 deletions datatypes/src/collections/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ pub enum FeatureCollectionError {
},

WrongDataType,

MissingColumnArray,

MissingTime,
MissingGeo,
}

impl From<FeatureCollectionError> for Error {
Expand Down
20 changes: 19 additions & 1 deletion datatypes/src/collections/feature_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,24 @@ where

table_size + map_size
}

/// Return the names of the columns of this type
pub fn column_names_of_type(&self, column_type: FeatureDataType) -> Vec<String> {
self.types
.iter()
.filter_map(|(k, v)| {
if v == &column_type {
Some(k.clone())
} else {
None
}
})
.collect()
}

pub fn column_types(&self) -> HashMap<String, FeatureDataType> {
self.types.clone()
}
}

impl<CollectionType> Clone for FeatureCollection<CollectionType> {
Expand Down Expand Up @@ -905,7 +923,7 @@ where
}

/// Create an `arrow` struct from column meta data and data
fn struct_array_from_data(
pub fn struct_array_from_data(
columns: Vec<Field>,
column_values: Vec<ArrayRef>,
number_of_features: usize,
Expand Down
14 changes: 14 additions & 0 deletions datatypes/src/collections/feature_collection_builder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::collections::batch_builder::RawFeatureCollectionBuilder;
use crate::collections::{error, FeatureCollection, FeatureCollectionError};
use crate::primitives::{FeatureDataType, FeatureDataValue, Geometry, TimeInterval};
use crate::util::arrow::{downcast_mut_array, ArrowTyped};
Expand Down Expand Up @@ -97,6 +98,19 @@ where
_collection_type: PhantomData,
}
}

pub fn batch_builder(
self,
num_features: usize,
num_coords: usize,
) -> RawFeatureCollectionBuilder {
RawFeatureCollectionBuilder::new(
CollectionType::DATA_TYPE,
self.types,
num_features,
num_coords,
)
}
}

/// A default implementation of a feature collection row builder
Expand Down
24 changes: 24 additions & 0 deletions datatypes/src/collections/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod feature_collection;
mod geo_feature_collection;
#[macro_use]
mod data_types;
mod batch_builder;
mod feature_collection_builder;

mod data_collection;
Expand All @@ -24,3 +25,26 @@ pub use data_types::VectorDataType;
pub use multi_line_string_collection::MultiLineStringCollection;
pub use multi_point_collection::MultiPointCollection;
pub use multi_polygon_collection::MultiPolygonCollection;

pub use batch_builder::RawFeatureCollectionBuilder;
pub use data_types::TypedFeatureCollection;

/// Calls a function on a `TypedFeatureCollection` by calling it on its variant.
/// Call via `call_generic_features!(input, features => function)`.
#[macro_export]
macro_rules! call_generic_features {
($input_features:expr, $features:ident => $function_call:expr) => {
call_generic_features!(
@variants $input_features, $features => $function_call,
Data, MultiPoint, MultiLineString, MultiPolygon
)
};

(@variants $input_features:expr, $features:ident => $function_call:expr, $($variant:tt),+) => {
match $input_features {
$(
$crate::collections::TypedFeatureCollection::$variant($features) => $function_call,
)+
}
};
}
82 changes: 82 additions & 0 deletions datatypes/src/collections/multi_point_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,45 @@ impl GeoFeatureCollectionRowBuilder<MultiPoint> for FeatureCollectionRowBuilder<
}
}

impl MultiPointCollection {
pub fn coordinates(&self) -> &[Coordinate2D] {
let geometries_ref = self
.table
.column_by_name(Self::GEOMETRY_COLUMN_NAME)
.expect("There must exist a geometry column");
let geometries: &ListArray = downcast_array(geometries_ref);

let coordinates_ref = geometries.values();
let coordinates: &FixedSizeListArray = downcast_array(&coordinates_ref);

let number_of_coordinates = coordinates.data().len();

let floats_ref = coordinates.values();
let floats: &Float64Array = downcast_array(&floats_ref);

unsafe {
slice::from_raw_parts(
floats.raw_values() as *const Coordinate2D,
number_of_coordinates,
)
}
}

#[allow(clippy::cast_ptr_alignment)]
pub fn multipoint_offsets(&self) -> &[i32] {
let geometries_ref = self
.table
.column_by_name(Self::GEOMETRY_COLUMN_NAME)
.expect("There must exist a geometry column");
let geometries: &ListArray = downcast_array(geometries_ref);

let data = geometries.data();
let buffer = &data.buffers()[0];

unsafe { slice::from_raw_parts(buffer.raw_data() as *const i32, geometries.len() + 1) }
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -864,4 +903,47 @@ mod tests {

assert_eq!(collection, deserialized);
}

#[test]
fn coordinates() {
let pc = MultiPointCollection::from_data(
MultiPoint::many(vec![
vec![(0., 0.)],
vec![(1., 1.), (1.1, 1.1)],
vec![(2., 2.)],
])
.unwrap(),
vec![
TimeInterval::new_unchecked(0, 1),
TimeInterval::new_unchecked(1, 2),
TimeInterval::new_unchecked(2, 3),
],
{
let mut map = HashMap::new();
map.insert("numbers".into(), FeatureData::Number(vec![0., 1., 2.]));
map.insert(
"number_nulls".into(),
FeatureData::NullableNumber(vec![Some(0.), None, Some(2.)]),
);
map
},
)
.unwrap();

let coords = pc.coordinates();
assert_eq!(coords.len(), 4);
assert_eq!(
coords,
&[
[0., 0.].into(),
[1., 1.].into(),
[1.1, 1.1].into(),
[2., 2.].into(),
]
);

let offsets = pc.multipoint_offsets();
assert_eq!(offsets.len(), 4);
assert_eq!(offsets, &[0, 1, 3, 4]);
}
}
2 changes: 2 additions & 0 deletions datatypes/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ pub enum Error {
ParseU32 {
source: <u32 as std::str::FromStr>::Err,
},
InvalidTypedRasterConversion,
InvalidTypedValueConversion,
}

impl From<arrow::error::ArrowError> for Error {
Expand Down
6 changes: 5 additions & 1 deletion datatypes/src/primitives/coordinate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ use crate::util::arrow::ArrowTyped;
use arrow::array::{BooleanArray, Float64Builder};
use arrow::datatypes::DataType;
use arrow::error::ArrowError;
use ocl::OclPrm;
use serde::{Deserialize, Serialize};
use std::{fmt, slice};

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize, Default)]
#[repr(C)]
pub struct Coordinate2D {
pub x: f64,
pub y: f64,
}

// Make coordinates transferable to OpenCl devices
unsafe impl OclPrm for Coordinate2D {}

impl Coordinate2D {
/// Creates a new coordinate
///
Expand Down
Loading

0 comments on commit 0d336c9

Please sign in to comment.