(sections, panels_by_id, figures, cap_full, cap_base)
| 524 | return CAP_PREFIX_RE.sub("", cap).strip() |
| 525 | |
| 526 | def build_figures_for_sections(sections, panels_by_id, figures, cap_full, cap_base): |
| 527 | sec_name_to_idx = {norm_title(sec.get("title","")): i |
| 528 | for i, sec in enumerate(sections) |
| 529 | if norm_title(sec.get("title","")) != norm_title("Poster Title & Author")} |
| 530 | panelid_to_secidx = {} |
| 531 | for p in panels_by_id.values(): |
| 532 | pname = norm_title(p.get("section_name","")) |
| 533 | if pname in sec_name_to_idx: |
| 534 | panelid_to_secidx[p["panel_id"]] = sec_name_to_idx[pname] |
| 535 | |
| 536 | # 收集:每 section 的 panel 高度、以及该 panel 下图的“安排高度总和” |
| 537 | sec_panel_height = {} |
| 538 | sec_arranged_fig_height = {} |
| 539 | for pid, pinfo in panels_by_id.items(): |
| 540 | if pid in panelid_to_secidx: |
| 541 | sidx = panelid_to_secidx[pid] |
| 542 | sec_panel_height[sidx] = float(pinfo.get("height", 0.0) or 0.0) |
| 543 | sec_arranged_fig_height[sidx] = 0.0 |
| 544 | |
| 545 | # 初步构建 fig 列表(宽度基于 panel 宽度推得) |
| 546 | sec_figs = {i: [] for i in range(len(sections))} |
| 547 | for fg in figures: |
| 548 | pid = fg.get("panel_id") |
| 549 | if pid not in panelid_to_secidx: continue |
| 550 | sidx = panelid_to_secidx[pid] |
| 551 | pinfo = panels_by_id.get(pid, {}) |
| 552 | p_w = float(pinfo.get("width", 1.0) or 1.0) |
| 553 | f_w = float(fg.get("width", 0.0) or 0.0) |
| 554 | frac = 0.0 if p_w <= 0 else (f_w / p_w) * 0.95 |
| 555 | width_frac = max(FIG_MIN_FRAC, min(FIG_MAX_FRAC, (frac if frac > 0 else 0.6) * FIG_ENLARGE_FACTOR)) |
| 556 | fpath = fg.get("figure_path", "") |
| 557 | cap_raw = cap_full.get(fpath) or cap_base.get(os.path.basename(fpath)) or "" |
| 558 | cap = clean_caption_prefix(cap_raw) # <-- 这里清洗 |
| 559 | sec_figs[sidx].append({ |
| 560 | "src": fpath, "caption": cap, |
| 561 | "width_frac": width_frac, |
| 562 | "order_y": float(fg.get("y", 0.0) or 0.0), |
| 563 | "arranged_height": float(fg.get("height", 0.0) or 0.0) |
| 564 | }) |
| 565 | # 统计安排高度 |
| 566 | sec_arranged_fig_height[sidx] = sec_arranged_fig_height.get(sidx, 0.0) + float(fg.get("height", 0.0) or 0.0) |
| 567 | |
| 568 | for i in list(sec_figs.keys()): |
| 569 | sec_figs[i].sort(key=lambda x: x["order_y"]) |
| 570 | |
| 571 | # —— 核心:按 panel 预算收缩图像 —— # |
| 572 | for sidx, figs in sec_figs.items(): |
| 573 | if not figs: continue |
| 574 | panel_h = sec_panel_height.get(sidx, 0.0) |
| 575 | arranged_h = sec_arranged_fig_height.get(sidx, 0.0) |
| 576 | # 粗略估算正文“行数”→ 行高比例 |
| 577 | content = sections[sidx].get("content","") or "" |
| 578 | n_chars = len(content.strip().replace("\n"," ")) |
| 579 | n_lines = math.ceil(n_chars / max(1, TEXT_CHAR_PER_LINE)) |
| 580 | text_ratio = n_lines * LINE_HEIGHT_WEIGHT # 经验换算 |
| 581 | # 允许图像占比随字数减少而下降(字越多,留给图的比例越小) |
| 582 | ratio_limit = max(0.30, BASE_FIG_RATIO_LIMIT - min(0.25, 0.12 * (n_chars/600.0))) |
| 583 | # 计算当前安排下的“图占比” |
no test coverage detected