1use std::collections::{BTreeMap, HashMap};
11
12use kurbo::{Rect as KRect, Vec2};
13
14use crate::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 start: f64,
46 pub across: f64,
48 pub gap: f64,
50 pub line: f64,
52 pub cut: Option<KRect>,
54 pub(super) items: Sums<OrderKey, Placed>,
55 pub(super) spaces: HashMap<OrderKey, SpaceIndex>,
56 pub(super) overhang: Counted,
59 pub(super) reach_across: (Counted, Counted),
60 pub(super) cover_across: (Counted, Counted),
61 pub(super) entry: Option<KRect>,
63 pub(super) cover: Option<KRect>,
64}
65
66#[derive(Default)]
69pub struct SpaceIndex {
70 pub(super) index: rstar::RTree<Entry>,
71 pub(super) covers: Extent,
72}
73
74#[derive(Clone, Debug, PartialEq)]
78pub struct Placed {
79 pub size: f64,
80 pub gap: f64,
81 pub across: f64,
83 pub delta: Vec2,
86 pub(super) reach: Option<(f64, f64)>,
87 pub(super) covered: Option<(f64, f64)>,
88 pub(super) counted: Counts,
90}
91
92#[derive(Clone, Debug, PartialEq, Default)]
94pub struct Counts {
95 overhang: Option<f64>,
96 reach: Option<(f64, f64)>,
97 cover: Option<(f64, f64)>,
98}
99
100impl Placed {
101 pub fn new(size: f64, gap: f64, across: f64, delta: Vec2) -> Placed {
102 Placed {
103 size,
104 gap,
105 across,
106 delta,
107 reach: None,
108 covered: None,
109 counted: Counts::default(),
110 }
111 }
112}
113
114#[derive(Clone, Debug)]
118pub struct Span {
119 pub n: usize,
120 pub length: f64,
121 pub reach: (f64, f64),
122 pub covered: (f64, f64),
123}
124
125impl Default for Span {
126 fn default() -> Self {
127 Span {
128 n: 0,
129 length: 0.0,
130 reach: (f64::INFINITY, f64::NEG_INFINITY),
131 covered: (f64::INFINITY, f64::NEG_INFINITY),
132 }
133 }
134}
135
136impl Summary for Span {
137 fn then(&self, next: &Self) -> Self {
138 let shift = |(lo, hi): (f64, f64), (nlo, nhi): (f64, f64)| {
139 (lo.min(self.length + nlo), hi.max(self.length + nhi))
140 };
141 Span {
142 n: self.n + next.n,
143 length: self.length + next.length,
144 reach: shift(self.reach, next.reach),
145 covered: shift(self.covered, next.covered),
146 }
147 }
148}
149
150impl Item for Placed {
151 type Sum = Span;
152 fn summary(&self) -> Span {
153 let none = (f64::INFINITY, f64::NEG_INFINITY);
154 Span {
155 n: 1,
156 length: self.size + self.gap,
157 reach: self.reach.unwrap_or(none),
158 covered: self.covered.unwrap_or(none),
159 }
160 }
161}
162
163#[derive(Default)]
165pub struct Counted(BTreeMap<i64, usize>);
166
167impl Counted {
168 pub(super) fn add(&mut self, v: f64) {
169 *self.0.entry(key(v)).or_default() += 1;
170 }
171 pub(super) fn remove(&mut self, v: f64) {
172 let k = key(v);
173 if let Some(n) = self.0.get_mut(&k) {
174 *n -= 1;
175 if *n == 0 {
176 self.0.remove(&k);
177 }
178 }
179 }
180 pub(super) fn least(&self) -> Option<f64> {
181 self.0.keys().next().map(|k| *k as f64 / 1e6)
182 }
183 pub(super) fn greatest(&self) -> Option<f64> {
184 self.0.keys().next_back().map(|k| *k as f64 / 1e6)
185 }
186}
187
188fn spans(row: bool, r: KRect) -> ((f64, f64), (f64, f64)) {
190 if row {
191 ((r.x0, r.x1), (r.y0, r.y1))
192 } else {
193 ((r.y0, r.y1), (r.x0, r.x1))
194 }
195}
196
197fn rect(row: bool, along: (f64, f64), across: (f64, f64)) -> KRect {
198 if row {
199 KRect::new(along.0, across.0, along.1, across.1)
200 } else {
201 KRect::new(across.0, along.0, across.1, along.1)
202 }
203}
204
205impl Run {
206 pub fn new(space: Space) -> Run {
207 Run {
208 space,
209 raw: Vec2::ZERO,
210 at: Vec2::ZERO,
211 origin: Vec2::ZERO,
212 row: false,
213 start: 0.0,
214 across: 0.0,
215 gap: 0.0,
216 line: 0.0,
217 cut: None,
218 items: Sums::new(),
219 spaces: HashMap::new(),
220 overhang: Counted::default(),
221 reach_across: Default::default(),
222 cover_across: Default::default(),
223 entry: None,
224 cover: None,
225 }
226 }
227
228 pub fn len(&self) -> usize {
229 self.items.len()
230 }
231
232 pub fn is_empty(&self) -> bool {
233 self.items.is_empty()
234 }
235
236 pub fn place(&self, before: f64, across: f64) -> (Vec2, Vec2) {
240 let along = (self.start + before) as f32;
243 let across = (self.across + across) as f32;
244 let (dx, dy) = if self.row {
245 (along, across)
246 } else {
247 (across, along)
248 };
249 let o = self.origin;
250 let (rx, ry) = ((o.x + self.raw.x) as f32, (o.y + self.raw.y) as f32);
251 let raw = (rx + dx, ry + dy);
252 let snap32 = |v: f32| (v + 0.5).floor();
253 let at = (
254 (o.x + self.at.x) as f32 + snap32(raw.0) - snap32(rx),
255 (o.y + self.at.y) as f32 + snap32(raw.1) - snap32(ry),
256 );
257 (
258 Vec2::new(raw.0 as f64 - o.x, raw.1 as f64 - o.y),
259 Vec2::new(at.0 as f64 - o.x, at.1 as f64 - o.y),
260 )
261 }
262
263 pub fn child(&self, key: &OrderKey) -> Option<(f64, &Placed)> {
266 let placed = self.items.get(key)?;
267 Some((self.items.before(key).length, placed))
268 }
269
270 pub fn prefix(&self, key: &OrderKey) -> f64 {
272 self.items.before(key).length
273 }
274
275 pub fn keys_after(&self, key: &OrderKey) -> Vec<OrderKey> {
277 self.items
278 .from(key)
279 .filter(|(k, _)| *k != key)
280 .map(|(k, _)| k.clone())
281 .collect()
282 }
283
284 pub fn entry(&self) -> Option<KRect> {
286 self.entry
287 }
288
289 pub fn child_at(&self, key: &OrderKey) -> Option<Vec2> {
291 let (before, p) = self.child(key)?;
292 Some(self.place(before, p.across).1)
293 }
294
295 pub fn children(&self) -> impl Iterator<Item = (&OrderKey, f64, &Placed)> {
297 let mut before = 0.0;
298 self.items.iter().map(move |(k, p)| {
299 let b = before;
300 before += p.size + p.gap;
301 (k, b, p)
302 })
303 }
304
305 pub(super) fn touching(&self, r: KRect) -> Vec<(&OrderKey, Vec2)> {
310 self.touching_rounded(r)
311 .into_iter()
312 .map(|(k, at, _)| (k, at))
313 .collect()
314 }
315
316 pub(super) fn touching_rounded(&self, r: KRect) -> Vec<(&OrderKey, Vec2, bool)> {
322 let ((a0, a1), _) = spans(self.row, r);
323 let base = if self.row { self.raw.x } else { self.raw.y } + self.start;
324 let over = self.overhang.greatest().unwrap_or(0.0).max(0.0);
325 let (from, to) = (a0 - base - over, a1 - base + over);
326 let Some((first, _, before)) = self.items.seek(|s| s.length - s_gap(s, self.gap) >= from)
327 else {
328 return Vec::new();
329 };
330 let mut out = Vec::new();
331 let mut at = before.length;
332 for (k, p) in self.items.from(first) {
333 if at > to {
334 break;
335 }
336 let (raw, rounded) = self.place(at, p.across);
337 let fresh = ((rounded - raw) - p.delta).hypot() < 1e-3;
338 out.push((k, rounded, fresh));
339 at += p.size + p.gap;
340 }
341 out
342 }
343
344 pub(super) fn extents(&self) -> (Option<KRect>, Option<KRect>) {
347 let total = self.items.total();
348 let base = if self.row { self.raw.x } else { self.raw.y } + self.start;
349 let across = if self.row { self.raw.y } else { self.raw.x } + self.across;
350 let make = |along: (f64, f64), lo: &Counted, hi: &Counted| {
351 let (Some(c0), Some(c1)) = (lo.least(), hi.greatest()) else {
352 return None;
353 };
354 if along.0.partial_cmp(&along.1) == Some(std::cmp::Ordering::Greater)
355 || along.0.is_nan()
356 {
357 return None;
358 }
359 Some(rect(
360 self.row,
361 (base + along.0, base + along.1),
362 (across + c0, across + c1),
363 ))
364 };
365 let reach = make(total.reach, &self.reach_across.0, &self.reach_across.1);
366 let cover = make(total.covered, &self.cover_across.0, &self.cover_across.1)
367 .and_then(|r| super::chunk::cut_to(r, self.cut));
368 (reach, cover)
369 }
370
371 pub(super) fn set(&mut self, key: OrderKey, mut placed: Placed) {
374 self.unset(&key);
375 let local = self.spaces.entry(key.clone()).or_default();
376 let reach = local.index.root().envelope();
377 let reach = (reach.lower()[0] <= reach.upper()[0]).then(|| {
378 KRect::new(
379 reach.lower()[0],
380 reach.lower()[1],
381 reach.upper()[0],
382 reach.upper()[1],
383 )
384 });
385 let covered = local.covers.rect();
386 let d = if self.row {
387 (placed.delta.x, placed.delta.y)
388 } else {
389 (placed.delta.y, placed.delta.x)
390 };
391 let along = |r: KRect| {
392 let ((a0, a1), _) = spans(self.row, r);
393 (a0 + d.0, a1 + d.0)
394 };
395 let across = |r: KRect| {
396 let (_, (c0, c1)) = spans(self.row, r);
397 (placed.across + d.1 + c0, placed.across + d.1 + c1)
398 };
399 placed.reach = reach.map(along);
400 placed.covered = covered.map(along);
401 placed.counted = Counts::default();
402 if let Some(r) = reach {
403 let (lo, hi) = along(r);
404 let o = (-lo).max(hi - placed.size).max(0.0);
405 self.overhang.add(o);
406 let c = across(r);
407 self.reach_across.0.add(c.0);
408 self.reach_across.1.add(c.1);
409 placed.counted.overhang = Some(o);
410 placed.counted.reach = Some(c);
411 }
412 if let Some(r) = covered {
413 let c = across(r);
414 self.cover_across.0.add(c.0);
415 self.cover_across.1.add(c.1);
416 placed.counted.cover = Some(c);
417 }
418 self.items.insert(key, placed);
419 }
420
421 pub(super) fn unset(&mut self, key: &OrderKey) -> Option<Placed> {
424 let p = self.items.remove(key)?;
425 if let Some(o) = p.counted.overhang {
426 self.overhang.remove(o);
427 }
428 if let Some((c0, c1)) = p.counted.reach {
429 self.reach_across.0.remove(c0);
430 self.reach_across.1.remove(c1);
431 }
432 if let Some((c0, c1)) = p.counted.cover {
433 self.cover_across.0.remove(c0);
434 self.cover_across.1.remove(c1);
435 }
436 Some(p)
437 }
438}
439
440fn s_gap(s: &Span, gap: f64) -> f64 {
442 if s.n == 0 { 0.0 } else { gap }
443}