com.formkiq.vision.crafter.SimpleDocumentBlockMaker Maven / Gradle / Ivy
/*
* Copyright (C) 2018 FormKiQ Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formkiq.vision.crafter;
import static com.formkiq.vision.document.DocumentBlock.isEquals;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.Range;
import com.formkiq.vision.comparator.DocumentBlockRectangleComparator;
import com.formkiq.vision.document.DocumentBlock;
import com.formkiq.vision.document.DocumentBlockRectangle;
import com.formkiq.vision.predicate.DocumentBlockHorizontalLinePredicate;
/**
* Basic {@link DocumentBlock} maker. Given Horizontal / Vertical lines, make
* square boxes.
*
*/
public class SimpleDocumentBlockMaker
implements Function> {
/** {@link Collection} {@link DocumentBlock}. */
private Collection horizontal;
/** {@link Collection} {@link DocumentBlock}. */
private Collection vertical;
/**
* constructor.
* @param horizontalLines {@link Collection} {@link DocumentBlock}
* @param verticalLines {@link Collection} {@link DocumentBlock}
*/
public SimpleDocumentBlockMaker(
final Collection horizontalLines,
final Collection verticalLines) {
this.horizontal = horizontalLines;
this.vertical = verticalLines;
}
@Override
public List apply(final DocumentBlockRectangle block) {
List o = new ArrayList<>();
if (new DocumentBlockHorizontalLinePredicate().test(block)) {
List bottomBlocks = findBottomBlock(
block.getLowerLeftX(), block.getLowerLeftY(),
block.getUpperRightX(), block.getUpperRightY());
for (DocumentBlockRectangle bottom : bottomBlocks) {
Optional left = findLeftBlock(
block.getLowerLeftX(), bottom.getLowerLeftY(),
block.getUpperRightX(), block.getUpperRightY());
Optional right = findRightBlock(
block.getLowerLeftX(), bottom.getLowerLeftY(),
block.getUpperRightX(), block.getUpperRightY());
if (left.isPresent() && right.isPresent()
&& !left.get().equals(right.get())) {
o.add(new DocumentBlock(left.get().getLowerLeftX(),
bottom.getLowerLeftY(),
right.get().getUpperRightX(),
block.getUpperRightY()));
}
}
} else {
DocumentBlockRectangle left = block;
Optional top = findHorizontalLine(
Float.valueOf(left.getLowerLeftX()),
Float.valueOf(left.getUpperRightY()));
Optional bottom = findHorizontalLine(
Float.valueOf(left.getLowerLeftX()),
Float.valueOf(left.getLowerLeftY()));
if (top.isPresent() && bottom.isPresent()) {
Optional right = findVerticalLine(
Float.valueOf(top.get().getUpperRightX()),
Float.valueOf(top.get().getLowerLeftY()),
Float.valueOf(bottom.get().getUpperRightY()));
if (right.isPresent() && !left.equals(right.get())) {
o.add(new DocumentBlock(left.getLowerLeftX(),
bottom.get().getLowerLeftY(),
right.get().getUpperRightX(),
top.get().getUpperRightY()));
}
}
}
return o;
}
/**
* Find Horizontal Line.
* @param x {@link Float}
* @param y {@link Float}
* @return {@link Optional} {@link DocumentBlock}
*/
private Optional findHorizontalLine(final Float x,
final Float y) {
Optional line = this.horizontal.stream().filter(h -> {
return h.toRangeX(2).contains(x) && h.toRangeY(2).contains(y);
}).max(new DocumentBlockRectangleComparator());
return line;
}
/**
* Find Horizontal Line.
* @param x {@link Float}
* @param y0 {@link Float}
* @param y1 {@link Float}
* @return {@link Optional} {@link DocumentBlock}
*/
private Optional findVerticalLine(final Float x,
final Float y0, final Float y1) {
Optional line = this.vertical.stream().filter(v -> {
return v.toRangeX(2).contains(x) && v.toRangeY(2).contains(y0)
&& v.toRangeY(2).contains(y1);
}).max(new DocumentBlockRectangleComparator());
return line;
}
/**
* Find Left Block.
* @param lowerLeftX float
* @param lowerLeftY float
* @param upperRightX float
* @param upperRightY float
* @return {@link Optional} {@link DocumentBlockRectangle}
*/
private Optional findLeftBlock(final float lowerLeftX,
final float lowerLeftY, final float upperRightX,
final float upperRightY) {
Range yr = Range.between(Float.valueOf(lowerLeftY + 2),
Float.valueOf(upperRightY - 2));
Optional left = this.vertical.stream().filter(v -> {
return isEquals(v.getLowerLeftX(), lowerLeftX)
&& (v.toRangeY().containsRange(yr))
&& (v.toRangeY().containsRange(yr));
}).min(new DocumentBlockRectangleComparator());
return left;
}
/**
* Find Right Block.
* @param lowerLeftX float
* @param lowerLeftY float
* @param upperRightX float
* @param upperRightY float
* @return {@link Optional} {@link DocumentBlock}
*/
private Optional findRightBlock(final float lowerLeftX,
final float lowerLeftY, final float upperRightX,
final float upperRightY) {
Range yr = Range.between(Float.valueOf(lowerLeftY + 2),
Float.valueOf(upperRightY - 2));
Optional left = this.vertical.stream().filter(v -> {
return isEquals(v.getUpperRightX(), upperRightX)
&& (v.toRangeY().containsRange(yr))
&& (v.toRangeY().containsRange(yr));
}).max(new DocumentBlockRectangleComparator());
return left;
}
/**
* Find Bottom Block.
* @param lowerLeftX float
* @param lowerLeftY float
* @param upperRightX float
* @param upperRightY float
* @return {@link List} {@link DocumentBlock}
*/
private List findBottomBlock(final float lowerLeftX,
final float lowerLeftY, final float upperRightX,
final float upperRightY) {
List bottom = this.horizontal.stream()
.filter(h -> lowerLeftY > h.getUpperRightY()
&& isEquals(h.getLowerLeftX(), lowerLeftX)
&& isEquals(h.getUpperRightX(), upperRightX))
.collect(Collectors.toList());
return bottom;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy