geometry: make graph private, encapsulate all mutating usage of it

This commit is contained in:
Mikolaj Wielgus 2024-01-30 19:00:16 +00:00
parent 410b029eb3
commit 39bd393ff7
3 changed files with 63 additions and 44 deletions

View File

@ -1,6 +1,8 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use geo::Point; use geo::Point;
use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::{ layout::{
@ -16,7 +18,7 @@ use crate::{
math::Circle, math::Circle,
}; };
use petgraph::stable_graph::NodeIndex; use super::geometry::SetPos;
#[enum_dispatch(GetNodeIndex, MakePrimitive)] #[enum_dispatch(GetNodeIndex, MakePrimitive)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -46,7 +48,7 @@ impl TryFrom<GeometryIndex> for DotIndex {
} }
} }
#[enum_dispatch(GetPos, GetWidth)] #[enum_dispatch(GetPos, SetPos, GetWidth)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum DotWeight { pub enum DotWeight {
Fixed(FixedDotWeight), Fixed(FixedDotWeight),
@ -91,6 +93,12 @@ impl GetPos for FixedDotWeight {
} }
} }
impl SetPos for FixedDotWeight {
fn set_pos(&mut self, pos: Point) {
self.circle.pos = pos
}
}
impl GetWidth for FixedDotWeight { impl GetWidth for FixedDotWeight {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.circle.r * 2.0 self.circle.r * 2.0
@ -112,6 +120,12 @@ impl GetPos for LooseDotWeight {
} }
} }
impl SetPos for LooseDotWeight {
fn set_pos(&mut self, pos: Point) {
self.circle.pos = pos
}
}
impl GetWidth for LooseDotWeight { impl GetWidth for LooseDotWeight {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.circle.r * 2.0 self.circle.r * 2.0

View File

@ -24,6 +24,11 @@ pub trait GetPos {
fn pos(&self) -> Point; fn pos(&self) -> Point;
} }
#[enum_dispatch]
pub trait SetPos {
fn set_pos(&mut self, pos: Point);
}
#[enum_dispatch] #[enum_dispatch]
pub trait GetWidth { pub trait GetWidth {
fn width(&self) -> f64; fn width(&self) -> f64;
@ -41,7 +46,7 @@ pub enum GeometryLabel {
Core, Core,
} }
pub trait DotWeightTrait<GW>: GetPos + GetWidth + Into<GW> + Copy {} pub trait DotWeightTrait<GW>: GetPos + SetPos + GetWidth + Into<GW> + Copy {}
pub trait SegWeightTrait<GW>: GetWidth + Into<GW> + Copy {} pub trait SegWeightTrait<GW>: GetWidth + Into<GW> + Copy {}
pub trait BendWeightTrait<GW>: GetOffset + GetWidth + Into<GW> + Copy {} pub trait BendWeightTrait<GW>: GetOffset + GetWidth + Into<GW> + Copy {}
@ -56,7 +61,7 @@ pub struct Geometry<
SI: GetNodeIndex + Into<GI> + Copy, SI: GetNodeIndex + Into<GI> + Copy,
BI: GetNodeIndex + Into<GI> + Copy, BI: GetNodeIndex + Into<GI> + Copy,
> { > {
pub graph: StableDiGraph<GW, GeometryLabel, usize>, graph: StableDiGraph<GW, GeometryLabel, usize>,
weight_marker: PhantomData<GW>, weight_marker: PhantomData<GW>,
dot_weight_marker: PhantomData<DW>, dot_weight_marker: PhantomData<DW>,
seg_weight_marker: PhantomData<SW>, seg_weight_marker: PhantomData<SW>,
@ -140,6 +145,40 @@ impl<
bend bend
} }
pub fn remove(&mut self, node: GI) {
self.graph.remove_node(node.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() = weight.into()
}
pub fn flip_bend(&mut self, bend: BI) {
let (from, to) = self.bend_joints(bend);
let from_edge_weight = self
.graph
.remove_edge(
self.graph
.find_edge(from.node_index(), bend.node_index())
.unwrap(),
)
.unwrap();
let to_edge_weight = self
.graph
.remove_edge(
self.graph
.find_edge(bend.node_index(), to.node_index())
.unwrap(),
)
.unwrap();
self.graph
.update_edge(from.node_index(), bend.node_index(), to_edge_weight);
self.graph
.update_edge(bend.node_index(), to.node_index(), from_edge_weight);
}
pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) { pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) {
if let Some(old_inner_edge) = self if let Some(old_inner_edge) = self
.graph .graph

View File

@ -18,7 +18,7 @@ use crate::guide::Guide;
use crate::layout::bend::BendIndex; use crate::layout::bend::BendIndex;
use crate::layout::dot::DotWeight; use crate::layout::dot::DotWeight;
use crate::layout::geometry::{ use crate::layout::geometry::{
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, SegWeightTrait, BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, SegWeightTrait,
}; };
use crate::layout::{ use crate::layout::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
@ -188,7 +188,7 @@ impl Layout {
.unwrap(); .unwrap();
self.remove_from_rtree(weight.retag(node.node_index())); self.remove_from_rtree(weight.retag(node.node_index()));
self.geometry.graph.remove_node(node.node_index()); self.geometry.remove(node);
} }
// TODO: This method shouldn't be public. // TODO: This method shouldn't be public.
@ -729,12 +729,6 @@ impl Layout {
.add_bend(from.into(), to.into(), core.into(), weight); .add_bend(from.into(), to.into(), core.into(), weight);
self.geometry.reattach_bend(bend.into(), Some(inner)); self.geometry.reattach_bend(bend.into(), Some(inner));
self.geometry.graph.update_edge(
inner.node_index(),
bend.node_index(),
GeometryLabel::Outer,
);
self.insert_into_rtree(bend.into()); self.insert_into_rtree(bend.into());
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend) Ok(bend)
@ -744,15 +738,7 @@ impl Layout {
#[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))] #[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))]
pub fn flip_bend(&mut self, bend: FixedBendIndex) { pub fn flip_bend(&mut self, bend: FixedBendIndex) {
self.remove_from_rtree(bend.into()); self.remove_from_rtree(bend.into());
self.geometry.flip_bend(bend.into());
let Some(GeometryWeight::FixedBend(weight)) =
self.geometry.graph.node_weight_mut(bend.node_index())
else {
unreachable!();
};
weight.cw = !weight.cw;
self.insert_into_rtree(bend.into()); self.insert_into_rtree(bend.into());
} }
@ -821,32 +807,12 @@ impl Layout {
) -> Result<(), Infringement> { ) -> Result<(), Infringement> {
self.remove_from_rtree_with_limbs(dot.into()); self.remove_from_rtree_with_limbs(dot.into());
let mut weight = *self.geometry.graph.node_weight(dot.node_index()).unwrap(); let old_pos = self.geometry.dot_weight(dot).pos();
let old_weight = weight; self.geometry.move_dot(dot, to);
match weight {
GeometryWeight::FixedDot(ref mut fixed) => {
fixed.circle.pos = to;
}
GeometryWeight::LooseDot(ref mut loose) => {
loose.circle.pos = to;
}
_ => unreachable!(),
}
*self
.geometry
.graph
.node_weight_mut(dot.node_index())
.unwrap() = weight;
if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) { if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) {
// Restore original state. // Restore original state.
*self self.geometry.move_dot(dot, old_pos);
.geometry
.graph
.node_weight_mut(dot.node_index())
.unwrap() = old_weight;
self.insert_into_rtree_with_limbs(dot.into()); self.insert_into_rtree_with_limbs(dot.into());
return Err(infringement); return Err(infringement);