UNPKG

mindee

Version:

Mindee Client Library for Node.js

131 lines (130 loc) 5.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomLines = exports.CustomLine = void 0; exports.getLineItems = getLineItems; const handler_1 = require("../../errors/handler"); const errors_1 = require("../../errors"); const geometry_1 = require("../../geometry"); const listField_1 = require("./listField"); class CustomLine { constructor(rowNumber) { this.rowNumber = rowNumber; this.bbox = new geometry_1.BBox(1, 1, 0, 0); this.fields = new Map(); } /** * Extends the current bbox of the line with the bbox. */ extendWithBbox(bbox) { this.bbox = (0, geometry_1.mergeBbox)(this.bbox, bbox); } /** * Extends the current bbox of the line with the polygon. */ extendWith(polygon) { this.bbox = (0, geometry_1.mergeBbox)(this.bbox, (0, geometry_1.getBbox)(polygon)); } updateField(name, fieldValue) { if (!this.fields.has(name)) { this.fields.set(name, fieldValue); } else { const existingField = this.fields.get(name); if (existingField === undefined) { handler_1.errorHandler.throw(new errors_1.MindeeError(`The field '${name}' should exist but was not found.`)); return; } const mergedContent = existingField?.content === undefined ? fieldValue.content : existingField.content + " " + fieldValue.content; const mergedBbox = (0, geometry_1.getBBoxForPolygons)([ existingField.polygon, fieldValue.polygon, ]); this.fields.set(name, new listField_1.ListFieldValue({ content: mergedContent, confidence: existingField.confidence * fieldValue.confidence, polygon: (0, geometry_1.getBoundingBoxFromBBox)(mergedBbox), })); } } } exports.CustomLine = CustomLine; class CustomLines extends Array { } exports.CustomLines = CustomLines; /** * Get line items from fields. */ function getLineItems(anchorNames, fieldNames, fields, heightLineTolerance) { const fieldsToTransformIntoLines = new Map([...fields].filter(([k]) => fieldNames.includes(k))); const anchorName = findBestAnchor(anchorNames, fieldsToTransformIntoLines); const linesPrepared = prepare(anchorName, fieldsToTransformIntoLines, heightLineTolerance); linesPrepared.forEach((currentLine) => { fieldsToTransformIntoLines.forEach((field, fieldName) => { field.values.forEach((listFieldValue) => { const minMaxY = (0, geometry_1.getMinMaxY)(listFieldValue.polygon); if (Math.abs(minMaxY.max - currentLine.bbox.yMax) <= heightLineTolerance && Math.abs(minMaxY.min - currentLine.bbox.yMin) <= heightLineTolerance) { currentLine.updateField(fieldName, listFieldValue); } }); }); }); return linesPrepared; } /** * Loop through the possible anchor fields and find the one with the most values. */ function findBestAnchor(possibleAnchorNames, fields) { let anchorName = ""; let anchorRows = 0; possibleAnchorNames.forEach((fieldName) => { const fieldValues = fields.get(fieldName)?.values; if (fieldValues !== undefined && fieldValues.length > anchorRows) { anchorRows = fieldValues.length; anchorName = fieldName; } }); if (anchorName === "") { handler_1.errorHandler.throw(new errors_1.MindeeError("No anchor was found.")); } return anchorName; } /** * Check if the bbox fits inside the line. */ function isBboxInLine(line, bbox, heightTolerance) { if (Math.abs(bbox.yMin - line.bbox.yMin) <= heightTolerance) { return true; } return Math.abs(line.bbox.yMin - bbox.yMin) <= heightTolerance; } function prepare(anchorName, fields, heightLineTolerance) { const linesPrepared = []; const anchorField = fields.get(anchorName); if (anchorField === undefined || anchorField.values.length === 0) { handler_1.errorHandler.throw(new errors_1.MindeeError("No lines have been detected.")); } let currentLineNumber = 1; let currentLine = new CustomLine(currentLineNumber); if (anchorField !== undefined) { let currentValue = anchorField.values[0]; currentLine.extendWith(currentValue.polygon); for (let index = 1; index < anchorField.values.length; index++) { currentValue = anchorField.values[index]; const currentFieldBbox = (0, geometry_1.getBbox)(currentValue.polygon); if (!isBboxInLine(currentLine, currentFieldBbox, heightLineTolerance)) { linesPrepared.push(currentLine); currentLineNumber++; currentLine = new CustomLine(currentLineNumber); } currentLine.extendWithBbox(currentFieldBbox); } if (linesPrepared.filter((line) => line.rowNumber === currentLineNumber) .length === 0) { linesPrepared.push(currentLine); } } return linesPrepared; }