Select Git revision
RandomRectangleGenerator.java
RandomRectangleGenerator.java 3.85 KiB
package danyfel80.randomcrops;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import icy.roi.ROI2D;
import plugins.kernel.roi.roi2d.ROI2DRectangle;
public class RandomRectangleGenerator implements Callable<List<ROI2DRectangle>>
{
public static class Builder
{
private Dimension rectangleSize;
private int rectangleCount;
private List<ROI2D> limitingRois;
public Builder(Dimension rectangleSize, int rectangleCount, List<ROI2D> limitingRois)
{
Objects.requireNonNull(rectangleSize);
Objects.requireNonNull(limitingRois);
if (limitingRois.isEmpty())
throw new IllegalArgumentException("limitingRois is empty. At least one roi is needed");
this.rectangleSize = rectangleSize;
this.rectangleCount = rectangleCount;
this.limitingRois = limitingRois;
}
public RandomRectangleGenerator build()
{
RandomRectangleGenerator generator = new RandomRectangleGenerator();
generator.rectangleSize = rectangleSize;
generator.rectangleCount = rectangleCount;
generator.limitingRois = limitingRois;
return generator;
}
}
private Random randomValueGenerator;
private Dimension rectangleSize;
private int rectangleCount;
private List<ROI2D> limitingRois;
private RandomRectangleGenerator()
{
randomValueGenerator = new Random();
}
@Override
public List<ROI2DRectangle> call() throws Exception
{
computeValueBoundary();
if (valueBoundary.getWidth() < rectangleSize.width || valueBoundary.getHeight() < rectangleSize.height)
throw new IllegalArgumentException("Rectangle");
List<ROI2DRectangle> rectangles = new ArrayList<>(rectangleCount);
for (int count = 0; count < rectangleCount; count++)
{
if (Thread.interrupted())
throw new InterruptedException();
rectangles.add(getValidRandomRectangle());
}
return rectangles;
}
private Rectangle2D valueBoundary;
private Supplier<Integer> xGenerator;
private Supplier<Integer> yGenerator;
private void computeValueBoundary()
{
Rectangle2D seedBounds = limitingRois.get(0).getBounds2D();
valueBoundary = new Rectangle2D.Double(seedBounds.getX(), seedBounds.getY(), seedBounds.getWidth(),
seedBounds.getHeight());
limitingRois.stream().map(ROI2D::getBounds2D)
.forEach(rect2d -> Rectangle2D.union(valueBoundary, rect2d, valueBoundary));
int minX = (int) Math.floor(valueBoundary.getMinX());
int maxX = (int) Math.floor(valueBoundary.getMaxX());
int xLength = maxX - minX;
xGenerator = () -> minX + randomValueGenerator.nextInt(xLength);
int minY = (int) Math.floor(valueBoundary.getMinY());
int maxY = (int) Math.floor(valueBoundary.getMaxY());
int yLength = maxY - minY;
yGenerator = () -> minY + randomValueGenerator.nextInt(yLength);
}
private ROI2DRectangle getValidRandomRectangle() throws InterruptedException
{
Rectangle rect = new Rectangle(rectangleSize);
do
{
if (Thread.interrupted())
throw new InterruptedException();
rect.x = xGenerator.get();
rect.y = yGenerator.get();
}
while (!isValidRectangle(rect));
return new ROI2DRectangle(rect);
}
private boolean isValidRectangle(Rectangle rect)
{
return limitingRois.stream().anyMatch(roi -> roi.getBounds2D().contains(rect) && roi.contains(rect));
}
}