use crate::error::{BenchError, Result};
use crate::scenarios::BenchmarkScenario;
use std::path::PathBuf;
pub struct GeoJsonReadScenario {
input_path: PathBuf,
feature_count: Option<usize>,
}
impl GeoJsonReadScenario {
pub fn new<P: Into<PathBuf>>(input_path: P) -> Self {
Self {
input_path: input_path.into(),
feature_count: None,
}
}
pub fn with_feature_count(mut self, count: usize) -> Self {
self.feature_count = Some(count);
self
}
}
impl BenchmarkScenario for GeoJsonReadScenario {
fn name(&self) -> &str {
"geojson_read"
}
fn description(&self) -> &str {
"Benchmark GeoJSON file reading performance"
}
fn setup(&mut self) -> Result<()> {
if !self.input_path.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!("Input file does not exist: {}", self.input_path.display()),
));
}
Ok(())
}
fn execute(&mut self) -> Result<()> {
#[cfg(feature = "vector")]
{
}
#[cfg(not(feature = "vector"))]
{
return Err(BenchError::missing_dependency("oxigdal-geojson", "vector"));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
Ok(())
}
}
pub struct GeoJsonWriteScenario {
output_path: PathBuf,
#[allow(dead_code)]
feature_count: usize,
geometry_complexity: usize,
created: bool,
}
impl GeoJsonWriteScenario {
pub fn new<P: Into<PathBuf>>(output_path: P, feature_count: usize) -> Self {
Self {
output_path: output_path.into(),
feature_count,
geometry_complexity: 10,
created: false,
}
}
pub fn with_complexity(mut self, complexity: usize) -> Self {
self.geometry_complexity = complexity;
self
}
}
impl BenchmarkScenario for GeoJsonWriteScenario {
fn name(&self) -> &str {
"geojson_write"
}
fn description(&self) -> &str {
"Benchmark GeoJSON file writing performance"
}
fn setup(&mut self) -> Result<()> {
if let Some(parent) = self.output_path.parent() {
std::fs::create_dir_all(parent)?;
}
Ok(())
}
fn execute(&mut self) -> Result<()> {
#[cfg(feature = "vector")]
{
self.created = true;
}
#[cfg(not(feature = "vector"))]
{
return Err(BenchError::missing_dependency("oxigdal-geojson", "vector"));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
if self.created && self.output_path.exists() {
std::fs::remove_file(&self.output_path)?;
}
Ok(())
}
}
pub struct SimplificationScenario {
input_path: PathBuf,
#[allow(dead_code)]
tolerance: f64,
algorithm: SimplificationAlgorithm,
}
#[derive(Debug, Clone, Copy)]
pub enum SimplificationAlgorithm {
DouglasPeucker,
VisvalingamWhyatt,
TopologyPreserving,
}
impl SimplificationScenario {
pub fn new<P: Into<PathBuf>>(input_path: P, tolerance: f64) -> Self {
Self {
input_path: input_path.into(),
tolerance,
algorithm: SimplificationAlgorithm::DouglasPeucker,
}
}
pub fn with_algorithm(mut self, algorithm: SimplificationAlgorithm) -> Self {
self.algorithm = algorithm;
self
}
}
impl BenchmarkScenario for SimplificationScenario {
fn name(&self) -> &str {
"geometry_simplification"
}
fn description(&self) -> &str {
"Benchmark geometry simplification algorithms"
}
fn setup(&mut self) -> Result<()> {
if !self.input_path.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!("Input file does not exist: {}", self.input_path.display()),
));
}
Ok(())
}
#[allow(unreachable_code)]
fn execute(&mut self) -> Result<()> {
#[cfg(all(feature = "vector", feature = "algorithms"))]
{
}
#[cfg(not(all(feature = "vector", feature = "algorithms")))]
{
return Err(BenchError::missing_dependency(
"oxigdal simplification",
"vector and algorithms",
));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
Ok(())
}
}
pub struct BufferScenario {
input_path: PathBuf,
#[allow(dead_code)]
buffer_distance: f64,
resolution: usize,
}
impl BufferScenario {
pub fn new<P: Into<PathBuf>>(input_path: P, buffer_distance: f64) -> Self {
Self {
input_path: input_path.into(),
buffer_distance,
resolution: 16,
}
}
pub fn with_resolution(mut self, resolution: usize) -> Self {
self.resolution = resolution;
self
}
}
impl BenchmarkScenario for BufferScenario {
fn name(&self) -> &str {
"geometry_buffer"
}
fn description(&self) -> &str {
"Benchmark geometry buffer operations"
}
fn setup(&mut self) -> Result<()> {
if !self.input_path.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!("Input file does not exist: {}", self.input_path.display()),
));
}
Ok(())
}
#[allow(unreachable_code)]
fn execute(&mut self) -> Result<()> {
#[cfg(all(feature = "vector", feature = "algorithms"))]
{
}
#[cfg(not(all(feature = "vector", feature = "algorithms")))]
{
return Err(BenchError::missing_dependency(
"oxigdal buffer",
"vector and algorithms",
));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
Ok(())
}
}
pub struct SpatialIndexScenario {
input_path: PathBuf,
index_type: SpatialIndexType,
query_count: usize,
}
#[derive(Debug, Clone, Copy)]
pub enum SpatialIndexType {
RTree,
Quadtree,
KdTree,
}
impl SpatialIndexScenario {
pub fn new<P: Into<PathBuf>>(input_path: P) -> Self {
Self {
input_path: input_path.into(),
index_type: SpatialIndexType::RTree,
query_count: 1000,
}
}
pub fn with_index_type(mut self, index_type: SpatialIndexType) -> Self {
self.index_type = index_type;
self
}
pub fn with_query_count(mut self, count: usize) -> Self {
self.query_count = count;
self
}
}
impl BenchmarkScenario for SpatialIndexScenario {
fn name(&self) -> &str {
"spatial_indexing"
}
fn description(&self) -> &str {
"Benchmark spatial index construction and query performance"
}
fn setup(&mut self) -> Result<()> {
if !self.input_path.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!("Input file does not exist: {}", self.input_path.display()),
));
}
Ok(())
}
#[allow(unreachable_code)]
fn execute(&mut self) -> Result<()> {
#[cfg(all(feature = "vector", feature = "algorithms"))]
{
}
#[cfg(not(all(feature = "vector", feature = "algorithms")))]
{
return Err(BenchError::missing_dependency(
"oxigdal spatial indexing",
"vector and algorithms",
));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
Ok(())
}
}
pub struct IntersectionScenario {
input_path1: PathBuf,
input_path2: PathBuf,
}
impl IntersectionScenario {
pub fn new<P1, P2>(input_path1: P1, input_path2: P2) -> Self
where
P1: Into<PathBuf>,
P2: Into<PathBuf>,
{
Self {
input_path1: input_path1.into(),
input_path2: input_path2.into(),
}
}
}
impl BenchmarkScenario for IntersectionScenario {
fn name(&self) -> &str {
"geometry_intersection"
}
fn description(&self) -> &str {
"Benchmark geometry intersection operations"
}
fn setup(&mut self) -> Result<()> {
if !self.input_path1.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!(
"Input file 1 does not exist: {}",
self.input_path1.display()
),
));
}
if !self.input_path2.exists() {
return Err(BenchError::scenario_failed(
self.name(),
format!(
"Input file 2 does not exist: {}",
self.input_path2.display()
),
));
}
Ok(())
}
#[allow(unreachable_code)]
fn execute(&mut self) -> Result<()> {
#[cfg(all(feature = "vector", feature = "algorithms"))]
{
}
#[cfg(not(all(feature = "vector", feature = "algorithms")))]
{
return Err(BenchError::missing_dependency(
"oxigdal intersection",
"vector and algorithms",
));
}
Ok(())
}
fn teardown(&mut self) -> Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_geojson_read_scenario_creation() {
let scenario = GeoJsonReadScenario::new(std::env::temp_dir().join("test.geojson"))
.with_feature_count(100);
assert_eq!(scenario.name(), "geojson_read");
assert_eq!(scenario.feature_count, Some(100));
}
#[test]
fn test_simplification_scenario_creation() {
let scenario =
SimplificationScenario::new(std::env::temp_dir().join("test.geojson"), 0.001)
.with_algorithm(SimplificationAlgorithm::VisvalingamWhyatt);
assert_eq!(scenario.name(), "geometry_simplification");
assert_eq!(scenario.tolerance, 0.001);
}
#[test]
fn test_buffer_scenario_creation() {
let scenario = BufferScenario::new(std::env::temp_dir().join("test.geojson"), 10.0)
.with_resolution(32);
assert_eq!(scenario.name(), "geometry_buffer");
assert_eq!(scenario.resolution, 32);
}
#[test]
fn test_spatial_index_scenario_creation() {
let scenario = SpatialIndexScenario::new(std::env::temp_dir().join("test.geojson"))
.with_index_type(SpatialIndexType::Quadtree)
.with_query_count(500);
assert_eq!(scenario.name(), "spatial_indexing");
assert_eq!(scenario.query_count, 500);
}
}