//----------------------------------------------------------------------------// // // // T i m e P a t t e r n // // // //----------------------------------------------------------------------------// // <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.glyph.pattern; import omr.constant.ConstantSet; import omr.glyph.CompoundBuilder; import omr.glyph.Evaluation; import omr.glyph.Grades; import omr.glyph.Shape; import omr.glyph.ShapeSet; import omr.glyph.facets.Glyph; import omr.grid.StaffInfo; import omr.sheet.Scale; import omr.sheet.SystemInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Point; import java.awt.Rectangle; import java.util.EnumSet; /** * Class {@code TimePattern} verifies the time signature glyphs. * * @author Hervé Bitteur */ public class TimePattern extends GlyphPattern { //~ Static fields/initializers --------------------------------------------- /** Specific application parameters */ private static final Constants constants = new Constants(); /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( TimePattern.class); //~ Instance fields -------------------------------------------------------- /** Specific compound adapter. */ private final TimeSigAdapter adapter; /** Scale-dependent parameters. */ private final Parameters params; //~ Constructors ----------------------------------------------------------- /** * Creates a new TimePattern object. * * @param system the containing system */ public TimePattern (SystemInfo system) { super("Time", system); params = new Parameters(system.getSheet().getScale()); adapter = new TimeSigAdapter( system, Grades.timeMinGrade, ShapeSet.FullTimes); } //~ Methods ---------------------------------------------------------------- //------------// // runPattern // //------------// /** * Check that each staff begins with a time * * @return the number of times rebuilt */ @Override public int runPattern () { int successNb = 0; for (Glyph glyph : system.getGlyphs()) { if (!ShapeSet.Times.contains(glyph.getShape()) || glyph.isManualShape()) { continue; } // We must find a time out of these glyphs Glyph compound = system.buildCompound( glyph, true, system.getGlyphs(), adapter); if (compound != null) { successNb++; } } return successNb; } //~ Inner Classes ---------------------------------------------------------- //-----------// // Constants // //-----------// private static final class Constants extends ConstantSet { //~ Instance fields ---------------------------------------------------- Scale.Fraction xOffset = new Scale.Fraction( 0.25d, "Core Time horizontal offset"); Scale.Fraction yOffset = new Scale.Fraction( 0.25d, "Core Time vertical offset"); Scale.Fraction timeWidth = new Scale.Fraction( 1.6, "Typical width of a time signature"); Scale.Fraction maxTimeWidth = new Scale.Fraction( 4, "Maximum width of a time signature"); Scale.Fraction maxTimeHeight = new Scale.Fraction( 8, "Maximum height of a time signature"); } //------------// // Parameters // //------------// private static class Parameters { //~ Instance fields ---------------------------------------------------- final int xOffset; final int yOffset; final int timeWidth; final int maxTimeWidth; final int maxTimeHeight; //~ Constructors ------------------------------------------------------- public Parameters (Scale scale) { xOffset = scale.toPixels(constants.xOffset); yOffset = scale.toPixels(constants.yOffset); timeWidth = scale.toPixels(constants.timeWidth); maxTimeWidth = scale.toPixels(constants.maxTimeWidth); maxTimeHeight = scale.toPixels(constants.maxTimeHeight); } } //----------------// // TimeSigAdapter // //----------------// /** * Compound adapter to search for a time sig shape */ private class TimeSigAdapter extends CompoundBuilder.TopRawAdapter { //~ Constructors ------------------------------------------------------- public TimeSigAdapter (SystemInfo system, double minGrade, EnumSet<Shape> desiredShapes) { super(system, minGrade, desiredShapes); } //~ Methods ------------------------------------------------------------ @Override public Rectangle computeReferenceBox () { // Define the core box to intersect time glyph(s) Point center = seed.getAreaCenter(); StaffInfo staff = system.getStaffAt(center); Rectangle rect = seed.getBounds(); if (rect.width < params.timeWidth) { rect.grow(params.timeWidth - rect.width, 0); } rect.grow(-params.xOffset, 0); rect.y = staff.getFirstLine() .yAt(center.x) + params.yOffset; rect.height = staff.getLastLine() .yAt(center.x) - params.yOffset - rect.y; // Draw the time core box, for visual debug seed.addAttachment("t", rect); return rect; } @Override public Evaluation getChosenEvaluation () { return new Evaluation(chosenEvaluation.shape, Evaluation.ALGORITHM); } @Override public boolean isCandidateClose (Glyph glyph) { if (super.isCandidateClose(glyph)) { // Check dimension of resulting bounds Rectangle result = glyph.getBounds() .union(box); if ((result.width > params.maxTimeWidth) || (result.height > params.maxTimeHeight)) { logger.debug("Excluding too large {}", glyph); return false; } else { return true; } } else { return false; } } @Override public boolean isCandidateSuitable (Glyph glyph) { return !glyph.isManualShape() && glyph.isActive(); } } }