Adapting to new Index return type

This commit is contained in:
2019-10-29 10:46:11 +01:00
parent 8699c066e5
commit b112fcfab6
6 changed files with 151 additions and 80 deletions

View File

@@ -2,6 +2,7 @@ use super::space::Position;
use super::space::Shape;
use super::space::Space;
use super::space_db::SpaceDB;
use super::space_index::SpaceFields;
use super::space_index::SpaceSetObject;
use super::DataBase;
use super::ResultSet;
@@ -157,14 +158,18 @@ impl Core {
&self.properties
}
fn to_space_object(&self, space_id: &str, list: Vec<SpaceSetObject>) -> Vec<SpaceObject> {
fn to_space_object(
&self,
space_id: &str,
list: Vec<(Position, SpaceFields)>,
) -> Vec<SpaceObject> {
list.into_iter()
.map(|o| {
let offset: usize = o.value().into();
.map(|(position, fields)| {
let offset: usize = fields.value().into();
let value = self.properties[offset].clone();
SpaceObject {
space_id: space_id.to_string(),
position: o.position().clone(),
position: position.clone(),
value,
}
})
@@ -172,7 +177,7 @@ impl Core {
}
fn decode_positions(
list: &mut [SpaceObject],
list: &mut [(Position, &Properties)],
space: &Space,
db: &DataBase,
output_space: &Option<&str>,
@@ -181,18 +186,17 @@ impl Core {
let unified = db.space(unified_id)?;
// Rebase the point to the requested output space before decoding.
for o in list {
o.position = unified
.decode(&Space::change_base(&o.position, space, unified)?)?
for (position, _) in list {
*position = unified
.decode(&Space::change_base(&position, space, unified)?)?
.into();
o.space_id = unified_id.to_string();
}
} else {
// Decode the positions into f64 values, which are defined in their
// respective reference space.
for o in list {
for (position, _) in list {
// Simply decode
o.position = space.decode(&o.position)?.into();
*position = space.decode(&position)?.into();
}
}
@@ -233,12 +237,14 @@ impl Core {
p.push(to.encode(&position)?);
}
let r = s.get_by_positions(&p, parameters)?;
let mut r = self.to_space_object(s.name(), r);
let mut r = s
.get_by_positions(&p, parameters)?
.into_iter()
.map(|(position, fields)| (position, &self.properties[fields.value().as_usize()]))
.collect::<Vec<_>>();
Self::decode_positions(r.as_mut_slice(), to, db, output_space)?;
Self::decode_positions(&mut r, to, db, output_space)?;
results.append(&mut r);
results.push((s.name(), r));
}
Ok(results)
@@ -271,12 +277,14 @@ impl Core {
// let current_shape = shape.encode(current_space)?;
// println!("current shape Encoded: {:?}", current_shape);
let r = s.get_by_shape(&current_shape, parameters)?;
let mut r = self.to_space_object(s.name(), r);
let mut r = s
.get_by_shape(&current_shape, parameters)?
.into_iter()
.map(|(position, fields)| (position, &self.properties[fields.value().as_usize()]))
.collect::<Vec<_>>();
Self::decode_positions(r.as_mut_slice(), current_space, db, output_space)?;
Self::decode_positions(&mut r, current_space, db, output_space)?;
results.append(&mut r);
results.push((s.name(), r));
}
Ok(results)
@@ -303,13 +311,17 @@ impl Core {
// reference space
for s in &self.space_db {
let current_space = db.space(s.name())?;
let fields = SpaceFields::new(s.name().into(), offset.into());
let r = s.get_by_id(offset, parameters)?;
let mut r = self.to_space_object(s.name(), r);
let mut r = s
.get_by_id(offset, parameters)?
.into_iter()
.map(|position| (position, &self.properties[fields.value().as_usize()]))
.collect::<Vec<_>>();
Self::decode_positions(&mut r, current_space, db, output_space)?;
Self::decode_positions(r.as_mut_slice(), current_space, db, output_space)?;
results.append(&mut r);
results.push((s.name(), r));
}
}
@@ -350,9 +362,9 @@ impl Core {
Ok(v) => {
// Convert the search Volume into Universe.
let mut p = vec![];
for o in v {
for position in v {
if let Ok(position) =
Space::change_base(o.position(), from, Space::universe())
Space::change_base(&position, from, Space::universe())
{
p.push(position)
}
@@ -384,12 +396,17 @@ impl Core {
p.push(position);
}
let r = s.get_by_positions(&p, parameters)?;
let mut r = self.to_space_object(s.name(), r);
let mut r = s
.get_by_positions(&p, parameters)?
.into_iter()
.map(|(position, fields)| {
(position, &self.properties[fields.value().as_usize()])
})
.collect::<Vec<_>>();
Self::decode_positions(&mut r, to, db, output_space)?;
Self::decode_positions(r.as_mut_slice(), to, db, output_space)?;
results.append(&mut r);
results.push((s.name(), r));
}
}

View File

@@ -14,9 +14,11 @@ pub use db_core::CoreQueryParameters;
pub use db_core::Properties;
use space::Position;
use space::Space;
pub use space_index::SpaceFields;
pub use space_index::SpaceSetObject;
pub type ResultSet = Result<Vec<SpaceObject>, String>;
// (Space Name, Position, Fields)
pub type ResultSet<'r> = Result<Vec<(&'r String, Vec<(Position, &'r Properties)>)>, String>;
pub type ReferenceSpaceIndex = ironsea_index_hashmap::Index<Space, String>;
type CoreIndex = ironsea_index_hashmap::Index<Core, String>;

View File

@@ -39,6 +39,10 @@ impl Coordinate {
Coordinate::CoordinateF64(_v) => unreachable!(),
}
}
pub fn as_usize(&self) -> usize {
self.u64() as usize
}
}
/*

View File

@@ -99,7 +99,7 @@ impl SpaceDB {
let shift = if count >= 31 { 31 } else { count };
count += 1;
indices.push((
SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS),
SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS),
vec![power.0, power.0, power.0],
shift,
));
@@ -118,7 +118,7 @@ impl SpaceDB {
// Insert Full resolution index.
indices.push((
SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS),
SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS),
vec![count, count, count],
0, // Smallest value => highest resolution
));
@@ -157,7 +157,7 @@ impl SpaceDB {
}
indices.push((
SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS),
SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS),
vec![count, count, count],
shift,
));
@@ -172,7 +172,7 @@ impl SpaceDB {
} else {
// Generate only full-scale.
indices.push((
SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS),
SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS),
vec![0, 0, 0],
0,
));
@@ -302,12 +302,10 @@ impl SpaceDB {
}
// Convert the value back to caller's references
fn decode_value(&self, mut objects: Vec<SpaceSetObject>) -> Vec<SpaceSetObject> {
for o in &mut objects {
o.set_value(self.values[o.value().u64() as usize]);
fn decode_value(&self, objects: &mut Vec<(Position, SpaceFields)>) {
for (_, fields) in objects.iter_mut() {
fields.set_value(self.values[fields.value().u64() as usize]);
}
objects
}
// Search by Id, a.k.a values
@@ -316,7 +314,7 @@ impl SpaceDB {
&self,
id: usize,
parameters: &CoreQueryParameters,
) -> Result<Vec<SpaceSetObject>, String> {
) -> Result<Vec<(Position)>, String> {
// Is that ID referenced in the current space?
if let Ok(offset) = self.values.binary_search(&id.into()) {
let index = self.resolution(parameters);
@@ -329,20 +327,17 @@ impl SpaceDB {
let objects = self.resolutions[index]
.find_by_value(&SpaceFields::new(self.name().into(), offset.into()));
let mut results = if let Some(view_port) = view_port {
let results = if let Some(view_port) = view_port {
objects
.into_iter()
.filter(|o| view_port.contains(o.position()))
.collect::<Vec<SpaceSetObject>>()
.filter(|position| view_port.contains(position))
.collect::<Vec<_>>()
} else {
objects
};
// Convert the Value back to caller's references
// Here we do not use decode() as we have a single id value to manage.
for o in &mut results {
o.set_value(id.into());
}
Ok(results)
} else {
@@ -356,7 +351,7 @@ impl SpaceDB {
&self,
positions: &[Position],
parameters: &CoreQueryParameters,
) -> Result<Vec<SpaceSetObject>, String> {
) -> Result<Vec<(Position, SpaceFields)>, String> {
let index = self.resolution(parameters);
// FIXME: Should I do it here, or add the assumption this is a clean list?
@@ -365,13 +360,18 @@ impl SpaceDB {
//let view_port = parameters.view_port(space);
// Select the objects
let results = positions
let mut results = positions
.iter()
.flat_map(|position| self.resolutions[index].find(position))
.collect::<Vec<SpaceSetObject>>();
.flat_map(|position| {
self.resolutions[index]
.find(position)
.into_iter()
.map(move |fields| (position.clone(), fields.clone()))
})
.collect();
// Decode the Value reference
let results = self.decode_value(results);
self.decode_value(&mut results);
Ok(results)
}
@@ -386,7 +386,7 @@ impl SpaceDB {
&self,
shape: &Shape,
parameters: &CoreQueryParameters,
) -> Result<Vec<SpaceSetObject>, String> {
) -> Result<Vec<(Position, SpaceFields)>, String> {
let index = self.resolution(parameters);
// Convert the view port to the encoded space coordinates
@@ -394,10 +394,14 @@ impl SpaceDB {
let view_port = parameters.view_port(space);
// Select the objects
let results = self.resolutions[index].find_by_shape(&shape, &view_port)?;
let mut results = self.resolutions[index]
.find_by_shape(&shape, &view_port)?
.into_iter()
.map(|(position, fields)| (position, fields.clone()))
.collect();
// Decode the Value reference
let results = self.decode_value(results);
self.decode_value(&mut results);
Ok(results)
}

View File

@@ -7,7 +7,7 @@ use super::space::Position;
use super::space::Shape;
use super::SpaceId;
#[derive(Clone, Debug, Deserialize, Hash, Serialize)]
#[derive(Clone, Debug, Hash)]
pub struct SpaceSetObject {
space_id: SpaceId,
position: Position,
@@ -58,6 +58,22 @@ impl SpaceFields {
pub fn new(space_id: SpaceId, value: Coordinate) -> Self {
SpaceFields { space_id, value }
}
/*
pub fn id(&self) -> &Coordinate {
&self.value
}
pub fn space_id(&self) -> &SpaceId {
&self.space_id
}
*/
pub fn value(&self) -> &Coordinate {
&self.value
}
pub fn set_value(&mut self, value: Coordinate) {
self.value = value;
}
}
impl PartialEq for SpaceFields {
@@ -66,13 +82,13 @@ impl PartialEq for SpaceFields {
}
}
impl ironsea_index::Record<Position> for SpaceSetObject {
impl ironsea_index::Record<Position> for &SpaceSetObject {
fn key(&self) -> Position {
self.position.clone()
}
}
impl ironsea_index::RecordFields<SpaceFields> for SpaceSetObject {
impl ironsea_index::RecordFields<SpaceFields> for &SpaceSetObject {
fn fields(&self) -> SpaceFields {
SpaceFields {
space_id: self.space_id().clone(),
@@ -109,17 +125,17 @@ impl SpaceIndex {
}
// Inputs and Results are expressed in encoded space coordinates.
pub fn find(&self, key: &Position) -> Vec<SpaceSetObject> {
pub fn find(&self, key: &Position) -> Vec<&SpaceFields> {
self.index.find(key)
}
// Inputs and Results are expressed in encoded space coordinates.
fn find_range(&self, start: &Position, end: &Position) -> Vec<SpaceSetObject> {
fn find_range(&self, start: &Position, end: &Position) -> Vec<(Position, &SpaceFields)> {
self.index.find_range(start, end)
}
// Inputs and Results are expressed in encoded space coordinates.
pub fn find_by_value(&self, id: &SpaceFields) -> Vec<SpaceSetObject> {
pub fn find_by_value(&self, id: &SpaceFields) -> Vec<Position> {
self.index.find_by_value(id)
}
@@ -128,21 +144,22 @@ impl SpaceIndex {
&self,
shape: &Shape,
view_port: &Option<Shape>,
) -> Result<Vec<SpaceSetObject>, String> {
) -> Result<Vec<(Position, &SpaceFields)>, String> {
match shape {
Shape::Point(position) => {
if let Some(mbb) = view_port {
if mbb.contains(position) {
Ok(self.find(position))
} else {
Err(format!(
if !mbb.contains(position) {
return Err(format!(
"View port '{:?}' does not contain '{:?}'",
mbb, position
))
));
}
} else {
Ok(self.find(position))
}
Ok(self
.find(position)
.into_iter()
.map(|fields| (position.clone(), fields))
.collect())
}
Shape::BoundingBox(bl, bh) => {
if let Some(mbb) = view_port {
@@ -198,7 +215,7 @@ impl SpaceIndex {
let results = self
.find_range(&lower, &higher)
.into_iter()
.filter(|p| (p.position() - center).norm() <= radius.f64())
.filter(|(position, _)| (position - center).norm() <= radius.f64())
.collect();
Ok(results)

View File

@@ -45,7 +45,7 @@ fn main() {
};
let r = core.get_by_id(&c, id).unwrap();
println!("get_by_id {}: {}", id, r.len());
println!("{}: {:?}\n", id, r[0]);
println!("{}: {:?}\n", id, r[0].1[0]);
let c = CoreQueryParameters {
db: &db,
@@ -56,7 +56,7 @@ fn main() {
};
let r = core.get_by_id(&c, id).unwrap();
println!("get_by_id {}: {}", id, r.len());
println!("{}: {:?}\n", id, r[0]);
println!("{}: {:?}\n", id, r[0].1[0]);
let c = CoreQueryParameters {
db: &db,
@@ -68,7 +68,7 @@ fn main() {
let r = core.get_by_label(&c, id).unwrap();
println!("get_by_label {}: {}", id, r.len());
if !r.is_empty() {
println!("{}: {:?}\n", id, r[0]);
println!("{}: {:?}\n", id, r[0].1[0]);
}
let lower = space.encode(&[0.2, 0.2, 0.2]).unwrap();
@@ -85,15 +85,41 @@ fn main() {
};
let r = core.get_by_shape(&c, &shape, "std").unwrap();
println!("get_by_shape {:?}: {}", shape, r.len());
println!("{:?}: {:?}\n", shape, r[0]);
println!("{:?}: {:?}\n", shape, r[0].1[0]);
let a = r.iter().filter(|o| o.value.id() == id).collect::<Vec<_>>();
let a = r
.iter()
.filter_map(|(space, v)| {
let v = v
.iter()
.filter(|(_, properties)| properties.id() == id)
.collect::<Vec<_>>();
if v.is_empty() {
None
} else {
Some((space, v))
}
})
.collect::<Vec<_>>();
println!("get_by_shape A {:?} filtered on {}: {}", shape, id, a.len());
if !a.is_empty() {
println!("{:?}\n", a[0]);
println!("{:?}\n", a[0].1[0]);
}
let a = r.iter().filter(|o| o.value.id() != id).collect::<Vec<_>>();
let a = r
.iter()
.filter_map(|(space, v)| {
let v = v
.iter()
.filter(|(_, properties)| properties.id() != id)
.collect::<Vec<_>>();
if v.is_empty() {
None
} else {
Some((space, v))
}
})
.collect::<Vec<_>>();
println!(
"get_by_shape !A {:?} filtered on {}: {}",
shape,
@@ -101,16 +127,17 @@ fn main() {
a.len()
);
if !a.is_empty() {
println!("{:?}\n", a[0]);
println!("{:?}\n", a[0].1[0]);
}
println!(
"\nSPACE OBJECT:\n\n{}",
serde_json::to_string_pretty(space).unwrap()
);
//FIXME: Not returning SpatialObjects by default
println!(
"\nSPATIAL OBJECT:\n\n{}",
serde_json::to_string_pretty(a[0]).unwrap()
serde_json::to_string_pretty(&a[0]).unwrap()
);
}
}