From 3a812d5621d7c419f354b279795addd57a2a0ec9 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Tue, 26 Mar 2024 20:24:15 +0000 Subject: [PATCH] geometry: implement incomplete interface for manipulation of groupings --- src/bin/topola-egui/app.rs | 4 +- src/bin/topola-sdl2-demo/main.rs | 8 +- src/drawing/bend.rs | 36 ++++---- src/drawing/collect.rs | 10 +-- src/drawing/dot.rs | 36 ++++---- src/drawing/drawing.rs | 113 +++++++++++++++---------- src/drawing/graph.rs | 16 ++-- src/drawing/grouping.rs | 2 +- src/drawing/guide.rs | 4 +- src/drawing/loose.rs | 12 +-- src/drawing/primitive.rs | 24 +++--- src/drawing/seg.rs | 46 +++++------ src/drawing/segbend.rs | 6 +- src/geometry/geometry.rs | 61 ++++++++------ src/geometry/with_rtree.rs | 138 ++++++++++++++++++++----------- src/mesh.rs | 20 ++--- src/router.rs | 4 +- src/wraparoundable.rs | 10 +-- 18 files changed, 313 insertions(+), 237 deletions(-) diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index d6eefdf..ef48c52 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -139,12 +139,12 @@ impl eframe::App for App { let mut painter = Painter::new(ui, transform); if let Some(layout) = &self.drawing { - for node in layout.layer_nodes(1) { + for node in layout.layer_primitive_nodes(1) { let shape = node.primitive(layout).shape(); painter.paint_shape(&shape, egui::Color32::from_rgb(52, 52, 200)); } - for node in layout.layer_nodes(0) { + for node in layout.layer_primitive_nodes(0) { let shape = node.primitive(layout).shape(); painter.paint_shape(&shape, egui::Color32::from_rgb(200, 52, 52)); } diff --git a/src/bin/topola-sdl2-demo/main.rs b/src/bin/topola-sdl2-demo/main.rs index 50957c2..ff89e5e 100644 --- a/src/bin/topola-sdl2-demo/main.rs +++ b/src/bin/topola-sdl2-demo/main.rs @@ -14,7 +14,7 @@ use painter::Painter; use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use topola::draw::DrawException; use topola::drawing::dot::FixedDotWeight; -use topola::drawing::graph::{GeometryIndex, MakePrimitive}; +use topola::drawing::graph::{MakePrimitive, PrimitiveIndex}; use topola::drawing::primitive::MakeShape; use topola::drawing::rules::{Conditions, RulesTrait}; use topola::drawing::seg::FixedSegWeight; @@ -323,7 +323,7 @@ fn render_times( mut maybe_mesh: Option, path: &[VertexIndex], ghosts: &[Shape], - highlighteds: &[GeometryIndex], + highlighteds: &[PrimitiveIndex], times: i64, ) { let mut i = 0; @@ -394,7 +394,7 @@ fn render_times( }; //let result = panic::catch_unwind(|| { - for node in layout.layer_nodes(1) { + for node in layout.layer_primitive_nodes(1) { let color = if highlighteds.contains(&node) { ColorU::new(100, 100, 255, 255) } else { @@ -405,7 +405,7 @@ fn render_times( painter.paint_shape(&shape, color, view.zoom); } - for node in layout.layer_nodes(0) { + for node in layout.layer_primitive_nodes(0) { let color = if highlighteds.contains(&node) { ColorU::new(255, 100, 100, 255) } else { diff --git a/src/drawing/bend.rs b/src/drawing/bend.rs index 72c57b7..0fd68d3 100644 --- a/src/drawing/bend.rs +++ b/src/drawing/bend.rs @@ -2,7 +2,7 @@ use enum_dispatch::enum_dispatch; use crate::{ drawing::{ - graph::{GeometryIndex, GeometryWeight, GetLayer, GetMaybeNet, MakePrimitive, Retag}, + graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag}, primitive::{GenericPrimitive, Primitive}, rules::RulesTrait, Drawing, @@ -20,22 +20,22 @@ pub enum BendIndex { Loose(LooseBendIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(bend: BendIndex) -> Self { match bend { - BendIndex::Fixed(bend) => GeometryIndex::FixedBend(bend), - BendIndex::Loose(bend) => GeometryIndex::LooseBend(bend), + BendIndex::Fixed(bend) => PrimitiveIndex::FixedBend(bend), + BendIndex::Loose(bend) => PrimitiveIndex::LooseBend(bend), } } } -impl TryFrom for BendIndex { +impl TryFrom for BendIndex { type Error = (); // TODO. - fn try_from(index: GeometryIndex) -> Result { + fn try_from(index: PrimitiveIndex) -> Result { match index { - GeometryIndex::FixedBend(index) => Ok(BendIndex::Fixed(index)), - GeometryIndex::LooseBend(index) => Ok(BendIndex::Loose(index)), + PrimitiveIndex::FixedBend(index) => Ok(BendIndex::Fixed(index)), + PrimitiveIndex::LooseBend(index) => Ok(BendIndex::Loose(index)), _ => Err(()), } } @@ -48,28 +48,28 @@ pub enum BendWeight { Loose(LooseBendWeight), } -impl From for GeometryWeight { +impl From for PrimitiveWeight { fn from(bend: BendWeight) -> Self { match bend { - BendWeight::Fixed(weight) => GeometryWeight::FixedBend(weight), - BendWeight::Loose(weight) => GeometryWeight::LooseBend(weight), + BendWeight::Fixed(weight) => PrimitiveWeight::FixedBend(weight), + BendWeight::Loose(weight) => PrimitiveWeight::LooseBend(weight), } } } -impl TryFrom for BendWeight { +impl TryFrom for BendWeight { type Error = (); // TODO. - fn try_from(weight: GeometryWeight) -> Result { + fn try_from(weight: PrimitiveWeight) -> Result { match weight { - GeometryWeight::FixedBend(weight) => Ok(BendWeight::Fixed(weight)), - GeometryWeight::LooseBend(weight) => Ok(BendWeight::Loose(weight)), + PrimitiveWeight::FixedBend(weight) => Ok(BendWeight::Fixed(weight)), + PrimitiveWeight::LooseBend(weight) => Ok(BendWeight::Loose(weight)), _ => Err(()), } } } -impl BendWeightTrait for BendWeight {} +impl BendWeightTrait for BendWeight {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedBendWeight { @@ -80,7 +80,7 @@ pub struct FixedBendWeight { } impl_fixed_weight!(FixedBendWeight, FixedBend, FixedBendIndex); -impl BendWeightTrait for FixedBendWeight {} +impl BendWeightTrait for FixedBendWeight {} impl GetOffset for FixedBendWeight { fn offset(&self) -> f64 { @@ -127,4 +127,4 @@ impl GetWidth for LooseBendWeight { } impl_loose_weight!(LooseBendWeight, LooseBend, LooseBendIndex); -impl BendWeightTrait for LooseBendWeight {} +impl BendWeightTrait for LooseBendWeight {} diff --git a/src/drawing/collect.rs b/src/drawing/collect.rs index e120888..451031a 100644 --- a/src/drawing/collect.rs +++ b/src/drawing/collect.rs @@ -2,7 +2,7 @@ use crate::wraparoundable::{GetWraparound, WraparoundableIndex}; use super::{ bend::LooseBendIndex, - graph::GeometryIndex, + graph::PrimitiveIndex, primitive::{GetInnerOuter, GetJoints}, rules::RulesTrait, Drawing, @@ -18,8 +18,8 @@ impl<'a, R: RulesTrait> Collect<'a, R> { Self { drawing } } - pub fn bend_bow(&self, bend: LooseBendIndex) -> Vec { - let mut v: Vec = vec![]; + pub fn bend_bow(&self, bend: LooseBendIndex) -> Vec { + let mut v: Vec = vec![]; v.push(bend.into()); let ends = self.drawing.primitive(bend).joints(); @@ -37,7 +37,7 @@ impl<'a, R: RulesTrait> Collect<'a, R> { v } - pub fn bend_outer_bows(&self, bend: LooseBendIndex) -> Vec { + pub fn bend_outer_bows(&self, bend: LooseBendIndex) -> Vec { let mut v = vec![]; let mut rail = bend; @@ -49,7 +49,7 @@ impl<'a, R: RulesTrait> Collect<'a, R> { v } - pub fn wraparounded_bows(&self, around: WraparoundableIndex) -> Vec { + pub fn wraparounded_bows(&self, around: WraparoundableIndex) -> Vec { let mut v = vec![]; let mut rail = around.into(); diff --git a/src/drawing/dot.rs b/src/drawing/dot.rs index 8ecefcf..7b19fb7 100644 --- a/src/drawing/dot.rs +++ b/src/drawing/dot.rs @@ -5,7 +5,7 @@ use petgraph::stable_graph::NodeIndex; use crate::{ drawing::{ - graph::{GeometryIndex, GeometryWeight, GetLayer, GetMaybeNet, MakePrimitive, Retag}, + graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag}, primitive::{GenericPrimitive, Primitive}, rules::RulesTrait, Drawing, @@ -22,22 +22,22 @@ pub enum DotIndex { Loose(LooseDotIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(dot: DotIndex) -> Self { match dot { - DotIndex::Fixed(index) => GeometryIndex::FixedDot(index), - DotIndex::Loose(index) => GeometryIndex::LooseDot(index), + DotIndex::Fixed(index) => PrimitiveIndex::FixedDot(index), + DotIndex::Loose(index) => PrimitiveIndex::LooseDot(index), } } } -impl TryFrom for DotIndex { +impl TryFrom for DotIndex { type Error = (); // TODO. - fn try_from(index: GeometryIndex) -> Result { + fn try_from(index: PrimitiveIndex) -> Result { match index { - GeometryIndex::FixedDot(index) => Ok(DotIndex::Fixed(index)), - GeometryIndex::LooseDot(index) => Ok(DotIndex::Loose(index)), + PrimitiveIndex::FixedDot(index) => Ok(DotIndex::Fixed(index)), + PrimitiveIndex::LooseDot(index) => Ok(DotIndex::Loose(index)), _ => Err(()), } } @@ -50,28 +50,28 @@ pub enum DotWeight { Loose(LooseDotWeight), } -impl From for GeometryWeight { +impl From for PrimitiveWeight { fn from(dot: DotWeight) -> Self { match dot { - DotWeight::Fixed(weight) => GeometryWeight::FixedDot(weight), - DotWeight::Loose(weight) => GeometryWeight::LooseDot(weight), + DotWeight::Fixed(weight) => PrimitiveWeight::FixedDot(weight), + DotWeight::Loose(weight) => PrimitiveWeight::LooseDot(weight), } } } -impl TryFrom for DotWeight { +impl TryFrom for DotWeight { type Error = (); // TODO. - fn try_from(weight: GeometryWeight) -> Result { + fn try_from(weight: PrimitiveWeight) -> Result { match weight { - GeometryWeight::FixedDot(weight) => Ok(DotWeight::Fixed(weight)), - GeometryWeight::LooseDot(weight) => Ok(DotWeight::Loose(weight)), + PrimitiveWeight::FixedDot(weight) => Ok(DotWeight::Fixed(weight)), + PrimitiveWeight::LooseDot(weight) => Ok(DotWeight::Loose(weight)), _ => Err(()), } } } -impl DotWeightTrait for DotWeight {} +impl DotWeightTrait for DotWeight {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedDotWeight { @@ -81,7 +81,7 @@ pub struct FixedDotWeight { } impl_fixed_weight!(FixedDotWeight, FixedDot, FixedDotIndex); -impl DotWeightTrait for FixedDotWeight {} +impl DotWeightTrait for FixedDotWeight {} impl GetPos for FixedDotWeight { fn pos(&self) -> Point { @@ -109,7 +109,7 @@ pub struct LooseDotWeight { } impl_loose_weight!(LooseDotWeight, LooseDot, LooseDotIndex); -impl DotWeightTrait for LooseDotWeight {} +impl DotWeightTrait for LooseDotWeight {} impl GetPos for LooseDotWeight { fn pos(&self) -> Point { diff --git a/src/drawing/drawing.rs b/src/drawing/drawing.rs index b11d1c5..ca65786 100644 --- a/src/drawing/drawing.rs +++ b/src/drawing/drawing.rs @@ -19,7 +19,7 @@ use crate::drawing::rules::GetConditions; use crate::drawing::{ bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, - graph::{GeometryIndex, GeometryWeight, MakePrimitive}, + graph::{MakePrimitive, PrimitiveIndex, PrimitiveWeight}, grouping::{GroupingIndex, GroupingWeight}, primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape}, seg::{ @@ -27,6 +27,7 @@ use crate::drawing::{ SeqLooseSegIndex, SeqLooseSegWeight, }, }; +use crate::geometry::Compound; use crate::geometry::{ shape::{Shape, ShapeTrait}, with_rtree::GeometryWithRtree, @@ -56,29 +57,28 @@ pub enum LayoutException { // TODO add real error messages + these should eventually use Display #[derive(Error, Debug, Clone, Copy)] #[error("{0:?} infringes on {1:?}")] -pub struct Infringement(pub Shape, pub GeometryIndex); +pub struct Infringement(pub Shape, pub PrimitiveIndex); #[derive(Error, Debug, Clone, Copy)] #[error("{0:?} collides with {1:?}")] -pub struct Collision(pub Shape, pub GeometryIndex); +pub struct Collision(pub Shape, pub PrimitiveIndex); #[derive(Error, Debug, Clone, Copy)] #[error("{1:?} is already connected to net {0}")] -pub struct AlreadyConnected(pub usize, pub GeometryIndex); +pub struct AlreadyConnected(pub usize, pub PrimitiveIndex); #[derive(Debug)] pub struct Drawing { geometry_with_rtree: GeometryWithRtree< - GeometryWeight, + PrimitiveWeight, DotWeight, SegWeight, BendWeight, GroupingWeight, - GeometryIndex, + PrimitiveIndex, DotIndex, SegIndex, BendIndex, - GroupingIndex, >, rules: R, } @@ -179,13 +179,13 @@ impl Drawing { #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] - fn add_dot_infringably + GetLayer>( + fn add_dot_infringably + GetLayer>( &mut self, weight: W, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> where - GenericIndex: Into + Copy, + GenericIndex: Into + Copy, { let dot = self.geometry_with_rtree.add_dot(weight); self.fail_and_remove_if_infringes_except(dot.into(), infringables)?; @@ -405,7 +405,7 @@ impl Drawing { seg_weight: SeqLooseSegWeight, bend_weight: LooseBendWeight, cw: bool, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result { let seg_to = self.add_dot_infringably(dot_weight, infringables)?; let seg = self @@ -473,15 +473,15 @@ impl Drawing { #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 2))] #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - fn add_seg_infringably + GetLayer>( + fn add_seg_infringably + GetLayer>( &mut self, from: DotIndex, to: DotIndex, weight: W, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> where - GenericIndex: Into + Copy, + GenericIndex: Into + Copy, { let seg = self.geometry_with_rtree.add_seg(from, to, weight); self.fail_and_remove_if_infringes_except(seg.into(), infringables)?; @@ -500,7 +500,7 @@ impl Drawing { to: LooseDotIndex, around: WraparoundableIndex, weight: LooseBendWeight, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result { // It makes no sense to wrap something around or under one of its connectables. // @@ -537,16 +537,16 @@ impl Drawing { #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3))] #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - fn add_core_bend_infringably + GetLayer>( + fn add_core_bend_infringably + GetLayer>( &mut self, from: DotIndex, to: DotIndex, core: FixedDotIndex, weight: W, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> where - GenericIndex: Into + Copy, + GenericIndex: Into + Copy, { let bend = self .geometry_with_rtree @@ -566,7 +566,7 @@ impl Drawing { to: LooseDotIndex, inner: BendIndex, weight: LooseBendWeight, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> { let core = *self .geometry_with_rtree @@ -616,8 +616,8 @@ impl Drawing { #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 1))] fn fail_and_remove_if_infringes_except( &mut self, - node: GeometryIndex, - maybe_except: Option<&[GeometryIndex]>, + node: PrimitiveIndex, + maybe_except: Option<&[PrimitiveIndex]>, ) -> Result<(), Infringement> { if let Some(infringement) = self.detect_infringement_except(node, maybe_except) { if let Ok(dot) = node.try_into() { @@ -632,21 +632,33 @@ impl Drawing { Ok(()) } - pub fn nodes(&self) -> impl Iterator + '_ { + pub fn primitive_nodes(&self) -> impl Iterator + '_ { self.geometry_with_rtree .rtree() .iter() - .map(|wrapper| wrapper.data) + .filter_map(|wrapper| { + if let Compound::Primitive(primitive_node) = wrapper.data { + Some(primitive_node) + } else { + None + } + }) } - pub fn layer_nodes(&self, layer: u64) -> impl Iterator + '_ { + pub fn layer_primitive_nodes(&self, layer: u64) -> impl Iterator + '_ { self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting(&AABB::from_corners( [-f64::INFINITY, -f64::INFINITY, layer as f64], [f64::INFINITY, f64::INFINITY, layer as f64], )) - .map(|wrapper| wrapper.data) + .filter_map(|wrapper| { + if let Compound::Primitive(primitive_node) = wrapper.data { + Some(primitive_node) + } else { + None + } + }) } pub fn node_count(&self) -> usize { @@ -670,7 +682,7 @@ impl Drawing { &mut self, dot: DotIndex, to: Point, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result<(), Infringement> { let old_pos = self.geometry_with_rtree.geometry().dot_weight(dot).pos(); self.geometry_with_rtree.move_dot(dot, to); @@ -698,7 +710,7 @@ impl Drawing { &mut self, bend: BendIndex, offset: f64, - infringables: Option<&[GeometryIndex]>, + infringables: Option<&[PrimitiveIndex]>, ) -> Result<(), Infringement> { let old_offset = self .geometry_with_rtree @@ -720,8 +732,8 @@ impl Drawing { #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] fn detect_infringement_except( &self, - node: GeometryIndex, - maybe_except: Option<&[GeometryIndex]>, + node: PrimitiveIndex, + maybe_except: Option<&[PrimitiveIndex]>, ) -> Option { let limiting_shape = node.primitive(self).shape().inflate( node.primitive(self) @@ -735,10 +747,19 @@ impl Drawing { self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting(&limiting_shape.full_height_envelope_3d(0.0, 2)) - .filter(|wrapper| maybe_except.is_some_and(|except| !except.contains(&wrapper.data))) - .filter(|wrapper| !self.are_connectable(node, wrapper.data)) - .filter(|wrapper| { - let infringee_conditions = wrapper.data.primitive(self).conditions(); + .filter_map(|wrapper| { + if let Compound::Primitive(primitive_node) = wrapper.data { + Some(primitive_node) + } else { + None + } + }) + .filter(|primitive_node| { + maybe_except.is_some_and(|except| !except.contains(&primitive_node)) + }) + .filter(|primitive_node| !self.are_connectable(node, *primitive_node)) + .filter(|primitive_node| { + let infringee_conditions = primitive_node.primitive(self).conditions(); let epsilon = 1.0; inflated_shape = node.primitive(self).shape().inflate( @@ -746,31 +767,38 @@ impl Drawing { .clamp(0.0, f64::INFINITY), ); - inflated_shape.intersects(&wrapper.data.primitive(self).shape()) + inflated_shape.intersects(&primitive_node.primitive(self).shape()) }) - .map(|wrapper| wrapper.data) + .map(|primitive_node| primitive_node) .next() .and_then(|infringee| Some(Infringement(inflated_shape, infringee))) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - fn detect_collision(&self, node: GeometryIndex) -> Option { + fn detect_collision(&self, node: PrimitiveIndex) -> Option { let shape = node.primitive(self).shape(); self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting(&shape.full_height_envelope_3d(0.0, 2)) - .filter(|wrapper| !self.are_connectable(node, wrapper.data)) - .filter(|wrapper| shape.intersects(&wrapper.data.primitive(self).shape())) - .map(|wrapper| wrapper.data) + .filter_map(|wrapper| { + if let Compound::Primitive(primitive_node) = wrapper.data { + Some(primitive_node) + } else { + None + } + }) + .filter(|primitive_node| !self.are_connectable(node, *primitive_node)) + .filter(|primitive_node| shape.intersects(&primitive_node.primitive(self).shape())) + .map(|primitive_node| primitive_node) .next() .and_then(|collidee| Some(Collision(shape, collidee))) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - fn are_connectable(&self, node1: GeometryIndex, node2: GeometryIndex) -> bool { + fn are_connectable(&self, node1: PrimitiveIndex, node2: PrimitiveIndex) -> bool { if let (Some(node1_net_id), Some(node2_net_id)) = ( node1.primitive(self).maybe_net(), node2.primitive(self).maybe_net(), @@ -788,16 +816,15 @@ impl Drawing { pub fn geometry( &self, ) -> &Geometry< - GeometryWeight, + PrimitiveWeight, DotWeight, SegWeight, BendWeight, GroupingWeight, - GeometryIndex, + PrimitiveIndex, DotIndex, SegIndex, BendIndex, - GroupingIndex, > { self.geometry_with_rtree.geometry() } diff --git a/src/drawing/graph.rs b/src/drawing/graph.rs index 4e5b9b0..589e42e 100644 --- a/src/drawing/graph.rs +++ b/src/drawing/graph.rs @@ -16,8 +16,8 @@ use super::{ }; #[enum_dispatch] -pub trait Retag { - fn retag(&self, index: NodeIndex) -> GeometryIndex; +pub trait Retag { + fn retag(&self, index: NodeIndex) -> PrimitiveIndex; } #[enum_dispatch] @@ -37,9 +37,9 @@ pub trait MakePrimitive { macro_rules! impl_weight { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { - impl Retag for $weight_struct { - fn retag(&self, index: NodeIndex) -> GeometryIndex { - GeometryIndex::$weight_variant($index_struct::new(index)) + impl Retag for $weight_struct { + fn retag(&self, index: NodeIndex) -> PrimitiveIndex { + PrimitiveIndex::$weight_variant($index_struct::new(index)) } } @@ -79,7 +79,7 @@ macro_rules! impl_loose_weight { #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] -pub enum GeometryIndex { +pub enum PrimitiveIndex { FixedDot(FixedDotIndex), LooseDot(LooseDotIndex), FixedSeg(FixedSegIndex), @@ -89,9 +89,9 @@ pub enum GeometryIndex { LooseBend(LooseBendIndex), } -#[enum_dispatch(GetWidth, GetLayer, Retag)] +#[enum_dispatch(GetWidth, GetLayer, Retag)] #[derive(Debug, Clone, Copy, PartialEq)] -pub enum GeometryWeight { +pub enum PrimitiveWeight { FixedDot(FixedDotWeight), LooseDot(LooseDotWeight), FixedSeg(FixedSegWeight), diff --git a/src/drawing/grouping.rs b/src/drawing/grouping.rs index 9c01160..dc12448 100644 --- a/src/drawing/grouping.rs +++ b/src/drawing/grouping.rs @@ -4,7 +4,7 @@ use petgraph::stable_graph::NodeIndex; use crate::{ drawing::{ - graph::{GeometryIndex, GeometryWeight, GetLayer, GetMaybeNet, MakePrimitive, Retag}, + graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag}, primitive::{GenericPrimitive, Primitive}, rules::RulesTrait, Drawing, diff --git a/src/drawing/guide.rs b/src/drawing/guide.rs index 21b01f8..8af93e8 100644 --- a/src/drawing/guide.rs +++ b/src/drawing/guide.rs @@ -15,7 +15,7 @@ use crate::{ }; use super::{ - graph::GeometryIndex, + graph::PrimitiveIndex, primitive::GetJoints, rules::{Conditions, RulesTrait}, segbend::Segbend, @@ -241,7 +241,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> { .other_joint(head.segbend.dot.into()) } - fn conditions(&self, node: GeometryIndex) -> Conditions { + fn conditions(&self, node: PrimitiveIndex) -> Conditions { node.primitive(self.drawing).conditions() } } diff --git a/src/drawing/loose.rs b/src/drawing/loose.rs index 0d82f05..42f1061 100644 --- a/src/drawing/loose.rs +++ b/src/drawing/loose.rs @@ -6,7 +6,7 @@ use crate::{ drawing::{ bend::LooseBendIndex, dot::{DotIndex, LooseDotIndex}, - graph::{GeometryIndex, MakePrimitive}, + graph::{MakePrimitive, PrimitiveIndex}, primitive::{GetJoints, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg}, seg::{LoneLooseSegIndex, SeqLooseSegIndex}, }, @@ -29,13 +29,13 @@ pub enum LooseIndex { Bend(LooseBendIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(loose: LooseIndex) -> Self { match loose { - LooseIndex::Dot(dot) => GeometryIndex::LooseDot(dot), - LooseIndex::LoneSeg(seg) => GeometryIndex::LoneLooseSeg(seg), - LooseIndex::SeqSeg(seg) => GeometryIndex::SeqLooseSeg(seg), - LooseIndex::Bend(bend) => GeometryIndex::LooseBend(bend), + LooseIndex::Dot(dot) => PrimitiveIndex::LooseDot(dot), + LooseIndex::LoneSeg(seg) => PrimitiveIndex::LoneLooseSeg(seg), + LooseIndex::SeqSeg(seg) => PrimitiveIndex::SeqLooseSeg(seg), + LooseIndex::Bend(bend) => PrimitiveIndex::LooseBend(bend), } } } diff --git a/src/drawing/primitive.rs b/src/drawing/primitive.rs index 6799b00..fba545c 100644 --- a/src/drawing/primitive.rs +++ b/src/drawing/primitive.rs @@ -11,7 +11,7 @@ use crate::{ drawing::{ bend::{BendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, - graph::{GeometryIndex, GeometryWeight, GetLayer, GetMaybeNet, Retag}, + graph::{GetLayer, GetMaybeNet, PrimitiveIndex, PrimitiveWeight, Retag}, loose::LooseIndex, rules::{Conditions, GetConditions, RulesTrait}, seg::{ @@ -20,7 +20,7 @@ use crate::{ }, Drawing, }, - geometry::CompoundWeight, + geometry::Compound, }; #[enum_dispatch] @@ -40,10 +40,10 @@ pub trait MakeShape { #[enum_dispatch] pub trait GetLimbs { - fn limbs(&self) -> Vec { + fn limbs(&self) -> Vec { let mut v = vec![]; - v.extend(self.segs().into_iter().map(Into::::into)); - v.extend(self.bends().into_iter().map(Into::::into)); + v.extend(self.segs().into_iter().map(Into::::into)); + v.extend(self.bends().into_iter().map(Into::::into)); v } @@ -119,7 +119,7 @@ macro_rules! impl_primitive { ($primitive_struct:ident, $weight_struct:ident) => { impl<'a, R: RulesTrait> GetWeight<$weight_struct> for $primitive_struct<'a, R> { fn weight(&self) -> $weight_struct { - if let GeometryWeight::$primitive_struct(weight) = self.tagged_weight() { + if let PrimitiveWeight::$primitive_struct(weight) = self.tagged_weight() { weight } else { unreachable!() @@ -183,8 +183,8 @@ impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> { Self { index, drawing } } - fn tagged_weight(&self) -> GeometryWeight { - if let CompoundWeight::Primitive(weight) = *self + fn tagged_weight(&self) -> PrimitiveWeight { + if let Compound::Primitive(weight) = *self .drawing .geometry() .graph() @@ -202,8 +202,8 @@ impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> { } } -impl<'a, W, R: RulesTrait> GetInterior for GenericPrimitive<'a, W, R> { - fn interior(&self) -> Vec { +impl<'a, W, R: RulesTrait> GetInterior for GenericPrimitive<'a, W, R> { + fn interior(&self) -> Vec { vec![self.tagged_weight().retag(self.index.node_index())] } } @@ -260,12 +260,12 @@ impl<'a, R: RulesTrait> FixedDot<'a, R> { .unwrap(); if matches!( weight, - CompoundWeight::Primitive(GeometryWeight::LoneLooseSeg(..)) + Compound::Primitive(PrimitiveWeight::LoneLooseSeg(..)) ) { Some(LoneLooseSegIndex::new(ni.node_index()).into()) } else if matches!( weight, - CompoundWeight::Primitive(GeometryWeight::SeqLooseSeg(..)) + Compound::Primitive(PrimitiveWeight::SeqLooseSeg(..)) ) { Some(SeqLooseSegIndex::new(ni.node_index()).into()) } else { diff --git a/src/drawing/seg.rs b/src/drawing/seg.rs index 705a8e9..3383cc0 100644 --- a/src/drawing/seg.rs +++ b/src/drawing/seg.rs @@ -2,7 +2,7 @@ use enum_dispatch::enum_dispatch; use crate::{ drawing::{ - graph::{GeometryIndex, GeometryWeight, GetLayer, GetMaybeNet, MakePrimitive, Retag}, + graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag}, primitive::{GenericPrimitive, Primitive}, rules::RulesTrait, Drawing, @@ -21,24 +21,24 @@ pub enum SegIndex { SeqLoose(SeqLooseSegIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(seg: SegIndex) -> Self { match seg { - SegIndex::Fixed(seg) => GeometryIndex::FixedSeg(seg), - SegIndex::LoneLoose(seg) => GeometryIndex::LoneLooseSeg(seg), - SegIndex::SeqLoose(seg) => GeometryIndex::SeqLooseSeg(seg), + SegIndex::Fixed(seg) => PrimitiveIndex::FixedSeg(seg), + SegIndex::LoneLoose(seg) => PrimitiveIndex::LoneLooseSeg(seg), + SegIndex::SeqLoose(seg) => PrimitiveIndex::SeqLooseSeg(seg), } } } -impl TryFrom for SegIndex { +impl TryFrom for SegIndex { type Error = (); // TODO. - fn try_from(index: GeometryIndex) -> Result { + fn try_from(index: PrimitiveIndex) -> Result { match index { - GeometryIndex::FixedSeg(index) => Ok(SegIndex::Fixed(index)), - GeometryIndex::LoneLooseSeg(index) => Ok(SegIndex::LoneLoose(index)), - GeometryIndex::SeqLooseSeg(index) => Ok(SegIndex::SeqLoose(index)), + PrimitiveIndex::FixedSeg(index) => Ok(SegIndex::Fixed(index)), + PrimitiveIndex::LoneLooseSeg(index) => Ok(SegIndex::LoneLoose(index)), + PrimitiveIndex::SeqLooseSeg(index) => Ok(SegIndex::SeqLoose(index)), _ => Err(()), } } @@ -52,30 +52,30 @@ pub enum SegWeight { SeqLoose(SeqLooseSegWeight), } -impl From for GeometryWeight { +impl From for PrimitiveWeight { fn from(seg: SegWeight) -> Self { match seg { - SegWeight::Fixed(weight) => GeometryWeight::FixedSeg(weight), - SegWeight::LoneLoose(weight) => GeometryWeight::LoneLooseSeg(weight), - SegWeight::SeqLoose(weight) => GeometryWeight::SeqLooseSeg(weight), + SegWeight::Fixed(weight) => PrimitiveWeight::FixedSeg(weight), + SegWeight::LoneLoose(weight) => PrimitiveWeight::LoneLooseSeg(weight), + SegWeight::SeqLoose(weight) => PrimitiveWeight::SeqLooseSeg(weight), } } } -impl TryFrom for SegWeight { +impl TryFrom for SegWeight { type Error = (); // TODO. - fn try_from(weight: GeometryWeight) -> Result { + fn try_from(weight: PrimitiveWeight) -> Result { match weight { - GeometryWeight::FixedSeg(weight) => Ok(SegWeight::Fixed(weight)), - GeometryWeight::LoneLooseSeg(weight) => Ok(SegWeight::LoneLoose(weight)), - GeometryWeight::SeqLooseSeg(weight) => Ok(SegWeight::SeqLoose(weight)), + PrimitiveWeight::FixedSeg(weight) => Ok(SegWeight::Fixed(weight)), + PrimitiveWeight::LoneLooseSeg(weight) => Ok(SegWeight::LoneLoose(weight)), + PrimitiveWeight::SeqLooseSeg(weight) => Ok(SegWeight::SeqLoose(weight)), _ => Err(()), } } } -impl SegWeightTrait for SegWeight {} +impl SegWeightTrait for SegWeight {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedSegWeight { @@ -85,7 +85,7 @@ pub struct FixedSegWeight { } impl_fixed_weight!(FixedSegWeight, FixedSeg, FixedSegIndex); -impl SegWeightTrait for FixedSegWeight {} +impl SegWeightTrait for FixedSegWeight {} impl GetWidth for FixedSegWeight { fn width(&self) -> f64 { @@ -101,7 +101,7 @@ pub struct LoneLooseSegWeight { } impl_loose_weight!(LoneLooseSegWeight, LoneLooseSeg, LoneLooseSegIndex); -impl SegWeightTrait for LoneLooseSegWeight {} +impl SegWeightTrait for LoneLooseSegWeight {} impl GetWidth for LoneLooseSegWeight { fn width(&self) -> f64 { @@ -117,7 +117,7 @@ pub struct SeqLooseSegWeight { } impl_loose_weight!(SeqLooseSegWeight, SeqLooseSeg, SeqLooseSegIndex); -impl SegWeightTrait for SeqLooseSegWeight {} +impl SegWeightTrait for SeqLooseSegWeight {} impl GetWidth for SeqLooseSegWeight { fn width(&self) -> f64 { diff --git a/src/drawing/segbend.rs b/src/drawing/segbend.rs index 775c267..39e6b89 100644 --- a/src/drawing/segbend.rs +++ b/src/drawing/segbend.rs @@ -1,7 +1,7 @@ use crate::drawing::{ bend::LooseBendIndex, dot::LooseDotIndex, - graph::GeometryIndex, + graph::PrimitiveIndex, primitive::{GetInterior, GetJoints, GetOtherJoint, LooseBend, LooseDot}, seg::SeqLooseSegIndex, Drawing, @@ -25,8 +25,8 @@ impl Segbend { } } -impl GetInterior for Segbend { - fn interior(&self) -> Vec { +impl GetInterior for Segbend { + fn interior(&self) -> Vec { vec![self.bend.into(), self.dot.into(), self.seg.into()] } } diff --git a/src/geometry/geometry.rs b/src/geometry/geometry.rs index f60ea21..91d37aa 100644 --- a/src/geometry/geometry.rs +++ b/src/geometry/geometry.rs @@ -12,7 +12,7 @@ use crate::{ drawing::{ bend::{BendWeight, FixedBendWeight, LooseBendWeight}, dot::{DotWeight, FixedDotWeight, LooseDotWeight}, - graph::{GeometryWeight, Retag}, + graph::{PrimitiveWeight, Retag}, primitive::Primitive, rules::RulesTrait, seg::{FixedSegWeight, LoneLooseSegWeight, SegWeight, SeqLooseSegWeight}, @@ -52,10 +52,11 @@ pub enum GeometryLabel { Joined, Outer, Core, + Grouping, } #[derive(Debug, Clone, Copy, PartialEq)] -pub enum CompoundWeight { +pub enum Compound { Primitive(PW), Grouping(XW), } @@ -75,9 +76,8 @@ pub struct Geometry< DI: GetNodeIndex + Into + Copy, SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, - GI: GetNodeIndex + Copy, > { - graph: StableDiGraph, GeometryLabel, usize>, + graph: StableDiGraph, GeometryLabel, usize>, weight_marker: PhantomData, dot_weight_marker: PhantomData, seg_weight_marker: PhantomData, @@ -87,7 +87,6 @@ pub struct Geometry< dot_index_marker: PhantomData, seg_index_marker: PhantomData, bend_index_marker: PhantomData, - grouping_index_marker: PhantomData, } impl< @@ -100,8 +99,7 @@ impl< DI: GetNodeIndex + Into + Copy, SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, - GI: GetNodeIndex + Copy, - > Geometry + > Geometry { pub fn new() -> Self { Self { @@ -115,15 +113,11 @@ impl< dot_index_marker: PhantomData, seg_index_marker: PhantomData, bend_index_marker: PhantomData, - grouping_index_marker: PhantomData, } } pub fn add_dot>(&mut self, weight: W) -> GenericIndex { - GenericIndex::::new( - self.graph - .add_node(CompoundWeight::Primitive(weight.into())), - ) + GenericIndex::::new(self.graph.add_node(Compound::Primitive(weight.into()))) } pub fn add_seg>( @@ -132,10 +126,7 @@ impl< to: DI, weight: W, ) -> GenericIndex { - let seg = GenericIndex::::new( - self.graph - .add_node(CompoundWeight::Primitive(weight.into())), - ); + let seg = GenericIndex::::new(self.graph.add_node(Compound::Primitive(weight.into()))); self.graph .update_edge(from.node_index(), seg.node_index(), GeometryLabel::Joined); @@ -152,10 +143,7 @@ impl< core: DI, weight: W, ) -> GenericIndex { - let bend = GenericIndex::::new( - self.graph - .add_node(CompoundWeight::Primitive(weight.into())), - ); + let bend = GenericIndex::::new(self.graph.add_node(Compound::Primitive(weight.into()))); self.graph .update_edge(from.node_index(), bend.node_index(), GeometryLabel::Joined); @@ -167,22 +155,41 @@ impl< bend } - pub fn remove(&mut self, node: PI) { - self.graph.remove_node(node.node_index()); + pub fn add_grouping(&mut self, weight: GW) -> GenericIndex { + GenericIndex::::new(self.graph.add_node(Compound::Grouping(weight))) + } + + pub fn assign_to_grouping( + &mut self, + primitive: GenericIndex, + grouping: GenericIndex, + ) { + self.graph.update_edge( + primitive.node_index(), + grouping.node_index(), + GeometryLabel::Grouping, + ); + } + + pub fn remove_primitive(&mut self, primitive: PI) { + self.graph.remove_node(primitive.node_index()); + } + + pub fn remove_grouping(&mut self, grouping: GenericIndex) { + self.graph.remove_node(grouping.node_index()); } pub fn move_dot(&mut self, dot: DI, to: Point) { let mut weight = self.dot_weight(dot); weight.set_pos(to); - *self.graph.node_weight_mut(dot.node_index()).unwrap() = - CompoundWeight::Primitive(weight.into()); + *self.graph.node_weight_mut(dot.node_index()).unwrap() = Compound::Primitive(weight.into()); } pub fn shift_bend(&mut self, bend: BI, offset: f64) { let mut weight = self.bend_weight(bend); weight.set_offset(offset); *self.graph.node_weight_mut(bend.node_index()).unwrap() = - CompoundWeight::Primitive(weight.into()); + Compound::Primitive(weight.into()); } pub fn flip_bend(&mut self, bend: BI) { @@ -278,7 +285,7 @@ impl< } fn primitive_weight(&self, index: NodeIndex) -> PW { - if let CompoundWeight::Primitive(weight) = *self.graph.node_weight(index).unwrap() { + if let Compound::Primitive(weight) = *self.graph.node_weight(index).unwrap() { weight } else { unreachable!() @@ -452,7 +459,7 @@ impl< self.joineds(dot.into()).filter_map(|ni| ni.try_into().ok()) } - pub fn graph(&self) -> &StableDiGraph, GeometryLabel, usize> { + pub fn graph(&self) -> &StableDiGraph, GeometryLabel, usize> { &self.graph } } diff --git a/src/geometry/with_rtree.rs b/src/geometry/with_rtree.rs index 0b8ae6c..8c0532e 100644 --- a/src/geometry/with_rtree.rs +++ b/src/geometry/with_rtree.rs @@ -9,7 +9,7 @@ use crate::{ drawing::graph::{GetLayer, Retag}, geometry::{ shape::{Shape, ShapeTrait}, - BendWeightTrait, CompoundWeight, DotWeightTrait, Geometry, GeometryLabel, GetWidth, + BendWeightTrait, Compound, DotWeightTrait, Geometry, GeometryLabel, GetWidth, SegWeightTrait, }, graph::{GenericIndex, GetNodeIndex}, @@ -21,10 +21,8 @@ pub struct Bbox { } impl Bbox { - pub fn new(shape: &Shape, layer: u64) -> Bbox { - Self { - aabb: shape.envelope_3d(0.0, layer), - } + pub fn new(aabb: AABB<[f64; 3]>) -> Bbox { + Self { aabb } } } @@ -35,7 +33,7 @@ impl RTreeObject for Bbox { } } -type BboxedIndex = GeomWithData; +type BboxedIndex = GeomWithData; #[derive(Debug)] pub struct GeometryWithRtree< @@ -48,10 +46,9 @@ pub struct GeometryWithRtree< DI: GetNodeIndex + Into + Copy, SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, - GI: GetNodeIndex + Copy, > { - geometry: Geometry, - rtree: RTree>, + geometry: Geometry, + rtree: RTree>>>, layer_count: u64, weight_marker: PhantomData, dot_weight_marker: PhantomData, @@ -75,12 +72,11 @@ impl< DI: GetNodeIndex + Into + Copy, SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, - GI: GetNodeIndex + Copy, - > GeometryWithRtree + > GeometryWithRtree { pub fn new(layer_count: u64) -> Self { Self { - geometry: Geometry::::new(), + geometry: Geometry::::new(), rtree: RTree::new(), layer_count, weight_marker: PhantomData, @@ -101,12 +97,11 @@ impl< let dot = self.geometry.add_dot(weight); self.rtree.insert(BboxedIndex::new( Bbox::new( - &self - .geometry - .dot_shape(dot.into().try_into().unwrap_or_else(|_| unreachable!())), - weight.layer(), + self.geometry + .dot_shape(dot.into().try_into().unwrap_or_else(|_| unreachable!())) + .envelope_3d(0.0, weight.layer()), ), - dot.into(), + Compound::Primitive(dot.into()), )); dot } @@ -123,12 +118,11 @@ impl< let seg = self.geometry.add_seg(from, to, weight); self.rtree.insert(BboxedIndex::new( Bbox::new( - &self - .geometry - .seg_shape(seg.into().try_into().unwrap_or_else(|_| unreachable!())), - weight.layer(), + self.geometry + .seg_shape(seg.into().try_into().unwrap_or_else(|_| unreachable!())) + .envelope_3d(0.0, weight.layer()), ), - seg.into(), + Compound::Primitive(seg.into()), )); seg } @@ -146,16 +140,32 @@ impl< let bend = self.geometry.add_bend(from, to, core, weight); self.rtree.insert(BboxedIndex::new( Bbox::new( - &self - .geometry - .bend_shape(bend.into().try_into().unwrap_or_else(|_| unreachable!())), - weight.layer(), + self.geometry + .bend_shape(bend.into().try_into().unwrap_or_else(|_| unreachable!())) + .envelope_3d(0.0, weight.layer()), ), - bend.into(), + Compound::Primitive(bend.into()), )); bend } + pub fn add_grouping(&mut self, weight: GW) -> GenericIndex { + let grouping = self.geometry.add_grouping(weight); + self.rtree.insert(BboxedIndex::new( + Bbox::new(AABB::<[f64; 3]>::from_point([0.0, 0.0, -1.0].into())), + Compound::Grouping(grouping), + )); + grouping + } + + pub fn assign_to_grouping( + &mut self, + primitive: GenericIndex, + grouping: GenericIndex, + ) { + self.geometry.assign_to_grouping(primitive, grouping) + } + pub fn remove_dot(&mut self, dot: DI) -> Result<(), ()> { if self.geometry.joined_segs(dot).next().is_some() { return Err(()); @@ -166,18 +176,23 @@ impl< } self.rtree.remove(&self.make_dot_bbox(dot)); - self.geometry.remove(dot.into()); + self.geometry.remove_primitive(dot.into()); Ok(()) } pub fn remove_seg(&mut self, seg: SI) { self.rtree.remove(&self.make_seg_bbox(seg)); - self.geometry.remove(seg.into()); + self.geometry.remove_primitive(seg.into()); } pub fn remove_bend(&mut self, bend: BI) { self.rtree.remove(&self.make_bend_bbox(bend)); - self.geometry.remove(bend.into()); + self.geometry.remove_primitive(bend.into()); + } + + pub fn remove_grouping(&mut self, grouping: GenericIndex) { + self.rtree.remove(&self.make_grouping_bbox(grouping)); + self.geometry.remove_grouping(grouping); } pub fn move_dot(&mut self, dot: DI, to: Point) { @@ -258,27 +273,48 @@ impl< DI: GetNodeIndex + Into + Copy, SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, - GI: GetNodeIndex + Copy, - > GeometryWithRtree + > GeometryWithRtree { - fn make_dot_bbox(&self, dot: DI) -> BboxedIndex { + fn make_dot_bbox(&self, dot: DI) -> BboxedIndex>> { BboxedIndex::new( - Bbox::new(&self.geometry.dot_shape(dot), self.layer(dot.into())), - dot.into(), + Bbox::new( + self.geometry + .dot_shape(dot) + .envelope_3d(0.0, self.layer(dot.into())), + ), + Compound::Primitive(dot.into()), ) } - fn make_seg_bbox(&self, seg: SI) -> BboxedIndex { + fn make_seg_bbox(&self, seg: SI) -> BboxedIndex>> { BboxedIndex::new( - Bbox::new(&self.geometry.seg_shape(seg), self.layer(seg.into())), - seg.into(), + Bbox::new( + self.geometry + .seg_shape(seg) + .envelope_3d(0.0, self.layer(seg.into())), + ), + Compound::Primitive(seg.into()), ) } - fn make_bend_bbox(&self, bend: BI) -> BboxedIndex { + fn make_bend_bbox(&self, bend: BI) -> BboxedIndex>> { BboxedIndex::new( - Bbox::new(&self.geometry.bend_shape(bend), self.layer(bend.into())), - bend.into(), + Bbox::new( + self.geometry + .bend_shape(bend) + .envelope_3d(0.0, self.layer(bend.into())), + ), + Compound::Primitive(bend.into()), + ) + } + + fn make_grouping_bbox( + &self, + grouping: GenericIndex, + ) -> BboxedIndex>> { + BboxedIndex::new( + Bbox::new(AABB::<[f64; 3]>::from_point([0.0, 0.0, -1.0].into())), + Compound::Grouping(grouping), ) } @@ -306,24 +342,30 @@ impl< } } - pub fn geometry(&self) -> &Geometry { + pub fn geometry(&self) -> &Geometry { &self.geometry } - pub fn rtree(&self) -> &RTree> { + pub fn rtree(&self) -> &RTree>>> { &self.rtree } - pub fn graph(&self) -> &StableDiGraph, GeometryLabel, usize> { + pub fn graph(&self) -> &StableDiGraph, GeometryLabel, usize> { self.geometry.graph() } fn test_envelopes(&self) -> bool { !self.rtree.iter().any(|wrapper| { - let node = wrapper.data; - let shape = self.shape(node); - let layer = self.layer(node); - let wrapper = BboxedIndex::new(Bbox::new(&shape, layer), node); + // TODO: Test envelopes of groupings too. + let Compound::Primitive(primitive_node) = wrapper.data else { + return false; + }; + let shape = self.shape(primitive_node); + let layer = self.layer(primitive_node); + let wrapper = BboxedIndex::new( + Bbox::new(shape.envelope_3d(0.0, layer)), + Compound::Primitive(primitive_node), + ); !self .rtree .locate_in_envelope(&shape.envelope_3d(0.0, layer)) diff --git a/src/mesh.rs b/src/mesh.rs index 7b953f8..bed654d 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -13,7 +13,7 @@ use crate::{ drawing::{ bend::{FixedBendIndex, LooseBendIndex}, dot::FixedDotIndex, - graph::{GeometryIndex, MakePrimitive}, + graph::{MakePrimitive, PrimitiveIndex}, primitive::{GetCore, MakeShape, Primitive}, Drawing, }, @@ -37,12 +37,12 @@ pub enum TriangulationVertexIndex { FixedBend(FixedBendIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(vertex: VertexIndex) -> Self { match vertex { - VertexIndex::FixedDot(dot) => GeometryIndex::FixedDot(dot), - VertexIndex::FixedBend(bend) => GeometryIndex::FixedBend(bend), - VertexIndex::LooseBend(bend) => GeometryIndex::LooseBend(bend), + VertexIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot), + VertexIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend), + VertexIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend), } } } @@ -94,18 +94,18 @@ impl Mesh { } pub fn generate(&mut self, drawing: &Drawing) -> Result<(), InsertionError> { - for node in drawing.nodes() { + for node in drawing.primitive_nodes() { let center = node.primitive(drawing).shape().center(); match node { - GeometryIndex::FixedDot(dot) => { + PrimitiveIndex::FixedDot(dot) => { self.triangulation.add_vertex(TriangulationWeight { vertex: dot.into(), rails: vec![], pos: center, })?; } - GeometryIndex::FixedBend(bend) => { + PrimitiveIndex::FixedBend(bend) => { self.triangulation.add_vertex(TriangulationWeight { vertex: bend.into(), rails: vec![], @@ -116,10 +116,10 @@ impl Mesh { } } - for node in drawing.nodes() { + for node in drawing.primitive_nodes() { // Add rails as vertices. This is how the mesh differs from the triangulation. match node { - GeometryIndex::LooseBend(bend) => { + PrimitiveIndex::LooseBend(bend) => { self.triangulation .weight_mut(drawing.primitive(bend).core().into()) .rails diff --git a/src/router.rs b/src/router.rs index 819b288..2c4dedc 100644 --- a/src/router.rs +++ b/src/router.rs @@ -8,7 +8,7 @@ use crate::astar::{astar, AstarStrategy, PathTracker}; use crate::draw::DrawException; use crate::drawing::{ dot::FixedDotIndex, - graph::{GeometryIndex, MakePrimitive}, + graph::{MakePrimitive, PrimitiveIndex}, primitive::MakeShape, rules::RulesTrait, }; @@ -118,7 +118,7 @@ impl<'a, RO: RouterObserverTrait, R: RulesTrait> AstarStrategy<&Mesh, f64> fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 { self.observer.on_estimate(&self.tracer, vertex); - let start_point = GeometryIndex::from(vertex) + let start_point = PrimitiveIndex::from(vertex) .primitive(self.tracer.layout.layout()) .shape() .center(); diff --git a/src/wraparoundable.rs b/src/wraparoundable.rs index 5a19504..3cebd7f 100644 --- a/src/wraparoundable.rs +++ b/src/wraparoundable.rs @@ -5,7 +5,7 @@ use crate::{ drawing::{ bend::{BendIndex, FixedBendIndex, LooseBendIndex}, dot::FixedDotIndex, - graph::{GeometryIndex, MakePrimitive}, + graph::{MakePrimitive, PrimitiveIndex}, primitive::{FixedBend, FixedDot, GetFirstRail, GetInnerOuter, LooseBend, Primitive}, rules::RulesTrait, Drawing, @@ -26,12 +26,12 @@ pub enum WraparoundableIndex { LooseBend(LooseBendIndex), } -impl From for GeometryIndex { +impl From for PrimitiveIndex { fn from(wraparoundable: WraparoundableIndex) -> Self { match wraparoundable { - WraparoundableIndex::FixedDot(dot) => GeometryIndex::FixedDot(dot), - WraparoundableIndex::FixedBend(bend) => GeometryIndex::FixedBend(bend), - WraparoundableIndex::LooseBend(bend) => GeometryIndex::LooseBend(bend), + WraparoundableIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot), + WraparoundableIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend), + WraparoundableIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend), } } }