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 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);
AABB::from_corners(
[envelope.lower()[0], envelope.lower()[1], 0.0],

View File

@ -21,9 +21,9 @@ pub struct Bbox {
}
impl Bbox {
pub fn new(shape: &Shape) -> Bbox {
pub fn new(shape: &Shape, layer: u64) -> Bbox {
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
GenericIndex<W>: Into<GI>,
{
@ -100,13 +100,19 @@ impl<
&self
.geometry
.dot_shape(dot.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
),
dot.into(),
));
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
GenericIndex<W>: Into<GI>,
{
@ -116,13 +122,14 @@ impl<
&self
.geometry
.seg_shape(seg.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
),
seg.into(),
));
seg
}
pub fn add_bend<W: BendWeightTrait<GW>>(
pub fn add_bend<W: BendWeightTrait<GW> + GetLayer>(
&mut self,
from: DI,
to: DI,
@ -138,6 +145,7 @@ impl<
&self
.geometry
.bend_shape(bend.into().try_into().unwrap_or_else(|_| unreachable!())),
weight.layer(),
),
bend.into(),
));
@ -248,15 +256,24 @@ impl<
> GeometryWithRtree<GW, DW, SW, BW, GI, DI, SI, BI>
{
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> {
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> {
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 {
@ -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> {
&self.geometry
}
@ -287,10 +316,11 @@ impl<
!self.rtree.iter().any(|wrapper| {
let node = wrapper.data;
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
.rtree
.locate_in_envelope(&shape.flat_envelope_3d(0.0, 2))
.locate_in_envelope(&shape.envelope_3d(0.0, layer))
.any(|w| *w == wrapper)
})
}

View File

@ -5,6 +5,7 @@ use geo::Point;
use rstar::RTreeObject;
use thiserror::Error;
use super::graph::GetLayer;
use super::loose::{GetNextLoose, Loose, LooseIndex};
use super::rules::RulesTrait;
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_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,
weight: W,
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_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>>(
fn add_seg_infringably<W: SegWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: 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_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>>(
fn add_core_bend_infringably<W: BendWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
@ -723,7 +724,7 @@ impl<R: RulesTrait> Layout<R> {
self.geometry_with_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| !except.contains(&wrapper.data))
.filter(|wrapper| {
@ -749,7 +750,7 @@ impl<R: RulesTrait> Layout<R> {
self.geometry_with_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| shape.intersects(&wrapper.data.primitive(self).shape()))
.map(|wrapper| wrapper.data)