All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prerna.reactor.masterdatabase.util.Rectangles Maven / Gradle / Ivy

The newest version!
package prerna.reactor.masterdatabase.util;

import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Rectangles {

	private static final Logger classLogger = LogManager.getLogger(Rectangles.class);
	
    /**The map of rectangles holding x and y coordinates*/
    private Map rectanglesToDraw;

    /**
     * The main algorithm that attempts to declutter the rectangles.
     * 
     * @param rectanglesToFix the map of rectangles to declutter
     */
    public Map fix(Map rectanglesToFix) {
        rectanglesToDraw = new HashMap<>();

        //make copies to keep original list unaffected
        rectanglesToFix.forEach((key,rectangle) -> {
        	Rectangle2D copyRect = new Rectangle2D.Double();
            copyRect.setRect(rectangle);
            rectanglesToDraw.put(key,copyRect);
        });

        // Find the center C of the bounding box of your rectangles.
        Rectangle2D surroundRect = surroundingRect(rectanglesToDraw);
        Point center = new Point((int) surroundRect.getCenterX(), (int) surroundRect.getCenterY());
        int numIterations = 0;
        int movementFactor = 10; //ideally would be 1
        boolean hasIntersections = true;

        //keep going until there are no intersections present    
        while (hasIntersections) {
            //initialize to false within the loop.  
            hasIntersections = false;

            for(Entry rectangles: rectanglesToDraw.entrySet()) {
            	Rectangle2D rectangle = rectangles.getValue();
            	// Find all the rectangles R' that overlap R.
                List intersectingRects = findIntersections(rectangle, rectanglesToDraw);

                if (intersectingRects.size() > 0) {
                    // Define a movement vector v.
                    Point movementVector = new Point(0, 0);
                    Point centerR = new Point((int) rectangle.getCenterX(), (int) rectangle.getCenterY());

                    // For each rectangle R that overlaps another.
                    for (Rectangle2D rPrime : intersectingRects) {
                        Point centerRPrime = new Point((int) rPrime.getCenterX(), (int) rPrime.getCenterY());
                        int xTrans = (int) (centerR.getX() - centerRPrime.getX());
                        int yTrans = (int) (centerR.getY() - centerRPrime.getY());

                        // Add a vector to v proportional to the vector between the center of R and R'.
                        movementVector.translate(xTrans < 0 ? -movementFactor : movementFactor,
                                yTrans < 0 ? -movementFactor : movementFactor);
                    }

                    int xTrans = (int) (centerR.getX() - center.getX());
                    int yTrans = (int) (centerR.getY() - center.getY());

                    // Add a vector to v proportional to the vector between C and the center of R.
                    movementVector.translate(xTrans < 0 ? -movementFactor : movementFactor,
                            yTrans < 0 ? -movementFactor : movementFactor);

                    // Move R by v.
                    rectangle.setRect(rectangle.getX() + movementVector.getX(), rectangle.getY() + movementVector.getY(),
                    		rectangle.getWidth(), rectangle.getHeight());

                    // Repeat until nothing overlaps.
                    hasIntersections = true;
                }
            }

            numIterations++;
        }
        classLogger.info("Decluttering metamodel page took " + numIterations+ " iterations.");

        return rectanglesToDraw;
    }
    
    /**
     * Given a rectangle, finds the rectangles from the rectMap that intersect with it.
     * 
     * @param rect the rectangle to find intersections on
     * @param rectMap a map of all the rectangles in question
     */
    private List findIntersections(Rectangle2D rect, Map rectMap) {
        ArrayList intersections = new ArrayList();

        rectMap.forEach((key, intersectingRect) -> {
        	 if (!rect.equals(intersectingRect) && intersectingRect.intersects(rect)) {
                 intersections.add(intersectingRect);
             }
        });

        return intersections;
    }

    /**
     * Find the bounding rectangle of the list of rectangles by iterating over all
     * rectangles and finding the top left and bottom right corners
     * 
     * @param rectangles map of rectangle names and x and y coordinates
     */
    private Rectangle2D surroundingRect(Map rectangles) {
        Point topLeft = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
        Point bottomRight = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);

        rectangles.forEach((key, rectangle) -> {
        	topLeft.x = Math.min(topLeft.x, (int) rectangle.getMinX());
            topLeft.y = Math.min(topLeft.y, (int) rectangle.getMinY());
            bottomRight.x = Math.max(bottomRight.x, (int) rectangle.getMaxX());
            bottomRight.y = Math.max(bottomRight.y, (int) rectangle.getMaxY());
        });

        return new Rectangle2D.Double(topLeft.getX(), 
                                      topLeft.getY(), 
                                      bottomRight.getX() - topLeft.getX(),
                                      bottomRight.getY() - topLeft.getY());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy