fix(columns): Skip table detection on wide multi-column text pages
Multi-column text layouts (e.g., creditor matrices with 3 address columns) were incorrectly claimed by body-font table detection. Now runs column detection before table detection and skips tables on pages where all detected columns are wider than 150pt, letting group_into_lines handle the column-by-column reading order correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
73ade64fac
commit
d8f341bafc
+4
-4
@@ -2109,9 +2109,9 @@ fn effective_width(item: &TextItem) -> f32 {
|
||||
|
||||
/// Represents a column region on a page
|
||||
#[derive(Debug, Clone)]
|
||||
struct ColumnRegion {
|
||||
x_min: f32,
|
||||
x_max: f32,
|
||||
pub(crate) struct ColumnRegion {
|
||||
pub(crate) x_min: f32,
|
||||
pub(crate) x_max: f32,
|
||||
}
|
||||
|
||||
/// Detect column boundaries on a page using a horizontal projection profile.
|
||||
@@ -2119,7 +2119,7 @@ struct ColumnRegion {
|
||||
/// Builds an occupancy histogram across the page width and finds empty valleys
|
||||
/// (gutters) where no text exists. Validates valleys with vertical consistency
|
||||
/// checks to avoid false positives.
|
||||
fn detect_columns(items: &[TextItem], page: u32) -> Vec<ColumnRegion> {
|
||||
pub(crate) fn detect_columns(items: &[TextItem], page: u32) -> Vec<ColumnRegion> {
|
||||
const BIN_WIDTH: f32 = 2.0;
|
||||
const MIN_GUTTER_WIDTH: f32 = 8.0;
|
||||
const MIN_VERTICAL_SPAN_RATIO: f32 = 0.30;
|
||||
|
||||
@@ -190,6 +190,22 @@ pub fn to_markdown_from_items(items: Vec<TextItem>, options: MarkdownOptions) ->
|
||||
let group = page_groups.get(&page).unwrap();
|
||||
let page_items: Vec<TextItem> = group.iter().map(|(_, item)| (*item).clone()).collect();
|
||||
|
||||
// Skip table detection on pages with clear multi-column text layout.
|
||||
// Column detection in group_into_lines handles these correctly, and
|
||||
// table detection would incorrectly claim columnar text as table rows.
|
||||
// Only skip when all detected columns are wide (>150pt ~ 2 inches),
|
||||
// indicating true text columns rather than narrow table columns.
|
||||
let columns = crate::extractor::detect_columns(&page_items, page);
|
||||
if columns.len() >= 2 {
|
||||
let min_col_width = columns
|
||||
.iter()
|
||||
.map(|c| c.x_max - c.x_min)
|
||||
.fold(f32::INFINITY, f32::min);
|
||||
if min_col_width > 150.0 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let tables = detect_tables(&page_items, base_size);
|
||||
|
||||
for table in tables {
|
||||
|
||||
Reference in New Issue
Block a user