//----------------------------------------------------------------------------//
// //
// B a s s 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.Constant;
import omr.constant.ConstantSet;
import omr.glyph.CompoundBuilder;
import omr.glyph.CompoundBuilder.CompoundAdapter;
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;
/**
* Class {@code BassPattern} checks for segmented bass clefs, in the
* neighborhood of typical vertical two-dot patterns
*
* @author Hervé Bitteur
*/
public class BassPattern
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(
BassPattern.class);
//~ Constructors -----------------------------------------------------------
//-------------//
// BassPattern //
//-------------//
/**
* Creates a new BassPattern object.
*
* @param system the containing system
*/
public BassPattern (SystemInfo system)
{
super("Bass", system);
}
//~ Methods ----------------------------------------------------------------
//------------//
// runPattern //
//------------//
@Override
public int runPattern ()
{
int successNb = 0;
// Constants for clef verification
final double maxBassDotPitchDy = constants.maxBassDotPitchDy.getValue();
final double maxBassDotDx = scale.toPixels(constants.maxBassDotDx);
// Specific adapter definition for bass clefs
CompoundAdapter bassAdapter = new BassAdapter(
system,
Grades.clefMinGrade);
for (Glyph top : system.getGlyphs()) {
// Look for top dot
if ((top.getShape() != Shape.DOT_set)
|| (Math.abs(top.getPitchPosition() - -3) > maxBassDotPitchDy)) {
continue;
}
int topX = top.getCentroid().x;
StaffInfo topStaff = system.getStaffAt(top.getCentroid());
// Look for bottom dot right underneath, and in the same staff
for (Glyph bot : system.getGlyphs()) {
if ((bot.getShape() != Shape.DOT_set)
|| (Math.abs(bot.getPitchPosition() - -1) > maxBassDotPitchDy)) {
continue;
}
if (Math.abs(bot.getCentroid().x - topX) > maxBassDotDx) {
continue;
}
if (system.getStaffAt(bot.getCentroid()) != topStaff) {
continue;
}
// Here we have a couple
logger.debug(
"Got bass dots #{} & #{}",
top.getId(),
bot.getId());
Glyph compound = system.buildCompound(
top,
true,
system.getGlyphs(),
bassAdapter);
if (compound != null) {
successNb++;
}
}
}
return successNb;
}
//~ Inner Classes ----------------------------------------------------------
//-----------//
// Constants //
//-----------//
private static final class Constants
extends ConstantSet
{
//~ Instance fields ----------------------------------------------------
Scale.Fraction maxBassDotDx = new Scale.Fraction(
0.25,
"Tolerance on Bass dot abscissae");
Constant.Double maxBassDotPitchDy = new Constant.Double(
"pitch",
0.5,
"Ordinate tolerance on a Bass dot pitch position");
}
//-------------//
// BassAdapter //
//-------------//
/**
* This is the compound adapter meant to build bass clefs
*/
private class BassAdapter
extends CompoundBuilder.TopShapeAdapter
{
//~ Constructors -------------------------------------------------------
public BassAdapter (SystemInfo system,
double minGrade)
{
super(system, minGrade, ShapeSet.BassClefs);
}
//~ Methods ------------------------------------------------------------
@Override
public Rectangle computeReferenceBox ()
{
if (seed == null) {
throw new NullPointerException(
"Compound seed has not been set");
}
Rectangle pixRect = new Rectangle(seed.getCentroid());
pixRect.add(
new Point(
pixRect.x - (2 * scale.getInterline()),
pixRect.y + (3 * scale.getInterline())));
return pixRect;
}
@Override
public boolean isCandidateSuitable (Glyph glyph)
{
return !glyph.isManualShape()
|| ShapeSet.BassClefs.contains(glyph.getShape());
}
}
}