Skip to content
Snippets Groups Projects
Select Git revision
  • 0c97e389031781f33cc2a0b69ca88c714887743d
  • master default protected
2 results

RandomRectangleGenerator.java

Blame
  • 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));
        }
    
    }