//----------------------------------------------------------------------------// // // // F l a g 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.Shape; import omr.glyph.ShapeSet; import omr.glyph.facets.Glyph; import omr.sheet.Scale; import omr.sheet.SystemInfo; import omr.util.HorizontalSide; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Rectangle; /** * Class {@code FlagPattern} removes flags for which the related stem * has no attached head (or at least some significant no-shape stuff). * * @author Hervé Bitteur */ public class FlagPattern 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( FlagPattern.class); //~ Constructors ----------------------------------------------------------- //-------------// // FlagPattern // //-------------// /** * Creates a new FlagPattern object. * * @param system the system to process */ public FlagPattern (SystemInfo system) { super("Flag", system); } //~ Methods ---------------------------------------------------------------- //------------// // runPattern // //------------// @Override public int runPattern () { int nb = 0; for (Glyph flag : system.getGlyphs()) { if (!ShapeSet.Flags.contains(flag.getShape()) || flag.isManualShape()) { continue; } if (flag.isVip() || logger.isDebugEnabled()) { logger.info("Checking flag #{}", flag.getId()); } Glyph stem = flag.getStem(HorizontalSide.LEFT); if (stem == null) { if (flag.isVip() || logger.isDebugEnabled()) { logger.info("No left stem for flag #{}", flag.getId()); } flag.setShape(null); nb++; break; } // Look for other stuff on the stem, whatever the side Rectangle stemBox = system.stemBoxOf(stem); boolean found = false; for (Glyph g : system.lookupIntersectedGlyphs(stemBox, stem, flag)) { // We are looking for head (or some similar large stuff) Shape shape = g.getShape(); if (ShapeSet.NoteHeads.contains(shape) || ((shape == null) && (g.getNormalizedWeight() >= constants.minStuffWeight.getValue()))) { if (flag.isVip() || logger.isDebugEnabled()) { logger.info("Confirmed flag #{}", flag.getId()); } found = true; break; } } if (!found) { // Deassign this flag w/ no head neighbor if (flag.isVip() || logger.isDebugEnabled()) { logger.info("Cancelled flag #{}", flag.getId()); } flag.setShape(null); nb++; } } return nb; } //~ Inner Classes ---------------------------------------------------------- //-----------// // Constants // //-----------// private static final class Constants extends ConstantSet { //~ Instance fields ---------------------------------------------------- // Scale.AreaFraction minStuffWeight = new Scale.AreaFraction( 0.5, "Minimum weight for a stem stuff"); } }