geometry: make shape bboxes occupy only one layer instead of all

This commit is contained in:
Mikolaj Wielgus 2024-03-14 19:17:38 +00:00
parent cf01cdaea5
commit 5a0ea94a87
3 changed files with 55 additions and 16 deletions

View File

@ -14,7 +14,15 @@ pub trait ShapeTrait {
fn width(&self) -> f64; fn width(&self) -> f64;
fn length(&self) -> f64; fn length(&self) -> f64;
fn flat_envelope_3d(&self, margin: f64, layer_count: u64) -> AABB<[f64; 3]> { fn envelope_3d(&self, margin: f64, layer: u64) -> AABB<[f64; 3]> {
let envelope = self.envelope(margin);
AABB::from_corners(
[envelope.lower()[0], envelope.lower()[1], layer as f64],
[envelope.upper()[0], envelope.upper()[1], layer as f64],
)
}
fn full_height_envelope_3d(&self, margin: f64, layer_count: u64) -> AABB<[f64; 3]> {
let envelope = self.envelope(margin); let envelope = self.envelope(margin);
AABB::from_corners( AABB::from_corners(
[envelope.lower()[0], envelope.lower()[1], 0.0], [envelope.lower()[0], envelope.lower()[1], 0.0],

View File

@ -21,9 +21,9 @@ pub struct Bbox {
} }
impl Bbox { impl Bbox {
pub fn new(shape: &Shape) -> Bbox { pub fn new(shape: &Shape, layer: u64) -> Bbox {
Self { Self {
aabb: shape.flat_envelope_3d(0.0, 2), aabb: shape.envelope_3d(0.0, layer),
} }
} }
} }
@ -90,7 +90,7 @@ impl<
} }
} }
pub fn add_dot<W: DotWeightTrait<GW>>(&mut self, weight: W) -> GenericIndex<W> pub fn add_dot<W: DotWeightTrait<GW> + GetLayer>(&mut self, weight: W) -> GenericIndex<W>
where where
GenericIndex<W>: Into<GI>, GenericIndex<W>: Into<GI>,
{ {
@ -100,13 +100,19 @@ impl<
&self &self
.geometry .geometry
.dot_shape(dot.into().try_into().unwrap_or_else(|_| unreachable!())), .dot_shape(dot.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
), ),
dot.into(), dot.into(),
)); ));
dot dot
} }
pub fn add_seg<W: SegWeightTrait<GW>>(&mut self, from: DI, to: DI, weight: W) -> GenericIndex<W> pub fn add_seg<W: SegWeightTrait<GW> + GetLayer>(
&mut self,
from: DI,
to: DI,
weight: W,
) -> GenericIndex<W>
where where
GenericIndex<W>: Into<GI>, GenericIndex<W>: Into<GI>,
{ {
@ -116,13 +122,14 @@ impl<
&self &self
.geometry .geometry
.seg_shape(seg.into().try_into().unwrap_or_else(|_| unreachable!())), .seg_shape(seg.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
), ),
seg.into(), seg.into(),
)); ));
seg seg
} }
pub fn add_bend<W: BendWeightTrait<GW>>( pub fn add_bend<W: BendWeightTrait<GW> + GetLayer>(
&mut self, &mut self,
from: DI, from: DI,
to: DI, to: DI,
@ -138,6 +145,7 @@ impl<
&self &self
.geometry .geometry
.bend_shape(bend.into().try_into().unwrap_or_else(|_| unreachable!())), .bend_shape(bend.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
), ),
bend.into(), bend.into(),
)); ));
@ -248,15 +256,24 @@ impl<
> GeometryWithRtree<GW, DW, SW, BW, GI, DI, SI, BI> > GeometryWithRtree<GW, DW, SW, BW, GI, DI, SI, BI>
{ {
fn make_dot_bbox(&self, dot: DI) -> BboxedIndex<GI> { fn make_dot_bbox(&self, dot: DI) -> BboxedIndex<GI> {
BboxedIndex::new(Bbox::new(&self.geometry.dot_shape(dot)), dot.into()) BboxedIndex::new(
Bbox::new(&self.geometry.dot_shape(dot), self.layer(dot.into())),
dot.into(),
)
} }
fn make_seg_bbox(&self, seg: SI) -> BboxedIndex<GI> { fn make_seg_bbox(&self, seg: SI) -> BboxedIndex<GI> {
BboxedIndex::new(Bbox::new(&self.geometry.seg_shape(seg)), seg.into()) BboxedIndex::new(
Bbox::new(&self.geometry.seg_shape(seg), self.layer(seg.into())),
seg.into(),
)
} }
fn make_bend_bbox(&self, bend: BI) -> BboxedIndex<GI> { fn make_bend_bbox(&self, bend: BI) -> BboxedIndex<GI> {
BboxedIndex::new(Bbox::new(&self.geometry.bend_shape(bend)), bend.into()) BboxedIndex::new(
Bbox::new(&self.geometry.bend_shape(bend), self.layer(bend.into())),
bend.into(),
)
} }
fn shape(&self, index: GI) -> Shape { fn shape(&self, index: GI) -> Shape {
@ -271,6 +288,18 @@ impl<
} }
} }
fn layer(&self, index: GI) -> u64 {
if let Ok(dot) = <GI as TryInto<DI>>::try_into(index) {
self.geometry.dot_weight(dot).layer()
} else if let Ok(seg) = <GI as TryInto<SI>>::try_into(index) {
self.geometry.seg_weight(seg).layer()
} else if let Ok(bend) = <GI as TryInto<BI>>::try_into(index) {
self.geometry.bend_weight(bend).layer()
} else {
unreachable!();
}
}
pub fn geometry(&self) -> &Geometry<GW, DW, SW, BW, GI, DI, SI, BI> { pub fn geometry(&self) -> &Geometry<GW, DW, SW, BW, GI, DI, SI, BI> {
&self.geometry &self.geometry
} }
@ -287,10 +316,11 @@ impl<
!self.rtree.iter().any(|wrapper| { !self.rtree.iter().any(|wrapper| {
let node = wrapper.data; let node = wrapper.data;
let shape = self.shape(node); let shape = self.shape(node);
let wrapper = BboxedIndex::new(Bbox::new(&shape), node); let layer = self.layer(node);
let wrapper = BboxedIndex::new(Bbox::new(&shape, layer), node);
!self !self
.rtree .rtree
.locate_in_envelope(&shape.flat_envelope_3d(0.0, 2)) .locate_in_envelope(&shape.envelope_3d(0.0, layer))
.any(|w| *w == wrapper) .any(|w| *w == wrapper)
}) })
} }

View File

@ -5,6 +5,7 @@ use geo::Point;
use rstar::RTreeObject; use rstar::RTreeObject;
use thiserror::Error; use thiserror::Error;
use super::graph::GetLayer;
use super::loose::{GetNextLoose, Loose, LooseIndex}; use super::loose::{GetNextLoose, Loose, LooseIndex};
use super::rules::RulesTrait; use super::rules::RulesTrait;
use super::segbend::Segbend; use super::segbend::Segbend;
@ -175,7 +176,7 @@ impl<R: RulesTrait> Layout<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_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()))] #[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>>( fn add_dot_infringably<W: DotWeightTrait<GeometryWeight> + GetLayer>(
&mut self, &mut self,
weight: W, weight: W,
infringables: &[GeometryIndex], infringables: &[GeometryIndex],
@ -469,7 +470,7 @@ impl<R: RulesTrait> Layout<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_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().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()))] #[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>>( fn add_seg_infringably<W: SegWeightTrait<GeometryWeight> + GetLayer>(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
@ -527,7 +528,7 @@ impl<R: RulesTrait> Layout<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_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_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()))] #[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>>( fn add_core_bend_infringably<W: BendWeightTrait<GeometryWeight> + GetLayer>(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
@ -723,7 +724,7 @@ impl<R: RulesTrait> Layout<R> {
self.geometry_with_rtree self.geometry_with_rtree
.rtree() .rtree()
.locate_in_envelope_intersecting(&limiting_shape.flat_envelope_3d(0.0, 2)) .locate_in_envelope_intersecting(&limiting_shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| !self.are_connectable(node, wrapper.data)) .filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| !except.contains(&wrapper.data)) .filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| { .filter(|wrapper| {
@ -749,7 +750,7 @@ impl<R: RulesTrait> Layout<R> {
self.geometry_with_rtree self.geometry_with_rtree
.rtree() .rtree()
.locate_in_envelope_intersecting(&shape.flat_envelope_3d(0.0, 2)) .locate_in_envelope_intersecting(&shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| !self.are_connectable(node, wrapper.data)) .filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| shape.intersects(&wrapper.data.primitive(self).shape())) .filter(|wrapper| shape.intersects(&wrapper.data.primitive(self).shape()))
.map(|wrapper| wrapper.data) .map(|wrapper| wrapper.data)