Skip to content

Commit 7db87ac

Browse files
committed
fix: guard flowchart label deoverlap refinement
1 parent 7705fbd commit 7db87ac

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

src/layout/label_placement.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ const FLOWCHART_LABEL_SOFT_GAP: f32 = 6.0;
1919
type Rect = (f32, f32, f32, f32);
2020
type EdgeObstacle = (usize, Rect);
2121

22+
#[derive(Clone, Copy, Debug)]
23+
struct CenterLabelOverlapScore {
24+
count: usize,
25+
total: f32,
26+
max: f32,
27+
}
28+
29+
impl CenterLabelOverlapScore {
30+
fn improved_by(self, other: Self) -> bool {
31+
self.count < other.count
32+
|| (self.count == other.count && self.max + 0.1 < other.max)
33+
|| (self.count == other.count
34+
&& (self.max - other.max).abs() <= 0.1
35+
&& self.total + 0.1 < other.total)
36+
}
37+
}
38+
2239
#[derive(Clone)]
2340
struct FlowchartCenterLabelEntry {
2441
edge_idx: usize,
@@ -661,9 +678,62 @@ fn resolve_center_labels(
661678
);
662679
if kind == DiagramKind::Flowchart {
663680
nudge_flowchart_labels_clear_of_own_paths(edges, bounds);
681+
let before_score = center_label_overlap_score(edges, label_pad_x, label_pad_y);
682+
let mut candidate_edges = edges.to_vec();
683+
deoverlap_flowchart_center_labels(
684+
&mut candidate_edges,
685+
nodes,
686+
subgraphs,
687+
bounds,
688+
theme,
689+
label_pad_x,
690+
label_pad_y,
691+
&fixed_center_indices,
692+
);
693+
let after_score = center_label_overlap_score(&candidate_edges, label_pad_x, label_pad_y);
694+
if after_score.improved_by(before_score) {
695+
edges.clone_from_slice(&candidate_edges);
696+
}
664697
}
665698
}
666699

700+
fn center_label_overlap_score(
701+
edges: &[EdgeLayout],
702+
label_pad_x: f32,
703+
label_pad_y: f32,
704+
) -> CenterLabelOverlapScore {
705+
let rects: Vec<Rect> = edges
706+
.iter()
707+
.filter_map(|edge| {
708+
let label = edge.label.as_ref()?;
709+
let center = edge.label_anchor?;
710+
Some(flowchart_center_label_rect(
711+
center,
712+
label.width,
713+
label.height,
714+
label_pad_x,
715+
label_pad_y,
716+
))
717+
})
718+
.collect();
719+
720+
let mut count = 0usize;
721+
let mut total = 0.0f32;
722+
let mut max = 0.0f32;
723+
for i in 0..rects.len() {
724+
for j in (i + 1)..rects.len() {
725+
let overlap = overlap_area(&rects[i], &rects[j]);
726+
if overlap > LABEL_OVERLAP_WIDE_THRESHOLD {
727+
count += 1;
728+
total += overlap;
729+
max = max.max(overlap);
730+
}
731+
}
732+
}
733+
734+
CenterLabelOverlapScore { count, total, max }
735+
}
736+
667737
fn label_core_rect(center: (f32, f32), label: &TextBlock) -> Rect {
668738
(
669739
center.0 - label.width / 2.0,

0 commit comments

Comments
 (0)