1use std::collections::{BTreeMap, HashMap};
11
12use kurbo::{Rect as KRect, Vec2};
13
14use crate::prefix_sums::{Item, Summary, Sums};
15use crate::tree::OrderKey;
16
17use super::*;
18
19pub type RunId = u32;
21
22#[derive(Clone, Debug, PartialEq, Eq, Hash)]
25pub enum Space {
26 Root,
27 Item(RunId, OrderKey),
28}
29
30pub struct Run {
32 pub space: Space,
34 pub raw: Vec2,
36 pub at: Vec2,
37 pub origin: Vec2,
41 pub row: bool,
43 pub free: bool,
46 pub(super) boxes: rstar::RTree<Boxed>,
47 pub(super) free_reach: [Counted; 4],
48 pub(super) free_cover: [Counted; 4],
49 pub start: f64,
52 pub across: f64,
54 pub gap: f64,
58 pub line: f64,
60 pub cut: Option<KRect>,
62 pub(super) items: Sums<OrderKey, Placed>,
63 pub(super) spaces: HashMap<OrderKey, SpaceIndex>,
64 pub(super) overhang: Counted,
67 pub(super) reach_across: (Counted, Counted),
68 pub(super) cover_across: (Counted, Counted),
69 pub(super) entry: Option<KRect>,
71 pub(super) cover: Option<KRect>,
72}
73
74#[derive(Default)]
77pub struct SpaceIndex {
78 pub(super) index: rstar::RTree<Entry>,
79 pub(super) covers: Extent,
80}
81
82#[derive(Clone, Debug, PartialEq)]
86pub struct Placed {
87 pub size: f64,
88 pub at: Option<Vec2>,
90 pub(super) boxed: Option<KRect>,
92 pub(super) cover_box: Option<KRect>,
93 pub across: f64,
95 pub delta: Vec2,
98 pub(super) reach: Option<(f64, f64)>,
99 pub(super) covered: Option<(f64, f64)>,
100 pub(super) counted: Counts,
102}
103
104#[derive(Clone, Debug, PartialEq, Default)]
106pub struct Counts {
107 overhang: Option<f64>,
108 reach: Option<(f64, f64)>,
109 cover: Option<(f64, f64)>,
110}
111
112impl Placed {
113 pub fn at(at: Vec2, delta: Vec2) -> Placed {
115 Placed {
116 at: Some(at),
117 ..Placed::new(0.0, 0.0, delta)
118 }
119 }
120
121 pub fn new(size: f64, across: f64, delta: Vec2) -> Placed {
122 Placed {
123 at: None,
124 boxed: None,
125 cover_box: None,
126 size,
127 across,
128 delta,
129 reach: None,
130 covered: None,
131 counted: Counts::default(),
132 }
133 }
134}
135
136#[derive(Clone, Debug, Default)]
139pub struct Span {
140 pub n: usize,
141 pub length: f64,
142}
143
144impl Summary for Span {
145 fn then(&self, next: &Self) -> Self {
146 Span {
147 n: self.n + next.n,
148 length: self.length + next.length,
149 }
150 }
151}
152
153impl Item for Placed {
154 type Sum = Span;
155 fn summary(&self) -> Span {
156 Span {
157 n: 1,
158 length: self.size,
159 }
160 }
161}
162
163#[derive(Clone, Debug, PartialEq)]
165pub(super) struct Boxed {
166 pub(super) key: OrderKey,
167 pub(super) bounds: KRect,
168}
169
170impl rstar::RTreeObject for Boxed {
171 type Envelope = rstar::AABB<[f64; 2]>;
172 fn envelope(&self) -> Self::Envelope {
173 rstar::AABB::from_corners(
174 [self.bounds.x0, self.bounds.y0],
175 [self.bounds.x1, self.bounds.y1],
176 )
177 }
178}
179
180#[derive(Default)]
182pub struct Counted(BTreeMap<i64, usize>);
183
184impl Counted {
185 pub(super) fn add(&mut self, v: f64) {
186 *self.0.entry(key(v)).or_default() += 1;
187 }
188 pub(super) fn remove(&mut self, v: f64) {
189 let k = key(v);
190 if let Some(n) = self.0.get_mut(&k) {
191 *n -= 1;
192 if *n == 0 {
193 self.0.remove(&k);
194 }
195 }
196 }
197 pub(super) fn least(&self) -> Option<f64> {
198 self.0.keys().next().map(|k| *k as f64 / 1e6)
199 }
200 pub(super) fn greatest(&self) -> Option<f64> {
201 self.0.keys().next_back().map(|k| *k as f64 / 1e6)
202 }
203}
204
205fn spans(row: bool, r: KRect) -> ((f64, f64), (f64, f64)) {
207 if row {
208 ((r.x0, r.x1), (r.y0, r.y1))
209 } else {
210 ((r.y0, r.y1), (r.x0, r.x1))
211 }
212}
213
214fn rect(row: bool, along: (f64, f64), across: (f64, f64)) -> KRect {
215 if row {
216 KRect::new(along.0, across.0, along.1, across.1)
217 } else {
218 KRect::new(across.0, along.0, across.1, along.1)
219 }
220}
221
222impl Run {
223 pub fn new(space: Space) -> Run {
224 Run {
225 space,
226 raw: Vec2::ZERO,
227 at: Vec2::ZERO,
228 origin: Vec2::ZERO,
229 row: false,
230 free: false,
231 boxes: rstar::RTree::new(),
232 free_reach: Default::default(),
233 free_cover: Default::default(),
234 start: 0.0,
235 across: 0.0,
236 gap: 0.0,
237 line: 0.0,
238 cut: None,
239 items: Sums::new(),
240 spaces: HashMap::new(),
241 overhang: Counted::default(),
242 reach_across: Default::default(),
243 cover_across: Default::default(),
244 entry: None,
245 cover: None,
246 }
247 }
248
249 pub fn len(&self) -> usize {
250 self.items.len()
251 }
252
253 pub fn is_empty(&self) -> bool {
254 self.items.is_empty()
255 }
256
257 pub fn place_at(&self, at: Vec2) -> (Vec2, Vec2) {
264 let o = self.origin;
265 let (rx, ry) = ((o.x + self.raw.x) as f32, (o.y + self.raw.y) as f32);
266 let raw = (rx + at.x as f32, ry + at.y as f32);
267 let snap32 = |v: f32| (v + 0.5).floor();
268 let rounded = (
269 (o.x + self.at.x) as f32 + snap32(raw.0) - snap32(rx),
270 (o.y + self.at.y) as f32 + snap32(raw.1) - snap32(ry),
271 );
272 (
273 Vec2::new(raw.0 as f64 - o.x, raw.1 as f64 - o.y),
274 Vec2::new(rounded.0 as f64 - o.x, rounded.1 as f64 - o.y),
275 )
276 }
277
278 pub fn place(&self, before: f64, across: f64) -> (Vec2, Vec2) {
279 let along = (self.start + before) as f32;
282 let across = (self.across + across) as f32;
283 let (dx, dy) = if self.row {
284 (along, across)
285 } else {
286 (across, along)
287 };
288 let o = self.origin;
289 let (rx, ry) = ((o.x + self.raw.x) as f32, (o.y + self.raw.y) as f32);
290 let raw = (rx + dx, ry + dy);
291 let snap32 = |v: f32| (v + 0.5).floor();
292 let at = (
293 (o.x + self.at.x) as f32 + snap32(raw.0) - snap32(rx),
294 (o.y + self.at.y) as f32 + snap32(raw.1) - snap32(ry),
295 );
296 (
297 Vec2::new(raw.0 as f64 - o.x, raw.1 as f64 - o.y),
298 Vec2::new(at.0 as f64 - o.x, at.1 as f64 - o.y),
299 )
300 }
301
302 pub fn child(&self, key: &OrderKey) -> Option<(f64, &Placed)> {
305 let placed = self.items.get(key)?;
306 Some((self.prefix(key), placed))
307 }
308
309 pub fn prefix(&self, key: &OrderKey) -> f64 {
312 let s = self.items.before(key);
313 s.length + s.n as f64 * self.gap
314 }
315
316 pub fn keys_after(&self, key: &OrderKey) -> Vec<OrderKey> {
318 self.items
319 .from(key)
320 .filter(|(k, _)| *k != key)
321 .map(|(k, _)| k.clone())
322 .collect()
323 }
324
325 pub fn entry(&self) -> Option<KRect> {
327 self.entry
328 }
329
330 pub fn child_at(&self, key: &OrderKey) -> Option<Vec2> {
332 if self.free {
333 let p = self.items.get(key)?;
334 return Some(self.place_at(p.at.unwrap_or(Vec2::ZERO)).1);
335 }
336 let (before, p) = self.child(key)?;
337 Some(self.place(before, p.across).1)
338 }
339
340 pub fn children(&self) -> impl Iterator<Item = (&OrderKey, f64, &Placed)> {
342 let mut before = 0.0;
343 let gap = self.gap;
344 self.items.iter().map(move |(k, p)| {
345 let b = before;
346 before += p.size + gap;
347 (k, b, p)
348 })
349 }
350
351 pub(super) fn touching(&self, r: KRect) -> Vec<(&OrderKey, Vec2)> {
356 self.touching_rounded(r)
357 .into_iter()
358 .map(|(k, at, _)| (k, at))
359 .collect()
360 }
361
362 pub(super) fn touching_rounded(&self, r: KRect) -> Vec<(&OrderKey, Vec2, bool)> {
368 if self.free {
369 let env = rstar::AABB::from_corners([r.x0, r.y0], [r.x1, r.y1]);
370 let mut found: Vec<&Boxed> = self.boxes.locate_in_envelope_intersecting(&env).collect();
371 found.sort_by(|a, b| a.key.cmp(&b.key));
372 return found
373 .into_iter()
374 .filter_map(|b| {
375 let (k, p) = (&b.key, self.items.get(&b.key)?);
376 let (raw, rounded) = self.place_at(p.at.unwrap_or(Vec2::ZERO));
377 let fresh = ((rounded - raw) - p.delta).hypot() < 1e-3;
378 Some((k, rounded, fresh))
379 })
380 .collect();
381 }
382 let ((a0, a1), _) = spans(self.row, r);
383 let base = if self.row { self.raw.x } else { self.raw.y } + self.start;
384 let over = self.overhang.greatest().unwrap_or(0.0).max(0.0);
385 let (from, to) = (a0 - base - over, a1 - base + over);
386 let gap = self.gap;
387 let Some((first, _, before)) = self
388 .items
389 .seek(|s| s.length + s.n.saturating_sub(1) as f64 * gap >= from)
390 else {
391 return Vec::new();
392 };
393 let mut out = Vec::new();
394 let mut at = before.length + before.n as f64 * gap;
395 for (k, p) in self.items.from(first) {
396 if at > to {
397 break;
398 }
399 let (raw, rounded) = self.place(at, p.across);
400 let fresh = ((rounded - raw) - p.delta).hypot() < 1e-3;
401 out.push((k, rounded, fresh));
402 at += p.size + gap;
403 }
404 out
405 }
406
407 pub(super) fn extents(&self) -> (Option<KRect>, Option<KRect>) {
413 if self.free {
414 let make = |c: &[Counted; 4]| {
415 let (Some(x0), Some(y0), Some(x1), Some(y1)) =
416 (c[0].least(), c[1].least(), c[2].greatest(), c[3].greatest())
417 else {
418 return None;
419 };
420 Some(KRect::new(x0, y0, x1, y1) + self.raw)
421 };
422 let cover = make(&self.free_cover).and_then(|r| super::chunk::cut_to(r, self.cut));
423 return (make(&self.free_reach), cover);
424 }
425 let base = if self.row { self.raw.x } else { self.raw.y } + self.start;
426 let across = if self.row { self.raw.y } else { self.raw.x } + self.across;
427 let over = self.overhang.greatest().unwrap_or(0.0).max(0.0);
428 let along = |of: fn(&Placed) -> Option<(f64, f64)>| -> Option<(f64, f64)> {
429 let gap = self.gap;
430 let mut lo = f64::INFINITY;
431 let mut at = 0.0;
432 for (_, p) in self.items.iter() {
433 if at - over > lo {
434 break;
435 }
436 if let Some((l, _)) = of(p) {
437 lo = lo.min(at + l);
438 }
439 at += p.size + gap;
440 }
441 let total = self.items.total();
442 let mut hi = f64::NEG_INFINITY;
443 let mut end = total.length + total.n.saturating_sub(1) as f64 * gap;
444 for (_, p) in self.items.rev() {
445 let start = end - p.size;
446 if end + over < hi {
447 break;
448 }
449 if let Some((_, h)) = of(p) {
450 hi = hi.max(start + h);
451 }
452 end = start - gap;
453 }
454 (lo <= hi).then_some((lo, hi))
455 };
456 let make = |along: Option<(f64, f64)>, lo: &Counted, hi: &Counted| {
457 let along = along?;
458 let (Some(c0), Some(c1)) = (lo.least(), hi.greatest()) else {
459 return None;
460 };
461 Some(rect(
462 self.row,
463 (base + along.0, base + along.1),
464 (across + c0, across + c1),
465 ))
466 };
467 let reach = make(
468 along(|p| p.reach),
469 &self.reach_across.0,
470 &self.reach_across.1,
471 );
472 let cover = make(
473 along(|p| p.covered),
474 &self.cover_across.0,
475 &self.cover_across.1,
476 )
477 .and_then(|r| super::chunk::cut_to(r, self.cut));
478 (reach, cover)
479 }
480
481 pub(super) fn set(&mut self, key: OrderKey, mut placed: Placed) {
484 self.unset(&key);
485 if self.free {
486 let local = self.spaces.entry(key.clone()).or_default();
487 let env = local.index.root().envelope();
488 let reach = (env.lower()[0] <= env.upper()[0]).then(|| {
489 KRect::new(
490 env.lower()[0],
491 env.lower()[1],
492 env.upper()[0],
493 env.upper()[1],
494 )
495 });
496 let covered = local.covers.rect();
497 let at = placed.at.unwrap_or(Vec2::ZERO) + placed.delta;
500 placed.boxed = reach.map(|r| r + at);
501 placed.cover_box = covered.map(|r| r + at);
502 if let Some(b) = placed.boxed {
503 self.boxes.insert(Boxed {
504 key: key.clone(),
505 bounds: b,
506 });
507 for (c, v) in self.free_reach.iter_mut().zip([b.x0, b.y0, b.x1, b.y1]) {
508 c.add(v);
509 }
510 }
511 if let Some(b) = placed.cover_box {
512 for (c, v) in self.free_cover.iter_mut().zip([b.x0, b.y0, b.x1, b.y1]) {
513 c.add(v);
514 }
515 }
516 self.items.insert(key, placed);
517 return;
518 }
519 let local = self.spaces.entry(key.clone()).or_default();
520 let reach = local.index.root().envelope();
521 let reach = (reach.lower()[0] <= reach.upper()[0]).then(|| {
522 KRect::new(
523 reach.lower()[0],
524 reach.lower()[1],
525 reach.upper()[0],
526 reach.upper()[1],
527 )
528 });
529 let covered = local.covers.rect();
530 let d = if self.row {
531 (placed.delta.x, placed.delta.y)
532 } else {
533 (placed.delta.y, placed.delta.x)
534 };
535 let along = |r: KRect| {
536 let ((a0, a1), _) = spans(self.row, r);
537 (a0 + d.0, a1 + d.0)
538 };
539 let across = |r: KRect| {
540 let (_, (c0, c1)) = spans(self.row, r);
541 (placed.across + d.1 + c0, placed.across + d.1 + c1)
542 };
543 placed.reach = reach.map(along);
544 placed.covered = covered.map(along);
545 placed.counted = Counts::default();
546 if let Some(r) = reach {
547 let (lo, hi) = along(r);
548 let o = (-lo).max(hi - placed.size).max(0.0);
549 self.overhang.add(o);
550 let c = across(r);
551 self.reach_across.0.add(c.0);
552 self.reach_across.1.add(c.1);
553 placed.counted.overhang = Some(o);
554 placed.counted.reach = Some(c);
555 }
556 if let Some(r) = covered {
557 let c = across(r);
558 self.cover_across.0.add(c.0);
559 self.cover_across.1.add(c.1);
560 placed.counted.cover = Some(c);
561 }
562 self.items.insert(key, placed);
563 }
564
565 pub(super) fn unset(&mut self, key: &OrderKey) -> Option<Placed> {
568 let p = self.items.remove(key)?;
569 if let Some(b) = p.boxed {
570 self.boxes.remove(&Boxed {
571 key: key.clone(),
572 bounds: b,
573 });
574 for (c, v) in self.free_reach.iter_mut().zip([b.x0, b.y0, b.x1, b.y1]) {
575 c.remove(v);
576 }
577 }
578 if let Some(b) = p.cover_box {
579 for (c, v) in self.free_cover.iter_mut().zip([b.x0, b.y0, b.x1, b.y1]) {
580 c.remove(v);
581 }
582 }
583 if let Some(o) = p.counted.overhang {
584 self.overhang.remove(o);
585 }
586 if let Some((c0, c1)) = p.counted.reach {
587 self.reach_across.0.remove(c0);
588 self.reach_across.1.remove(c1);
589 }
590 if let Some((c0, c1)) = p.counted.cover {
591 self.cover_across.0.remove(c0);
592 self.cover_across.1.remove(c1);
593 }
594 Some(p)
595 }
596}