//----------------------------------------------------------------------------// // // // S y s t e m B o u n d a r y // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.sheet; import omr.util.BrokenLine; import omr.util.Navigable; import omr.util.VerticalSide; import net.jcip.annotations.NotThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.ListIterator; /** * Class {@code SystemBoundary} handles the closed boundary of a system * as a 2D area, defined by two broken lines, on north and south sides. * * @author Hervé Bitteur */ @NotThreadSafe public class SystemBoundary { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger(SystemBoundary.class); //~ Instance fields -------------------------------------------------------- // /** Related system. */ @Navigable(false) private final SystemInfo system; /** The north and south limits. */ private final EnumMap<VerticalSide, BrokenLine> limits = new EnumMap<>( VerticalSide.class); /** Containment is delegated to a Polygon, lazily created. */ private Polygon polygon; //~ Constructors ----------------------------------------------------------- // //----------------// // SystemBoundary // //----------------// /** * Creates a new SystemBoundary object with north and south borders * * @param system the related system * @param north the northern limit * @param south the southern limit */ public SystemBoundary (SystemInfo system, BrokenLine north, BrokenLine south) { if ((north == null) || (south == null)) { throw new IllegalArgumentException( "SystemBoundary needs non-null limits"); } this.system = system; limits.put(VerticalSide.TOP, north); limits.put(VerticalSide.BOTTOM, south); } //~ Methods ---------------------------------------------------------------- // //----------// // contains // //----------// /** * Check whether the provided point lies within the SystemBoundary * * @param point the provided point * @return true if the provided point lies within the SystemBoundary */ public boolean contains (Point point) { return getPolygon().contains(point); } //-----------// // getBounds // //-----------// /** * Report the rectangular bounds that enclose this boundary * * @return the rectangular bounds */ public Rectangle getBounds () { return getPolygon().getBounds(); } //----------// // getLimit // //----------// /** * Report the broken line on provided side * * @param side the desired side (TOP or BOTTOM) * @return the desired limit */ public BrokenLine getLimit (VerticalSide side) { return limits.get(side); } //-----------// // getLimits // //-----------// /** * Report the limits as a collection * * @return the north and south limits */ public Collection<BrokenLine> getLimits () { return limits.values(); } //--------// // render // //--------// /** * Paint the SystemBoundary in the provided graphic context. * * @param g the Graphics context * @param editable flag to indicate whether boundary is editable */ public void render (Graphics g, boolean editable) { final Graphics2D g2 = (Graphics2D) g; final int radius = BrokenLine.getStickyDistance(); final Polygon poly = getPolygon(); Color oldColor = g.getColor(); if (editable) { g.setColor(Color.RED); } // Draw the polygon g2.drawPolygon(poly); // Mark the reference points if (editable) { for (int i = 0; i < poly.npoints; i++) { g2.drawRect( poly.xpoints[i] - radius, poly.ypoints[i] - radius, 2 * radius, 2 * radius); } } g.setColor(oldColor); } //----------// // toString // //----------// @Override public String toString () { return "{Boundary" + " system#" + system.getId() + " north:" + limits.get(VerticalSide.TOP) + " south:" + limits.get(VerticalSide.BOTTOM) + "}"; } //--------// // update // //--------// /** * Update the system boundary. */ public void update () { // Simply invalidate the polygon polygon = null; } //------------// // getPolygon // //------------// /** * Report defining polygon (after creating it if needed); * * @return the system polygon */ private Polygon getPolygon () { if (polygon == null) { Polygon poly = new Polygon(); // North side (from left to right) for (Point point : limits.get(VerticalSide.TOP).getPoints()) { poly.addPoint(point.x, point.y); } // South side (in reverse order) List<Point> points = limits.get(VerticalSide.BOTTOM).getPoints(); for (ListIterator<Point> it = points.listIterator(points.size()); it.hasPrevious();) { Point point = it.previous(); poly.addPoint(point.x, point.y); } polygon = poly; } return polygon; } }