    001    package ifs.example.rpp;
    002
    003    import ifs.model.*;
    004    import ifs.util.*;
    005    import java.util.*;
    006
    007    /**
    008     * Resource constraint (rectangular area where the rectangles are to be placed). It prohibits overlapping of the placed rectangles.
    009     *
    010     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
    011     * @version 1.0
    012     */
    013    public class ResourceConstraint extends Constraint {
    014        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ResourceConstraint.class);
    015        private Variable[][] iResource;
    016        private int iWidth, iHeight;
    017
    018        /**
    019         * Constructor.
    020         * @param width area width
    021         * @param height area height
    022         */
    023        public ResourceConstraint(int width, int height) {
    024            super();
    025            iWidth = width;
    026            iHeight = height;
    027            iResource = new Variable[width][height];
    028            for (int x = 0; x < width; x++)
    029                for (int y = 0; y < height; y++)
    030                    iResource[x][y] = null;
    031        }
    032
    033        /**
    034         * Compute conflicts with the given placement of the rectangle.
    035         * This means the rectangles which are already placed and which are overlapping with the given assignment.
    036         */
    037        public void computeConflicts(Value value, Set conflicts) {
    038            Rectangle rectangle = (Rectangle)value.variable();
    039            Location placement = (Location)value;
    040            for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
    041                for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++)
    042                    if (iResource[x][y] != null)
    043                        conflicts.add(iResource[x][y].getAssignment());
    044        }
    045
    046        /**
    047         * Returns true if there is a rectangle which overlaps with the given assignment.
    048         */
    049        public boolean inConflict(Value value) {
    050            Rectangle rectangle = (Rectangle)value.variable();
    051            Location placement = (Location)value;
    052            for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
    053                for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++)
    054                    if (iResource[x][y] != null)
    055                        return true;
    056            return false;
    057        }
    058
    059        /**
    060         * Returns true if the given rectangles (assignments) do not overlap.
    061         */
    062        public boolean isConsistent(Value value1, Value value2) {
    063            Rectangle r1 = (Rectangle)value1.variable();
    064            Location p1 = (Location)value1;
    065            Rectangle r2 = (Rectangle)value2.variable();
    066            Location p2 = (Location)value2;
    067            if (p2.getX() + r2.getWidth() <= p1.getX()) return true;
    068            if (p2.getX() >= p1.getX() + r1.getWidth()) return true;
    069            if (p2.getY() + r2.getHeight() <= p1.getY()) return true;
    070            if (p2.getY() >= p1.getY() + r1.getHeight()) return true;
    071            return false;
    072        }
    073
    074        /**
    075         * Notification, when a rectangle is placed.
    076         * It memorizes the rectangle's new position in 2D ([0..width][0..height]) array.
    077         * It is used for faster lookup when computing conflicts.
    078         */
    079        public void assigned(long iteration, Value value) {
    080            super.assigned(iteration, value);
    081            Rectangle rectangle = (Rectangle)value.variable();
    082            Location placement = (Location)value;
    083            for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
    084                for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
    085                    iResource[x][y] = value.variable();
    086                }
    087        }
    088
    089        /**
    090         * Notification, when a rectangle is unplaced.
    091         * It removes the rectangle from the 2D ([0..width][0..height]) array.
    092         */
    093        public void unassigned(long iteration, Value value) {
    094            super.unassigned(iteration, value);
    095            Rectangle rectangle = (Rectangle)value.variable();
    096            Location placement = (Location)value;
    097            for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
    098                for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
    099                    iResource[x][y] = null;
    100                }
    101        }
    102
    103        public void check() {
    104            sLogger.debug("check");
    105            for (Enumeration e=variables().elements();e.hasMoreElements();) {
    106                Rectangle rectangle = (Rectangle)e.nextElement();
    107                Location placement = (Location)rectangle.getAssignment();
    108                if (placement==null) {
    109                    sLogger.warn("Rectangle "+rectangle.getName()+" is not assigned.");
    110                    continue;
    111                }
    112                sLogger.debug("Checking "+rectangle.getName()+"    (assigned:"+placement.getName()+", prohibited:"+rectangle.isProhibited(placement.getX(),placement.getY())+", initial:"+rectangle.getInitialAssignment()+", prohibited:["+rectangle.getProhibitedX()+","+rectangle.getProhibitedY()+"])");
    113                if (placement.getX()==rectangle.getProhibitedX() || placement.getY()==rectangle.getProhibitedY())
    114                    sLogger.error("Placement is prohibited.");
    115                if (placement.getX()<rectangle.getMinX() || placement.getX()>rectangle.getMaxX() ||
    116                    placement.getY()<rectangle.getMinY() || placement.getY()>rectangle.getMaxY())
    117                    sLogger.error("Placement is outside bounds.");
    118                for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
    119                    for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
    120                            if (iResource[x][y]==null || !iResource[x][y].equals(rectangle))
    121                                sLogger.error("Problem at ["+x+","+y+"], "+iResource[x][y]+" is assigned there.");
    122                    }
    123            }
    124            sLogger.debug(toString());
    125        }
    126
    127        /**
    128         * String representation of the constraint (for debugging and printing purposes).
    129         */
    130        public String toString() {
    131            StringBuffer sb = new StringBuffer("ResourceConstraint{\n        ");
    132            for (int y = 0; y < iHeight; y++) {
    133                for (int x = 0; x < iWidth; x++) {
    134                    sb.append(ToolBox.trim( iResource[x][y] == null ? "" : ((Rectangle)iResource[x][y]).getName().substring(4), 4));
    135                }
    136                sb.append("\n        ");
    137            }
    138            sb.append("\n      }");
    139            return sb.toString();
    140        }
    141    }