//----------------------------------------------------------------------------//
// //
// B a s i c E n v i r o n m e n t //
// //
//----------------------------------------------------------------------------//
// <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.facets;
import omr.lag.Lag;
import omr.lag.Section;
import omr.run.Run;
import omr.sheet.SystemInfo;
import omr.util.HorizontalSide;
import omr.util.Predicate;
import java.awt.Rectangle;
import java.util.HashSet;
import java.util.Set;
/**
* Class {@code BasicEnvironment} is the basic implementation of an
* environment facet.
*
* @author Hervé Bitteur
*/
class BasicEnvironment
extends BasicFacet
implements GlyphEnvironment
{
//~ Instance fields --------------------------------------------------------
/** Position with respect to nearest staff. Key references are : 0 for
* middle line (B), -2 for top line (F) and +2 for bottom line (E) */
private double pitchPosition;
/** Number of stems it is connected to (0, 1, 2) */
private int stemNumber;
/** Stem attached on left if any */
private Glyph leftStem;
/** Stem attached on right if any */
private Glyph rightStem;
/** Is there a ledger nearby ? */
private boolean withLedger;
//~ Constructors -----------------------------------------------------------
//------------------//
// BasicEnvironment //
//------------------//
/**
* Create a new BasicEnvironment object
*
* @param glyph our glyph
*/
public BasicEnvironment (Glyph glyph)
{
super(glyph);
}
//~ Methods ----------------------------------------------------------------
//---------------------//
// copyStemInformation //
//---------------------//
@Override
public void copyStemInformation (Glyph other)
{
for (HorizontalSide side : HorizontalSide.values()) {
setStem(other.getStem(side), side);
}
setStemNumber(other.getStemNumber());
}
//--------//
// dumpOf //
//--------//
@Override
public String dumpOf ()
{
StringBuilder sb = new StringBuilder();
if (stemNumber > 0) {
sb.append(String.format(" stemNumber=%s%n", stemNumber));
}
if (leftStem != null) {
sb.append(String.format(" leftStem=%s%n", leftStem));
}
if (rightStem != null) {
sb.append(String.format(" rightStem=%s%n", rightStem));
}
sb.append(String.format(" pitchPosition=%s%n", getPitchPosition()));
if (withLedger) {
sb.append(String.format(" withLedger%n"));
}
return sb.toString();
}
//--------------------//
// getAlienPixelsFrom //
//--------------------//
@Override
public int getAlienPixelsFrom (Lag lag,
Rectangle absRoi,
Predicate<Section> predicate)
{
// Use lag orientation
final Rectangle oRoi = lag.getOrientation()
.oriented(absRoi);
final int posMin = oRoi.y;
final int posMax = (oRoi.y + oRoi.height) - 1;
int count = 0;
for (Section section : lag.lookupIntersectedSections(absRoi)) {
// Exclude sections that are part of the glyph
if (section.getGlyph() == glyph) {
continue;
}
// Additional section predicate, if any
if ((predicate != null) && !predicate.check(section)) {
continue;
}
int pos = section.getFirstPos() - 1;
for (Run run : section.getRuns()) {
pos++;
if (pos > posMax) {
break;
}
if (pos < posMin) {
continue;
}
int coordMin = Math.max(oRoi.x, run.getStart());
int coordMax = Math.min(
(oRoi.x + oRoi.width) - 1,
run.getStop());
if (coordMax >= coordMin) {
count += (coordMax - coordMin + 1);
}
}
}
return count;
}
//-----------------------//
// getConnectedNeighbors //
//-----------------------//
@Override
public Set<Glyph> getConnectedNeighbors ()
{
Set<Section> sections = glyph.getMembers();
// Retrieve sections connected to this glyph
Set<Section> connectedSections = new HashSet<>();
for (Section section : sections) {
for (Section s : section.getSources()) {
if (!sections.contains(s)) {
connectedSections.add(s);
}
}
for (Section s : section.getTargets()) {
if (!sections.contains(s)) {
connectedSections.add(s);
}
}
for (Section s : section.getOppositeSections()) {
if (!sections.contains(s)) {
connectedSections.add(s);
}
}
}
// Retrieve their containing glyphs
Set<Glyph> connectedGlyphs = new HashSet<>();
for (Section s : connectedSections) {
Glyph g = s.getGlyph();
if (g != null) {
connectedGlyphs.add(g);
}
}
return connectedGlyphs;
}
//--------------//
// getFirstStem //
//--------------//
@Override
public Glyph getFirstStem ()
{
for (HorizontalSide side : HorizontalSide.values()) {
Glyph stem = getStem(side);
if (stem != null) {
return stem;
}
}
return null;
}
//------------------//
// getPitchPosition //
//------------------//
@Override
public double getPitchPosition ()
{
return pitchPosition;
}
//---------//
// getStem //
//---------//
@Override
public Glyph getStem (HorizontalSide side)
{
if (side == HorizontalSide.LEFT) {
return leftStem;
} else {
return rightStem;
}
}
//---------------//
// getStemNumber //
//---------------//
@Override
public int getStemNumber ()
{
return stemNumber;
}
//-----------------//
// getSymbolsAfter //
//-----------------//
@Override
public void getSymbolsAfter (Predicate<Glyph> predicate,
Set<Glyph> goods,
Set<Glyph> bads)
{
for (Section section : glyph.getMembers()) {
for (Section sct : section.getTargets()) {
if (sct.isGlyphMember()) {
Glyph other = sct.getGlyph();
if (other != glyph) {
if (predicate.check(other)) {
goods.add(other);
} else {
bads.add(other);
}
}
}
}
}
}
//------------------//
// getSymbolsBefore //
//------------------//
@Override
public void getSymbolsBefore (Predicate<Glyph> predicate,
Set<Glyph> goods,
Set<Glyph> bads)
{
for (Section section : glyph.getMembers()) {
for (Section sct : section.getSources()) {
if (sct.isGlyphMember()) {
Glyph other = sct.getGlyph();
if (other != glyph) {
if (predicate.check(other)) {
goods.add(other);
} else {
bads.add(other);
}
}
}
}
}
}
//-----------//
// getSystem //
//-----------//
@Override
public SystemInfo getSystem ()
{
return glyph.getFirstSection()
.getSystem();
}
//--------------//
// isWithLedger //
//--------------//
@Override
public boolean isWithLedger ()
{
return withLedger;
}
//------------------//
// setPitchPosition //
//------------------//
@Override
public void setPitchPosition (double pitchPosition)
{
this.pitchPosition = pitchPosition;
}
//---------//
// setStem //
//---------//
@Override
public void setStem (Glyph stem,
HorizontalSide side)
{
if (side == HorizontalSide.LEFT) {
leftStem = stem;
} else {
rightStem = stem;
}
}
//---------------//
// setStemNumber //
//---------------//
@Override
public void setStemNumber (int stemNumber)
{
this.stemNumber = stemNumber;
}
//---------------//
// setWithLedger //
//---------------//
@Override
public void setWithLedger (boolean withLedger)
{
this.withLedger = withLedger;
}
}