Quick Start
This guide will get you up and running with spatial-narrative in under 5 minutes.
Create Your First Narrative
Step 1: Create Events
Events are the fundamental building blocks. Each event has a location, timestamp, and text description:
use spatial_narrative::core::{Event, Location, Timestamp};
// Create locations
let nyc = Location::new(40.7128, -74.0060);
let boston = Location::new(42.3601, -71.0589);
// Create timestamps
let morning = Timestamp::parse("2024-06-15T09:00:00Z").unwrap();
let afternoon = Timestamp::parse("2024-06-15T14:00:00Z").unwrap();
// Create events
let event1 = Event::new(nyc, morning, "Departure from New York City");
let event2 = Event::new(boston, afternoon, "Arrival in Boston");
println!("Event 1: {} at {}", event1.text, event1.timestamp.to_rfc3339());
println!("Event 2: {} at {}", event2.text, event2.timestamp.to_rfc3339());
Step 2: Build a Narrative
A Narrative collects events into a coherent story:
use spatial_narrative::core::{Event, Location, Timestamp, NarrativeBuilder};
let events = vec![
Event::new(
Location::new(40.7128, -74.0060),
Timestamp::parse("2024-06-15T09:00:00Z").unwrap(),
"Departure from NYC"
),
Event::new(
Location::new(42.3601, -71.0589),
Timestamp::parse("2024-06-15T14:00:00Z").unwrap(),
"Arrival in Boston"
),
];
let narrative = NarrativeBuilder::new()
.title("Road Trip to Boston")
.description("A day trip from NYC to Boston")
.tag("travel")
.tag("road-trip")
.events(events)
.build();
println!("Narrative: {}", narrative.title.as_deref().unwrap_or("Untitled"));
println!("Events: {}", narrative.events.len());
Step 3: Query Events
Filter events spatially and temporally:
use spatial_narrative::core::{GeoBounds, TimeRange, Timestamp};
// Get events in chronological order
let ordered = narrative.events_chronological();
for event in &ordered {
println!("{}: {}", event.timestamp.to_rfc3339(), event.text);
}
// Get time range
if let Some(range) = narrative.time_range() {
println!("Duration: {} hours", range.duration().num_hours());
}
// Get geographic bounds
if let Some(bounds) = narrative.bounds() {
println!("Area: ({:.2}, {:.2}) to ({:.2}, {:.2})",
bounds.min_lat, bounds.min_lon,
bounds.max_lat, bounds.max_lon
);
}
Step 4: Index for Fast Queries
For large datasets, use indexes:
use spatial_narrative::index::SpatiotemporalIndex;
use spatial_narrative::core::{GeoBounds, TimeRange, Timestamp};
// Create an index
let mut index = SpatiotemporalIndex::new();
// Insert events
for event in &narrative.events {
index.insert(event.clone(), &event.location, &event.timestamp);
}
// Query by location and time
let bounds = GeoBounds::new(40.0, -75.0, 43.0, -70.0);
let time_range = TimeRange::new(
Timestamp::parse("2024-06-15T00:00:00Z").unwrap(),
Timestamp::parse("2024-06-15T23:59:59Z").unwrap(),
);
let results = index.query(&bounds, &time_range);
println!("Found {} events in region during time range", results.len());
Step 5: Build a Graph
Connect events into a relationship graph:
use spatial_narrative::graph::{NarrativeGraph, EdgeType};
// Create graph from events
let mut graph = NarrativeGraph::from_events(narrative.events.clone());
// Auto-connect by temporal sequence
graph.connect_temporal();
// Connect spatially close events (within 50km)
graph.connect_spatial(50.0);
println!("Graph: {} nodes, {} edges", graph.node_count(), graph.edge_count());
// Export to DOT format for visualization
let dot = graph.to_dot();
println!("DOT output:\n{}", dot);
Step 6: Export to GeoJSON
Export for use in mapping tools:
use spatial_narrative::io::{Format, GeoJsonFormat};
let geojson_format = GeoJsonFormat::default();
let geojson_string = geojson_format.export(&narrative.events).unwrap();
// Save to file
std::fs::write("narrative.geojson", &geojson_string).unwrap();
println!("Exported to narrative.geojson");
Complete Example
Here's everything together:
use spatial_narrative::core::{Event, Location, Timestamp, NarrativeBuilder};
use spatial_narrative::index::SpatiotemporalIndex;
use spatial_narrative::graph::{NarrativeGraph, EdgeType};
use spatial_narrative::io::{Format, GeoJsonFormat};
fn main() {
// Create events
let events = vec![
Event::new(
Location::builder().lat(40.7128).lon(-74.0060).name("NYC").build().unwrap(),
Timestamp::parse("2024-06-15T09:00:00Z").unwrap(),
"Departure from New York City"
),
Event::new(
Location::builder().lat(41.2033).lon(-73.1975).name("New Haven").build().unwrap(),
Timestamp::parse("2024-06-15T11:00:00Z").unwrap(),
"Quick stop in New Haven"
),
Event::new(
Location::builder().lat(42.3601).lon(-71.0589).name("Boston").build().unwrap(),
Timestamp::parse("2024-06-15T14:00:00Z").unwrap(),
"Arrival in Boston"
),
];
// Build narrative
let narrative = NarrativeBuilder::new()
.title("Road Trip to Boston")
.events(events)
.build();
// Index events
let mut index = SpatiotemporalIndex::new();
for event in &narrative.events {
index.insert(event.clone(), &event.location, &event.timestamp);
}
// Build graph
let mut graph = NarrativeGraph::from_events(narrative.events.clone());
graph.connect_temporal();
// Export
let geojson = GeoJsonFormat::default().export(&narrative.events).unwrap();
println!("Created narrative with {} events", narrative.events.len());
println!("Graph has {} connections", graph.edge_count());
println!("GeoJSON: {} bytes", geojson.len());
}
Next Steps
- Concepts - Understand the architecture
- Core Types - Deep dive into types
- Cookbook - Common patterns and recipes