use crate::data_structure::{Entity, Layer, Block, ObjectId, BlockReference};
use crate::geometry::Point;
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Document {
id: ObjectId,
name: String,
version: String,
units: Units,
entities: HashMap<ObjectId, Entity>,
layers: HashMap<ObjectId, Layer>,
blocks: HashMap<ObjectId, Block>,
block_references: HashMap<ObjectId, BlockReference>,
model_space: ObjectId,
paper_space: ObjectId,
active_space: SpaceType,
properties: HashMap<String, String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Units {
Millimeters,
Centimeters,
Meters,
Kilometers,
Inches,
Feet,
Miles,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SpaceType {
ModelSpace,
PaperSpace,
}
impl Document {
#[inline]
pub fn new(name: String) -> Self {
let model_space_id = ObjectId::new();
let paper_space_id = ObjectId::new();
let model_space_layer_id = model_space_id.clone();
let paper_space_layer_id = paper_space_id.clone();
let mut doc = Self {
id: ObjectId::new(),
name,
version: "1.0".to_string(),
units: Units::Millimeters,
entities: HashMap::new(),
layers: HashMap::new(),
blocks: HashMap::new(),
block_references: HashMap::new(),
model_space: model_space_id,
paper_space: paper_space_id,
active_space: SpaceType::ModelSpace,
properties: HashMap::new(),
};
let mut model_space_layer = Layer::new("ModelSpace".to_string());
model_space_layer.set_description("Default model space layer".to_string());
doc.layers.insert(model_space_layer_id, model_space_layer);
let mut paper_space_layer = Layer::new("PaperSpace".to_string());
paper_space_layer.set_description("Default paper space layer".to_string());
doc.layers.insert(paper_space_layer_id, paper_space_layer);
doc
}
#[inline]
pub fn id(&self) -> &ObjectId {
&self.id
}
#[inline]
pub fn name(&self) -> &str {
&self.name
}
#[inline]
pub fn set_name(&mut self, name: String) {
self.name = name;
}
#[inline]
pub fn version(&self) -> &str {
&self.version
}
#[inline]
pub fn units(&self) -> Units {
self.units
}
#[inline]
pub fn set_units(&mut self, units: Units) {
self.units = units;
}
#[inline]
pub fn entities(&self) -> &HashMap<ObjectId, Entity> {
&self.entities
}
#[inline]
pub fn entities_mut(&mut self) -> &mut HashMap<ObjectId, Entity> {
&mut self.entities
}
#[inline]
pub fn add_entity(&mut self, entity: Entity) -> ObjectId {
let id = entity.id().clone();
self.entities.insert(id.clone(), entity);
id
}
#[inline]
pub fn remove_entity(&mut self, entity_id: &ObjectId) -> bool {
self.entities.remove(entity_id).is_some()
}
#[inline]
pub fn get_entity(&self, entity_id: &ObjectId) -> Option<&Entity> {
self.entities.get(entity_id)
}
#[inline]
pub fn get_entity_mut(&mut self, entity_id: &ObjectId) -> Option<&mut Entity> {
self.entities.get_mut(entity_id)
}
#[inline]
pub fn entity_exists(&self, entity_id: &ObjectId) -> bool {
self.entities.contains_key(entity_id)
}
#[inline]
pub fn entity_count(&self) -> usize {
self.entities.len()
}
#[inline]
pub fn layers(&self) -> &HashMap<ObjectId, Layer> {
&self.layers
}
#[inline]
pub fn layers_mut(&mut self) -> &mut HashMap<ObjectId, Layer> {
&mut self.layers
}
#[inline]
pub fn add_layer(&mut self, layer: Layer) -> ObjectId {
let id = layer.id().clone();
self.layers.insert(id.clone(), layer);
id
}
#[inline]
pub fn remove_layer(&mut self, layer_id: &ObjectId) -> bool {
self.layers.remove(layer_id).is_some()
}
#[inline]
pub fn get_layer(&self, layer_id: &ObjectId) -> Option<&Layer> {
self.layers.get(layer_id)
}
#[inline]
pub fn layer_count(&self) -> usize {
self.layers.len()
}
#[inline]
pub fn blocks(&self) -> &HashMap<ObjectId, Block> {
&self.blocks
}
#[inline]
pub fn add_block(&mut self, block: Block) -> ObjectId {
let id = block.id().clone();
self.blocks.insert(id.clone(), block);
id
}
#[inline]
pub fn get_block(&self, block_id: &ObjectId) -> Option<&Block> {
self.blocks.get(block_id)
}
#[inline]
pub fn block_count(&self) -> usize {
self.blocks.len()
}
#[inline]
pub fn block_references(&self) -> &HashMap<ObjectId, BlockReference> {
&self.block_references
}
#[inline]
pub fn add_block_reference(&mut self, block_ref: BlockReference) -> ObjectId {
let id = block_ref.id().clone();
self.block_references.insert(id.clone(), block_ref);
id
}
#[inline]
pub fn get_block_reference(&self, block_ref_id: &ObjectId) -> Option<&BlockReference> {
self.block_references.get(block_ref_id)
}
#[inline]
pub fn block_reference_count(&self) -> usize {
self.block_references.len()
}
#[inline]
pub fn model_space(&self) -> &ObjectId {
&self.model_space
}
#[inline]
pub fn paper_space(&self) -> &ObjectId {
&self.paper_space
}
#[inline]
pub fn active_space(&self) -> SpaceType {
self.active_space
}
#[inline]
pub fn set_active_space(&mut self, space: SpaceType) {
self.active_space = space;
}
#[inline]
pub fn properties(&self) -> &HashMap<String, String> {
&self.properties
}
#[inline]
pub fn set_property(&mut self, key: String, value: String) {
self.properties.insert(key, value);
}
#[inline]
pub fn bounding_box(&self) -> Option<(Point, Point)> {
if self.entities.is_empty() {
return None;
}
let mut min_x = f64::MAX;
let mut max_x = f64::MIN;
let mut min_y = f64::MAX;
let mut max_y = f64::MIN;
for entity in self.entities.values() {
if let Some((min, max)) = entity.bounding_box() {
min_x = min_x.min(min.x);
max_x = max_x.max(max.x);
min_y = min_y.min(min.y);
max_y = max_y.max(max.y);
}
}
Some((
Point::new(min_x, min_y, 0.0),
Point::new(max_x, max_y, 0.0),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::data_structure::{EntityType, EntityGeometry};
#[test]
fn test_document_creation() {
let doc = Document::new("TestDrawing".to_string());
assert_eq!(doc.name(), "TestDrawing");
assert_eq!(doc.entity_count(), 0);
assert!(doc.layer_count() > 0);
}
#[test]
fn test_document_add_entity() {
let mut doc = Document::new("TestDrawing".to_string());
let entity = Entity::new(
EntityType::Point,
EntityGeometry::Point(Point::origin()),
);
let entity_id = doc.add_entity(entity);
assert_eq!(doc.entity_count(), 1);
assert!(doc.get_entity(&entity_id).is_some());
}
#[test]
fn test_document_add_layer() {
let mut doc = Document::new("TestDrawing".to_string());
let layer = Layer::new("MyLayer".to_string());
let layer_id = doc.add_layer(layer);
assert_eq!(doc.layer_count(), 3);
assert!(doc.get_layer(&layer_id).is_some());
}
}