geometry: implement incomplete interface for manipulation of groupings

This commit is contained in:
Mikolaj Wielgus 2024-03-26 20:24:15 +00:00
parent 888a4ecbad
commit 3a812d5621
18 changed files with 313 additions and 237 deletions

View File

@ -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));
}

View File

@ -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<Mesh>,
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 {

View File

@ -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<BendIndex> for GeometryIndex {
impl From<BendIndex> 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<GeometryIndex> for BendIndex {
impl TryFrom<PrimitiveIndex> for BendIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<BendIndex, ()> {
fn try_from(index: PrimitiveIndex) -> Result<BendIndex, ()> {
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<BendWeight> for GeometryWeight {
impl From<BendWeight> 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<GeometryWeight> for BendWeight {
impl TryFrom<PrimitiveWeight> for BendWeight {
type Error = (); // TODO.
fn try_from(weight: GeometryWeight) -> Result<BendWeight, ()> {
fn try_from(weight: PrimitiveWeight) -> Result<BendWeight, ()> {
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<GeometryWeight> for BendWeight {}
impl BendWeightTrait<PrimitiveWeight> 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<GeometryWeight> for FixedBendWeight {}
impl BendWeightTrait<PrimitiveWeight> 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<GeometryWeight> for LooseBendWeight {}
impl BendWeightTrait<PrimitiveWeight> for LooseBendWeight {}

View File

@ -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<GeometryIndex> {
let mut v: Vec<GeometryIndex> = vec![];
pub fn bend_bow(&self, bend: LooseBendIndex) -> Vec<PrimitiveIndex> {
let mut v: Vec<PrimitiveIndex> = 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<GeometryIndex> {
pub fn bend_outer_bows(&self, bend: LooseBendIndex) -> Vec<PrimitiveIndex> {
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<GeometryIndex> {
pub fn wraparounded_bows(&self, around: WraparoundableIndex) -> Vec<PrimitiveIndex> {
let mut v = vec![];
let mut rail = around.into();

View File

@ -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<DotIndex> for GeometryIndex {
impl From<DotIndex> 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<GeometryIndex> for DotIndex {
impl TryFrom<PrimitiveIndex> for DotIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<DotIndex, ()> {
fn try_from(index: PrimitiveIndex) -> Result<DotIndex, ()> {
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<DotWeight> for GeometryWeight {
impl From<DotWeight> 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<GeometryWeight> for DotWeight {
impl TryFrom<PrimitiveWeight> for DotWeight {
type Error = (); // TODO.
fn try_from(weight: GeometryWeight) -> Result<DotWeight, ()> {
fn try_from(weight: PrimitiveWeight) -> Result<DotWeight, ()> {
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<GeometryWeight> for DotWeight {}
impl DotWeightTrait<PrimitiveWeight> 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<GeometryWeight> for FixedDotWeight {}
impl DotWeightTrait<PrimitiveWeight> 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<GeometryWeight> for LooseDotWeight {}
impl DotWeightTrait<PrimitiveWeight> for LooseDotWeight {}
impl GetPos for LooseDotWeight {
fn pos(&self) -> Point {

View File

@ -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<R: RulesTrait> {
geometry_with_rtree: GeometryWithRtree<
GeometryWeight,
PrimitiveWeight,
DotWeight,
SegWeight,
BendWeight,
GroupingWeight,
GeometryIndex,
PrimitiveIndex,
DotIndex,
SegIndex,
BendIndex,
GroupingIndex,
>,
rules: R,
}
@ -179,13 +179,13 @@ impl<R: RulesTrait> Drawing<R> {
#[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<W: DotWeightTrait<GeometryWeight> + GetLayer>(
fn add_dot_infringably<W: DotWeightTrait<PrimitiveWeight> + GetLayer>(
&mut self,
weight: W,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
GenericIndex<W>: Into<PrimitiveIndex> + 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<R: RulesTrait> Drawing<R> {
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<Segbend, LayoutException> {
let seg_to = self.add_dot_infringably(dot_weight, infringables)?;
let seg = self
@ -473,15 +473,15 @@ impl<R: RulesTrait> Drawing<R> {
#[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<W: SegWeightTrait<GeometryWeight> + GetLayer>(
fn add_seg_infringably<W: SegWeightTrait<PrimitiveWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
GenericIndex<W>: Into<PrimitiveIndex> + 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<R: RulesTrait> Drawing<R> {
to: LooseDotIndex,
around: WraparoundableIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<LooseBendIndex, LayoutException> {
// It makes no sense to wrap something around or under one of its connectables.
//
@ -537,16 +537,16 @@ impl<R: RulesTrait> Drawing<R> {
#[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<W: BendWeightTrait<GeometryWeight> + GetLayer>(
fn add_core_bend_infringably<W: BendWeightTrait<PrimitiveWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
core: FixedDotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
GenericIndex<W>: Into<PrimitiveIndex> + Copy,
{
let bend = self
.geometry_with_rtree
@ -566,7 +566,7 @@ impl<R: RulesTrait> Drawing<R> {
to: LooseDotIndex,
inner: BendIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<LooseBendWeight>, Infringement> {
let core = *self
.geometry_with_rtree
@ -616,8 +616,8 @@ impl<R: RulesTrait> Drawing<R> {
#[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<R: RulesTrait> Drawing<R> {
Ok(())
}
pub fn nodes(&self) -> impl Iterator<Item = GeometryIndex> + '_ {
pub fn primitive_nodes(&self) -> impl Iterator<Item = PrimitiveIndex> + '_ {
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<Item = GeometryIndex> + '_ {
pub fn layer_primitive_nodes(&self, layer: u64) -> impl Iterator<Item = PrimitiveIndex> + '_ {
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<R: RulesTrait> Drawing<R> {
&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<R: RulesTrait> Drawing<R> {
&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<R: RulesTrait> Drawing<R> {
#[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<Infringement> {
let limiting_shape = node.primitive(self).shape().inflate(
node.primitive(self)
@ -735,10 +747,19 @@ impl<R: RulesTrait> Drawing<R> {
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<R: RulesTrait> Drawing<R> {
.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<Collision> {
fn detect_collision(&self, node: PrimitiveIndex) -> Option<Collision> {
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<R: RulesTrait> Drawing<R> {
pub fn geometry(
&self,
) -> &Geometry<
GeometryWeight,
PrimitiveWeight,
DotWeight,
SegWeight,
BendWeight,
GroupingWeight,
GeometryIndex,
PrimitiveIndex,
DotIndex,
SegIndex,
BendIndex,
GroupingIndex,
> {
self.geometry_with_rtree.geometry()
}

View File

@ -16,8 +16,8 @@ use super::{
};
#[enum_dispatch]
pub trait Retag<GeometryIndex> {
fn retag(&self, index: NodeIndex<usize>) -> GeometryIndex;
pub trait Retag<PrimitiveIndex> {
fn retag(&self, index: NodeIndex<usize>) -> 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<GeometryIndex> for $weight_struct {
fn retag(&self, index: NodeIndex<usize>) -> GeometryIndex {
GeometryIndex::$weight_variant($index_struct::new(index))
impl Retag<PrimitiveIndex> for $weight_struct {
fn retag(&self, index: NodeIndex<usize>) -> 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<GeometryIndex>)]
#[enum_dispatch(GetWidth, GetLayer, Retag<PrimitiveIndex>)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GeometryWeight {
pub enum PrimitiveWeight {
FixedDot(FixedDotWeight),
LooseDot(LooseDotWeight),
FixedSeg(FixedSegWeight),

View File

@ -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,

View File

@ -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()
}
}

View File

@ -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<LooseIndex> for GeometryIndex {
impl From<LooseIndex> 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),
}
}
}

View File

@ -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<GeometryIndex> {
fn limbs(&self) -> Vec<PrimitiveIndex> {
let mut v = vec![];
v.extend(self.segs().into_iter().map(Into::<GeometryIndex>::into));
v.extend(self.bends().into_iter().map(Into::<GeometryIndex>::into));
v.extend(self.segs().into_iter().map(Into::<PrimitiveIndex>::into));
v.extend(self.bends().into_iter().map(Into::<PrimitiveIndex>::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<GeometryIndex> for GenericPrimitive<'a, W, R> {
fn interior(&self) -> Vec<GeometryIndex> {
impl<'a, W, R: RulesTrait> GetInterior<PrimitiveIndex> for GenericPrimitive<'a, W, R> {
fn interior(&self) -> Vec<PrimitiveIndex> {
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 {

View File

@ -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<SegIndex> for GeometryIndex {
impl From<SegIndex> 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<GeometryIndex> for SegIndex {
impl TryFrom<PrimitiveIndex> for SegIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<SegIndex, ()> {
fn try_from(index: PrimitiveIndex) -> Result<SegIndex, ()> {
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<SegWeight> for GeometryWeight {
impl From<SegWeight> 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<GeometryWeight> for SegWeight {
impl TryFrom<PrimitiveWeight> for SegWeight {
type Error = (); // TODO.
fn try_from(weight: GeometryWeight) -> Result<SegWeight, ()> {
fn try_from(weight: PrimitiveWeight) -> Result<SegWeight, ()> {
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<GeometryWeight> for SegWeight {}
impl SegWeightTrait<PrimitiveWeight> 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<GeometryWeight> for FixedSegWeight {}
impl SegWeightTrait<PrimitiveWeight> 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<GeometryWeight> for LoneLooseSegWeight {}
impl SegWeightTrait<PrimitiveWeight> 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<GeometryWeight> for SeqLooseSegWeight {}
impl SegWeightTrait<PrimitiveWeight> for SeqLooseSegWeight {}
impl GetWidth for SeqLooseSegWeight {
fn width(&self) -> f64 {

View File

@ -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<GeometryIndex> for Segbend {
fn interior(&self) -> Vec<GeometryIndex> {
impl GetInterior<PrimitiveIndex> for Segbend {
fn interior(&self) -> Vec<PrimitiveIndex> {
vec![self.bend.into(), self.dot.into(), self.seg.into()]
}
}

View File

@ -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<PW, XW> {
pub enum Compound<PW, XW> {
Primitive(PW),
Grouping(XW),
}
@ -75,9 +76,8 @@ pub struct Geometry<
DI: GetNodeIndex + Into<PI> + Copy,
SI: GetNodeIndex + Into<PI> + Copy,
BI: GetNodeIndex + Into<PI> + Copy,
GI: GetNodeIndex + Copy,
> {
graph: StableDiGraph<CompoundWeight<PW, GW>, GeometryLabel, usize>,
graph: StableDiGraph<Compound<PW, GW>, GeometryLabel, usize>,
weight_marker: PhantomData<PW>,
dot_weight_marker: PhantomData<DW>,
seg_weight_marker: PhantomData<SW>,
@ -87,7 +87,6 @@ pub struct Geometry<
dot_index_marker: PhantomData<DI>,
seg_index_marker: PhantomData<SI>,
bend_index_marker: PhantomData<BI>,
grouping_index_marker: PhantomData<GI>,
}
impl<
@ -100,8 +99,7 @@ impl<
DI: GetNodeIndex + Into<PI> + Copy,
SI: GetNodeIndex + Into<PI> + Copy,
BI: GetNodeIndex + Into<PI> + Copy,
GI: GetNodeIndex + Copy,
> Geometry<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI>
> Geometry<PW, DW, SW, BW, GW, PI, DI, SI, BI>
{
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<W: DotWeightTrait<PW>>(&mut self, weight: W) -> GenericIndex<W> {
GenericIndex::<W>::new(
self.graph
.add_node(CompoundWeight::Primitive(weight.into())),
)
GenericIndex::<W>::new(self.graph.add_node(Compound::Primitive(weight.into())))
}
pub fn add_seg<W: SegWeightTrait<PW>>(
@ -132,10 +126,7 @@ impl<
to: DI,
weight: W,
) -> GenericIndex<W> {
let seg = GenericIndex::<W>::new(
self.graph
.add_node(CompoundWeight::Primitive(weight.into())),
);
let seg = GenericIndex::<W>::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<W> {
let bend = GenericIndex::<W>::new(
self.graph
.add_node(CompoundWeight::Primitive(weight.into())),
);
let bend = GenericIndex::<W>::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<GW> {
GenericIndex::<GW>::new(self.graph.add_node(Compound::Grouping(weight)))
}
pub fn assign_to_grouping<W>(
&mut self,
primitive: GenericIndex<W>,
grouping: GenericIndex<GW>,
) {
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<GW>) {
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<usize>) -> 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<CompoundWeight<PW, GW>, GeometryLabel, usize> {
pub fn graph(&self) -> &StableDiGraph<Compound<PW, GW>, GeometryLabel, usize> {
&self.graph
}
}

View File

@ -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<GI> = GeomWithData<Bbox, GI>;
type BboxedIndex<I> = GeomWithData<Bbox, I>;
#[derive(Debug)]
pub struct GeometryWithRtree<
@ -48,10 +46,9 @@ pub struct GeometryWithRtree<
DI: GetNodeIndex + Into<PI> + Copy,
SI: GetNodeIndex + Into<PI> + Copy,
BI: GetNodeIndex + Into<PI> + Copy,
GI: GetNodeIndex + Copy,
> {
geometry: Geometry<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI>,
rtree: RTree<BboxedIndex<PI>>,
geometry: Geometry<PW, DW, SW, BW, GW, PI, DI, SI, BI>,
rtree: RTree<BboxedIndex<Compound<PI, GenericIndex<GW>>>>,
layer_count: u64,
weight_marker: PhantomData<PW>,
dot_weight_marker: PhantomData<DW>,
@ -75,12 +72,11 @@ impl<
DI: GetNodeIndex + Into<PI> + Copy,
SI: GetNodeIndex + Into<PI> + Copy,
BI: GetNodeIndex + Into<PI> + Copy,
GI: GetNodeIndex + Copy,
> GeometryWithRtree<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI>
> GeometryWithRtree<PW, DW, SW, BW, GW, PI, DI, SI, BI>
{
pub fn new(layer_count: u64) -> Self {
Self {
geometry: Geometry::<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI>::new(),
geometry: Geometry::<PW, DW, SW, BW, GW, PI, DI, SI, BI>::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<GW> {
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<W>(
&mut self,
primitive: GenericIndex<W>,
grouping: GenericIndex<GW>,
) {
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<GW>) {
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<PI> + Copy,
SI: GetNodeIndex + Into<PI> + Copy,
BI: GetNodeIndex + Into<PI> + Copy,
GI: GetNodeIndex + Copy,
> GeometryWithRtree<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI>
> GeometryWithRtree<PW, DW, SW, BW, GW, PI, DI, SI, BI>
{
fn make_dot_bbox(&self, dot: DI) -> BboxedIndex<PI> {
fn make_dot_bbox(&self, dot: DI) -> BboxedIndex<Compound<PI, GenericIndex<GW>>> {
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<PI> {
fn make_seg_bbox(&self, seg: SI) -> BboxedIndex<Compound<PI, GenericIndex<GW>>> {
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<PI> {
fn make_bend_bbox(&self, bend: BI) -> BboxedIndex<Compound<PI, GenericIndex<GW>>> {
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<GW>,
) -> BboxedIndex<Compound<PI, GenericIndex<GW>>> {
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<PW, DW, SW, BW, GW, PI, DI, SI, BI, GI> {
pub fn geometry(&self) -> &Geometry<PW, DW, SW, BW, GW, PI, DI, SI, BI> {
&self.geometry
}
pub fn rtree(&self) -> &RTree<BboxedIndex<PI>> {
pub fn rtree(&self) -> &RTree<BboxedIndex<Compound<PI, GenericIndex<GW>>>> {
&self.rtree
}
pub fn graph(&self) -> &StableDiGraph<CompoundWeight<PW, GW>, GeometryLabel, usize> {
pub fn graph(&self) -> &StableDiGraph<Compound<PW, GW>, 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))

View File

@ -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<VertexIndex> for GeometryIndex {
impl From<VertexIndex> 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<impl RulesTrait>) -> 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

View File

@ -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>, 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();

View File

@ -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<WraparoundableIndex> for GeometryIndex {
impl From<WraparoundableIndex> 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),
}
}
}