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; }