List of usage examples for java.awt Shape equals
public boolean equals(Object obj)
From source file:com.joliciel.jochre.graphics.RowOfShapesImpl.java
@Override public int getShapeIndex(Shape shape) { int i = 0;// w ww . j ava2 s .co m for (Shape oneShape : this.getShapes()) { if (oneShape.equals(shape)) { return i; } i++; } return -1; }
From source file:com.joliciel.jochre.graphics.RowOfShapesImpl.java
@Override public Shape findNearestShape(int xCoordinate) { Shape nearestShape = null; int smallestDistance = -1; for (Shape shape : this.getShapes()) { if (shape.getLeft() <= xCoordinate && xCoordinate <= shape.getRight()) { nearestShape = shape;/* w w w.java 2s.c om*/ break; } if (nearestShape == null || Math.abs(xCoordinate - shape.getLeft()) <= smallestDistance) { smallestDistance = Math.abs(xCoordinate - shape.getLeft()); nearestShape = shape; } if (Math.abs(xCoordinate - shape.getRight()) <= smallestDistance) { smallestDistance = Math.abs(xCoordinate - shape.getRight()); nearestShape = shape; } if (!nearestShape.equals(shape)) { // as soon as we start getting farther away from the x-coordinate, we can break out break; } } return nearestShape; }
From source file:com.joliciel.jochre.graphics.SegmenterImpl.java
List<RowOfShapes> groupShapesIntoRows(SourceImage sourceImage, List<Shape> shapes, List<Rectangle> whiteAreas,
boolean useSlope) {
LOG.debug("########## groupShapesIntoRows #########");
LOG.debug("useSlope? " + useSlope);
List<RowOfShapes> rows = new ArrayList<RowOfShapes>();
for (Shape shape : shapes)
shape.setRow(null);/* ww w.j av a2 s .c o m*/
List<Shape> shapesToRemove = new ArrayList<Shape>();
for (Shape shape : shapes) {
for (Rectangle whiteArea : whiteAreas) {
double whiteAreaRight = whiteArea.getRight();
double whiteAreaLeft = whiteArea.getLeft();
if (useSlope) {
double xAdjustment = sourceImage.getXAdjustment(shape.getTop());
whiteAreaRight += xAdjustment;
whiteAreaLeft += xAdjustment;
}
if (whiteAreaRight > shape.getRight() && whiteAreaLeft < shape.getLeft()
&& whiteArea.getTop() < shape.getTop() && whiteArea.getBottom() > shape.getBottom()) {
// shape is surrounded
shapesToRemove.add(shape);
LOG.debug("Removing shape " + shape);
LOG.debug("Surrounded by white area: " + whiteArea);
}
}
}
shapes.removeAll(shapesToRemove);
// calculate the means
// get average shape width & height
DescriptiveStatistics shapeWidthStats = new DescriptiveStatistics();
for (Shape shape : shapes) {
shapeWidthStats.addValue(shape.getWidth());
}
double averageShapeWidth = shapeWidthStats.getPercentile(50);
LOG.debug("averageShapeWidth: " + averageShapeWidth);
// now, arrange the shapes in rows
// we're guaranteed that no two shapes overlap at this point.
// Now, it's possible that two shapes in the same line have no vertical overlap (e.g. a comma and an apostrophe)
// so we have to go searching a bit further afield, say five shapes in each direction
// but if we go too far, we may end up joining two lines together if the page isn't quite straight
// let's begin with any old shape and find the shapes closest to it horizontally
// e.g. up to 8 horizontal means to the right and left
// as we find shapes that go with it, we add them to the same line
int i = 0;
int j = 0;
int numberOfMeanWidthsForSearch = 8;
LOG.debug("numberOfMeanWidthsForSearch: " + numberOfMeanWidthsForSearch);
LOG.debug("search distance: " + averageShapeWidth * numberOfMeanWidthsForSearch);
for (Shape shape : shapes) {
if (shape.getRow() == null) {
RowOfShapes row = graphicsService.getEmptyRow(sourceImage);
row.addShape(shape);
row.setIndex(j++);
rows.add(row);
LOG.trace("========= New row " + row.getIndex() + "============");
LOG.trace("Adding " + shape + " to row " + row.getIndex());
}
int searchLeft = (int) ((double) shape.getLeft() - (numberOfMeanWidthsForSearch * averageShapeWidth));
int searchRight = (int) ((double) shape.getRight() + (numberOfMeanWidthsForSearch * averageShapeWidth));
LOG.trace("Shape " + i++ + ": " + shape + "(row " + shape.getRow().getIndex() + ")");
LOG.trace("searchLeft: " + searchLeft);
LOG.trace("searchRight: " + searchRight);
// construct an array to represent where white areas overlap with the search area
int[][] leftSearchArea = new int[shape.getLeft() - searchLeft][2];
int[][] rightSearchArea = new int[searchRight - shape.getRight()][2];
for (int k = 0; k < leftSearchArea.length; k++) {
leftSearchArea[k][0] = shape.getTop();
leftSearchArea[k][1] = shape.getBottom();
}
for (int k = 0; k < rightSearchArea.length; k++) {
rightSearchArea[k][0] = shape.getTop();
rightSearchArea[k][1] = shape.getBottom();
}
int newSearchLeft = searchLeft;
int newSearchRight = searchRight;
for (Rectangle whiteArea : whiteAreas) {
double whiteAreaRight = whiteArea.getRight();
double whiteAreaLeft = whiteArea.getLeft();
if (useSlope) {
double xAdjustment = sourceImage.getXAdjustment(shape.getTop());
whiteAreaRight += xAdjustment;
whiteAreaLeft += xAdjustment;
LOG.trace(whiteArea + ", xAdjustment=" + xAdjustment + " , whiteAreaLeft=" + whiteAreaLeft
+ " , whiteAreaRight=" + whiteAreaRight);
}
if (whiteAreaRight > newSearchLeft && whiteAreaLeft < shape.getLeft()
&& whiteArea.getTop() <= shape.getBottom() && whiteArea.getBottom() >= shape.getTop()) {
LOG.trace("overlap on left with: " + whiteArea.toString());
if (whiteArea.getTop() <= shape.getTop() && whiteArea.getBottom() >= shape.getBottom()
&& whiteAreaRight > newSearchLeft) {
newSearchLeft = (int) Math.round(whiteAreaRight);
LOG.trace("Complete, newSearchLeft = " + newSearchLeft);
} else {
LOG.trace("Partial, starting at " + whiteArea.getRight());
for (int k = whiteArea.getRight() - searchLeft; k >= 0; k--) {
if (k < leftSearchArea.length) {
if (whiteArea.getBottom() < shape.getBottom()
&& leftSearchArea[k][0] < whiteArea.getBottom())
leftSearchArea[k][0] = whiteArea.getBottom() + 1;
else if (whiteArea.getTop() > shape.getTop()
&& leftSearchArea[k][1] > whiteArea.getTop())
leftSearchArea[k][1] = whiteArea.getTop() - 1;
if (leftSearchArea[k][0] >= leftSearchArea[k][1]
&& searchLeft + k > newSearchLeft) {
newSearchLeft = searchLeft + k;
LOG.trace("Complete from " + newSearchLeft);
break;
}
}
}
// if (LOG.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// for (int k=0;k<leftSearchArea.length;k++) {
// String top = "" + (leftSearchArea[k][0]-shape.getTop());
// sb.append(String.format("%1$#" + 3 + "s", top)+ ",");
// }
// LOG.trace(sb.toString());
// sb = new StringBuilder();
// for (int k=0;k<leftSearchArea.length;k++) {
// String bottom = "" + (leftSearchArea[k][1]-shape.getTop());
// sb.append(String.format("%1$#" + 3 + "s", bottom)+ ",");
// }
// LOG.trace(sb.toString());
// }
}
} else if (whiteAreaLeft < newSearchRight && whiteAreaRight > shape.getRight()
&& whiteArea.getTop() <= shape.getBottom() && whiteArea.getBottom() >= shape.getTop()) {
LOG.trace("overlap on right with: " + whiteArea.toString());
if (whiteArea.getTop() <= shape.getTop() && whiteArea.getBottom() >= shape.getBottom()
&& newSearchRight > whiteAreaLeft) {
newSearchRight = (int) Math.round(whiteAreaLeft);
LOG.trace("Complete, newSearchRight = " + newSearchRight);
} else {
LOG.trace("Partial, starting at " + whiteArea.getLeft());
for (int k = whiteArea.getLeft() - shape.getRight(); k < rightSearchArea.length; k++) {
if (k > 0 && k < leftSearchArea.length && k < rightSearchArea.length) {
if (whiteArea.getBottom() < shape.getBottom()
&& leftSearchArea[k][0] < whiteArea.getBottom())
rightSearchArea[k][0] = whiteArea.getBottom() + 1;
else if (whiteArea.getTop() > shape.getTop()
&& leftSearchArea[k][1] > whiteArea.getTop())
rightSearchArea[k][1] = whiteArea.getTop() - 1;
if (rightSearchArea[k][0] >= rightSearchArea[k][1]
&& newSearchRight > shape.getRight() + k) {
newSearchRight = shape.getRight() + k;
LOG.trace("Complete from " + newSearchRight);
break;
}
}
}
// if (LOG.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// for (int k=0;k<rightSearchArea.length;k++) {
// String top = "" + (rightSearchArea[k][0]-shape.getTop());
// sb.append(String.format("%1$#" + 3 + "s", top)+ ",");
// }
// LOG.trace(sb.toString());
// sb = new StringBuilder();
// for (int k=0;k<rightSearchArea.length;k++) {
// String bottom = "" + (rightSearchArea[k][1]-shape.getTop());
// sb.append(String.format("%1$#" + 3 + "s", bottom)+ ",");
// }
// LOG.trace(sb.toString());
// }
}
}
}
LOG.trace("searchLeft adjusted for white columns: " + newSearchLeft);
LOG.trace("searchRight adjusted for white columns: " + newSearchRight);
// min 10% overlap to assume same row
double minOverlap = 0.10;
for (Shape otherShape : shapes) {
boolean haveSomeOverlap = false;
if (!shape.getRow().equals(otherShape.getRow()) && !otherShape.equals(shape)) {
// shapes are arranged from the top down
if (otherShape.getTop() > shape.getBottom()) {
break;
}
if (otherShape.getRight() > newSearchLeft && otherShape.getRight() < shape.getLeft()
&& otherShape.getTop() <= shape.getBottom()
&& otherShape.getBottom() >= shape.getTop()) {
int k = otherShape.getRight() - searchLeft;
if (otherShape.getTop() <= leftSearchArea[k][1]
&& otherShape.getBottom() >= leftSearchArea[k][0])
haveSomeOverlap = true;
} else if (otherShape.getLeft() < newSearchRight && otherShape.getLeft() > shape.getRight()
&& otherShape.getTop() <= shape.getBottom()
&& otherShape.getBottom() >= shape.getTop()) {
int k = otherShape.getLeft() - shape.getRight();
if (otherShape.getTop() <= rightSearchArea[k][1]
&& otherShape.getBottom() >= rightSearchArea[k][0])
haveSomeOverlap = true;
}
if (haveSomeOverlap) {
int overlap1 = shape.getBottom() - otherShape.getTop() + 1;
int overlap2 = otherShape.getBottom() - shape.getTop() + 1;
int overlap = overlap1 < overlap2 ? overlap1 : overlap2;
boolean addShapeToRow = false;
if ((((double) overlap / (double) shape.getHeight()) > minOverlap)
|| (((double) overlap / (double) otherShape.getHeight()) > minOverlap)) {
addShapeToRow = true;
}
if (addShapeToRow) {
LOG.debug("Adding " + otherShape + " to row " + shape.getRow().getIndex());
if (otherShape.getRow() == null) {
shape.getRow().addShape(otherShape);
} else {
// two rows need to be merged
LOG.debug("========= Merge rows " + shape.getRow().getIndex() + " with "
+ otherShape.getRow().getIndex() + "==========");
RowOfShapes otherRow = otherShape.getRow();
shape.getRow().addShapes(otherRow.getShapes());
rows.remove(otherRow);
}
}
} // add shape to row ?
} // should shape be considered?
} // next other shape
} // next shape
return rows;
}