//----------------------------------------------------------------------------//
// //
// B a s i c G l y p h //
// //
//----------------------------------------------------------------------------//
// <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.check.Result;
import omr.glyph.Evaluation;
import omr.glyph.GlyphSignature;
import omr.glyph.Nest;
import omr.glyph.Shape;
import omr.lag.Lag;
import omr.lag.Section;
import omr.math.Circle;
import omr.math.Line;
import omr.math.PointsCollector;
import omr.moments.ARTMoments;
import omr.moments.GeometricMoments;
import omr.run.Orientation;
import omr.score.entity.PartNode;
import omr.score.entity.TimeRational;
import omr.sheet.SystemInfo;
import omr.text.BasicContent;
import omr.text.TextRoleInfo;
import omr.text.TextWord;
import omr.util.HorizontalSide;
import omr.util.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
/**
* Class {@code BasicGlyph} is the basic Glyph implementation.
*
* <p>From an implementation point of view, this {@code BasicGlyph} is just a
* shell around specialized Glyph facets, and most of the methods are simply
* using delegation to the proper facet.
*
* @author Hervé Bitteur
*/
public class BasicGlyph
implements Glyph
{
//~ Static fields/initializers ---------------------------------------------
/** Usual logger utility */
private static final Logger logger = LoggerFactory.getLogger(BasicGlyph.class);
//~ Instance fields --------------------------------------------------------
/** All needed facets */
final GlyphAdministration administration;
final GlyphComposition composition;
final GlyphDisplay display;
final GlyphEnvironment environment;
final GlyphGeometry geometry;
final GlyphRecognition recognition;
final GlyphTranslation translation;
final GlyphAlignment alignment;
// The content facet is not final to allow lazy allocation
protected GlyphContent content;
// Set all facets
final Set<GlyphFacet> facets = new LinkedHashSet<>();
//~ Constructors -----------------------------------------------------------
//------------//
// BasicGlyph //
//------------//
/**
* Create a new BasicGlyph object.
*
* @param interline the scaling interline value
*/
public BasicGlyph (int interline)
{
addFacet(administration = new BasicAdministration(this));
addFacet(composition = new BasicComposition(this));
addFacet(display = new BasicDisplay(this));
addFacet(environment = new BasicEnvironment(this));
addFacet(geometry = new BasicGeometry(this, interline));
addFacet(recognition = new BasicRecognition(this));
addFacet(translation = new BasicTranslation(this));
addFacet(alignment = new BasicAlignment(this));
}
//------------//
// BasicGlyph //
//------------//
/**
* Create a new BasicGlyph object from a GlyphValue instance
* (typically unmarshalled from XML).
*
* @param value the GlyphValue "builder" object
*/
public BasicGlyph (GlyphValue value)
{
this(value.interline);
setId(value.id);
setShape(value.shape);
setStemNumber(value.stemNumber);
setWithLedger(value.withLedger);
setPitchPosition(value.pitchPosition);
for (Section section : value.members) {
addSection(section, Linking.NO_LINK_BACK);
}
}
//------------//
// BasicGlyph //
//------------//
/**
* Create a glyph with a specific alignment class.
*
* @param interline the scaling information
* @param alignmentClass the specific alignment class
*/
protected BasicGlyph (int interline,
Class<? extends GlyphAlignment> alignmentClass)
{
addFacet(administration = new BasicAdministration(this));
addFacet(composition = new BasicComposition(this));
addFacet(display = new BasicDisplay(this));
addFacet(environment = new BasicEnvironment(this));
addFacet(geometry = new BasicGeometry(this, interline));
addFacet(recognition = new BasicRecognition(this));
addFacet(translation = new BasicTranslation(this));
GlyphAlignment theAlignment = null;
try {
Constructor<?> constructor = alignmentClass.getConstructor(
new Class<?>[]{Glyph.class});
theAlignment = (GlyphAlignment) constructor.newInstance(
new Object[]{this});
} catch (Exception ex) {
logger.error(
"Cannot instantiate BasicGlyph with {} ex:{}",
alignmentClass,
ex);
}
addFacet(alignment = theAlignment);
}
//~ Methods ----------------------------------------------------------------
@Override
public void addAttachment (String id,
java.awt.Shape attachment)
{
display.addAttachment(id, attachment);
}
@Override
public void addSection (Section section,
Linking link)
{
composition.addSection(section, link);
}
@Override
public void addTranslation (PartNode entity)
{
translation.addTranslation(entity);
}
@Override
public void allowShape (Shape shape)
{
recognition.allowShape(shape);
}
@Override
public void clearTranslations ()
{
translation.clearTranslations();
}
@Override
public void colorize (Collection<Section> sections,
Color color)
{
display.colorize(sections, color);
}
@Override
public void colorize (Color color)
{
display.colorize(color);
}
@Override
public boolean containsSection (int id)
{
return composition.containsSection(id);
}
@Override
public void copyStemInformation (Glyph glyph)
{
environment.copyStemInformation(glyph);
}
@Override
public void cutSections ()
{
composition.cutSections();
}
@Override
public String asciiDrawing ()
{
return display.asciiDrawing();
}
//--------//
// dumpOf //
//--------//
@Override
public String dumpOf ()
{
StringBuilder sb = new StringBuilder();
for (GlyphFacet facet : facets) {
sb.append(facet.dumpOf());
}
return sb.toString();
}
@Override
public void forbidShape (Shape shape)
{
recognition.forbidShape(shape);
}
@Override
public ARTMoments getARTMoments ()
{
return geometry.getARTMoments();
}
@Override
public int getAlienPixelsFrom (Lag lag,
Rectangle absRoi,
Predicate<Section> predicate)
{
return environment.getAlienPixelsFrom(lag, absRoi, predicate);
}
@Override
public SystemInfo getAlienSystem (SystemInfo system)
{
return composition.getAlienSystem(system);
}
@Override
public Glyph getAncestor ()
{
return composition.getAncestor();
}
@Override
public Point getAreaCenter ()
{
return geometry.getAreaCenter();
}
@Override
public double getAspect (Orientation orientation)
{
return alignment.getAspect(orientation);
}
@Override
public Map<String, java.awt.Shape> getAttachments ()
{
return display.getAttachments();
}
@Override
public Rectangle getBounds ()
{
return geometry.getBounds();
}
@Override
public Point getCentroid ()
{
return geometry.getCentroid();
}
@Override
public Circle getCircle ()
{
return geometry.getCircle();
}
@Override
public Color getColor ()
{
return display.getColor();
}
@Override
public Set<Glyph> getConnectedNeighbors ()
{
return environment.getConnectedNeighbors();
}
@Override
public double getDensity ()
{
return geometry.getDensity();
}
@Override
public Evaluation getEvaluation ()
{
return recognition.getEvaluation();
}
@Override
public Section getFirstSection ()
{
return composition.getFirstSection();
}
@Override
public Glyph getFirstStem ()
{
return environment.getFirstStem();
}
@Override
public int getFirstStuck ()
{
return alignment.getFirstStuck();
}
@Override
public GeometricMoments getGeometricMoments ()
{
return geometry.getGeometricMoments();
}
@Override
public double getGrade ()
{
return recognition.getGrade();
}
@Override
public int getId ()
{
return administration.getId();
}
@Override
public BufferedImage getImage ()
{
return display.getImage();
}
@Override
public int getInterline ()
{
return geometry.getInterline();
}
@Override
public double getInvertedSlope ()
{
return alignment.getInvertedSlope();
}
@Override
public int getLastStuck ()
{
return alignment.getLastStuck();
}
@Override
public int getLength (Orientation orientation)
{
return alignment.getLength(orientation);
}
@Override
public Line getLine ()
{
return alignment.getLine();
}
@Override
public Point getLocation ()
{
return geometry.getLocation();
}
@Override
public TextRoleInfo getManualRole ()
{
return getContent()
.getManualRole();
}
@Override
public String getManualValue ()
{
return getContent()
.getManualValue();
}
@Override
public double getMeanDistance ()
{
return alignment.getMeanDistance();
}
@Override
public double getMeanThickness (Orientation orientation)
{
return alignment.getMeanThickness(orientation);
}
@Override
public SortedSet<Section> getMembers ()
{
return composition.getMembers();
}
@Override
public int getMidPos (Orientation orientation)
{
return alignment.getMidPos(orientation);
}
@Override
public Nest getNest ()
{
return administration.getNest();
}
@Override
public double getNormalizedHeight ()
{
return geometry.getNormalizedHeight();
}
@Override
public double getNormalizedWeight ()
{
return geometry.getNormalizedWeight();
}
@Override
public double getNormalizedWidth ()
{
return geometry.getNormalizedWidth();
}
@Override
public String getOcrLanguage ()
{
return getContent()
.getOcrLanguage();
}
@Override
public Glyph getPartOf ()
{
return composition.getPartOf();
}
@Override
public double getPitchPosition ()
{
return environment.getPitchPosition();
}
@Override
public PointsCollector getPointsCollector ()
{
return geometry.getPointsCollector();
}
@Override
public double getPositionAt (double coord,
Orientation orientation)
{
return alignment.getPositionAt(coord, orientation);
}
@Override
public Point2D getRectangleCentroid (Rectangle absRoi)
{
return alignment.getRectangleCentroid(absRoi);
}
@Override
public GlyphSignature getRegisteredSignature ()
{
return geometry.getRegisteredSignature();
}
@Override
public Result getResult ()
{
return composition.getResult();
}
@Override
public Shape getShape ()
{
return recognition.getShape();
}
@Override
public GlyphSignature getSignature ()
{
return geometry.getSignature();
}
@Override
public double getSlope ()
{
return alignment.getSlope();
}
@Override
public Point2D getStartPoint (Orientation orientation)
{
return alignment.getStartPoint(orientation);
}
@Override
public Glyph getStem (HorizontalSide side)
{
return environment.getStem(side);
}
@Override
public int getStemNumber ()
{
return environment.getStemNumber();
}
@Override
public Point2D getStopPoint (Orientation orientation)
{
return alignment.getStopPoint(orientation);
}
@Override
public void getSymbolsAfter (Predicate<Glyph> predicate,
Set<Glyph> goods,
Set<Glyph> bads)
{
environment.getSymbolsAfter(predicate, goods, bads);
}
@Override
public void getSymbolsBefore (Predicate<Glyph> predicate,
Set<Glyph> goods,
Set<Glyph> bads)
{
environment.getSymbolsBefore(predicate, goods, bads);
}
@Override
public SystemInfo getSystem ()
{
return environment.getSystem();
}
@Override
public Point getTextLocation ()
{
return getContent()
.getTextLocation();
}
@Override
public TextRoleInfo getTextRole ()
{
return getContent()
.getTextRole();
}
@Override
public String getTextValue ()
{
return getContent()
.getTextValue();
}
@Override
public TextWord getTextWord ()
{
return getContent()
.getTextWord();
}
@Override
public int getThickness (Orientation orientation)
{
return alignment.getThickness(orientation);
}
@Override
public double getThicknessAt (double coord,
Orientation orientation)
{
return alignment.getThicknessAt(coord, orientation);
}
@Override
public TimeRational getTimeRational ()
{
return recognition.getTimeRational();
}
@Override
public Collection<PartNode> getTranslations ()
{
return translation.getTranslations();
}
@Override
public int getWeight ()
{
return geometry.getWeight();
}
@Override
public String idString ()
{
return administration.idString();
}
@Override
public boolean intersects (Rectangle rectangle)
{
return geometry.intersects(rectangle);
}
//-----------------//
// invalidateCache //
//-----------------//
@Override
public void invalidateCache ()
{
// Invalidate all allocated facets
for (GlyphFacet facet : facets) {
facet.invalidateCache();
}
}
@Override
public boolean isActive ()
{
return composition.isActive();
}
@Override
public boolean isBar ()
{
return recognition.isBar();
}
@Override
public boolean isClef ()
{
return recognition.isClef();
}
@Override
public boolean isKnown ()
{
return recognition.isKnown();
}
@Override
public boolean isManualShape ()
{
return recognition.isManualShape();
}
@Override
public boolean isProcessed ()
{
return administration.isProcessed();
}
@Override
public boolean isShapeForbidden (Shape shape)
{
return recognition.isShapeForbidden(shape);
}
@Override
public boolean isStem ()
{
return recognition.isStem();
}
@Override
public boolean isSuccessful ()
{
return composition.isSuccessful();
}
@Override
public boolean isText ()
{
return recognition.isText();
}
@Override
public boolean isTransient ()
{
return administration.isTransient();
}
@Override
public boolean isTranslated ()
{
return translation.isTranslated();
}
@Override
public boolean isVip ()
{
return administration.isVip();
}
@Override
public boolean isVirtual ()
{
return administration.isVirtual();
}
@Override
public boolean isWellKnown ()
{
return recognition.isWellKnown();
}
@Override
public boolean isWithLedger ()
{
return environment.isWithLedger();
}
@Override
public void linkAllSections ()
{
composition.linkAllSections();
}
@Override
public void recolorize ()
{
display.recolorize();
}
@Override
public int removeAttachments (String prefix)
{
return display.removeAttachments(prefix);
}
@Override
public boolean removeSection (Section section,
Linking link)
{
return composition.removeSection(section, link);
}
@Override
public void renderAttachments (Graphics2D g)
{
display.renderAttachments(g);
}
@Override
public void renderLine (Graphics2D g)
{
alignment.renderLine(g);
}
@Override
public void resetEvaluation ()
{
recognition.resetEvaluation();
}
@Override
public void setCircle (Circle circle)
{
geometry.setCircle(circle);
}
@Override
public void setContourBox (Rectangle contourBox)
{
geometry.setContourBox(contourBox);
}
@Override
public void setEndingPoints (Point2D pStart,
Point2D pStop)
{
alignment.setEndingPoints(pStart, pStop);
}
@Override
public void setEvaluation (Evaluation evaluation)
{
recognition.setEvaluation(evaluation);
}
@Override
public void setId (int id)
{
administration.setId(id);
}
@Override
public void setManualRole (TextRoleInfo manualRole)
{
getContent()
.setManualRole(manualRole);
}
@Override
public void setManualValue (String manualValue)
{
getContent()
.setManualValue(manualValue);
}
@Override
public void setNest (Nest nest)
{
administration.setNest(nest);
}
@Override
public void setPartOf (Glyph compound)
{
composition.setPartOf(compound);
}
@Override
public void setPitchPosition (double pitchPosition)
{
environment.setPitchPosition(pitchPosition);
}
@Override
public void setProcessed (boolean processed)
{
administration.setProcessed(processed);
}
@Override
public void setRegisteredSignature (GlyphSignature sig)
{
geometry.setRegisteredSignature(sig);
}
@Override
public void setResult (Result result)
{
composition.setResult(result);
}
@Override
public void setShape (Shape shape,
double grade)
{
recognition.setShape(shape, grade);
}
@Override
public void setShape (Shape shape)
{
recognition.setShape(shape);
}
@Override
public void setStem (Glyph stem,
HorizontalSide side)
{
environment.setStem(stem, side);
}
@Override
public void setStemNumber (int stemNumber)
{
environment.setStemNumber(stemNumber);
}
@Override
public void setTextWord (String ocrLanguage,
TextWord textWord)
{
getContent()
.setTextWord(ocrLanguage, textWord);
}
@Override
public void setTimeRational (TimeRational timeRational)
{
recognition.setTimeRational(timeRational);
}
@Override
public void setTranslation (PartNode entity)
{
translation.setTranslation(entity);
}
@Override
public void setVip ()
{
administration.setVip();
}
@Override
public void setWithLedger (boolean withLedger)
{
environment.setWithLedger(withLedger);
}
@Override
public void stealSections (Glyph that)
{
composition.stealSections(that);
}
//----------//
// toString //
//----------//
@Override
public String toString ()
{
StringBuilder sb = new StringBuilder();
sb.append("{")
.append(getClass().getSimpleName())
.append("#")
.append(this.getId());
sb.append(internalsString());
sb.append("}");
return sb.toString();
}
@Override
public void translate (Point vector)
{
geometry.translate(vector);
}
//--------------//
// getAlignment //
//--------------//
protected GlyphAlignment getAlignment ()
{
return alignment;
}
//----------------//
// getComposition //
//----------------//
protected GlyphComposition getComposition ()
{
return composition;
}
//------------//
// getContent //
//------------//
protected GlyphContent getContent ()
{
// Lazy allocation, to avoid too many allocations
// (less than 3% of all glyphs need a content facet)
if (content == null) {
addFacet(content = new BasicContent(this));
}
return content;
}
//-----------------//
// internalsString //
//-----------------//
/**
* Return the string of the internals of this class, typically for
* inclusion in a toString.
* The overriding methods, if any, should return a string that begins with
* a " " followed by some content.
*
* @return the string of internals
*/
protected String internalsString ()
{
StringBuilder sb = new StringBuilder(25);
if (getShape() != null) {
sb.append(" ")
.append(recognition.getEvaluation());
if (getShape()
.getPhysicalShape() != getShape()) {
sb.append(" physical=")
.append(getShape().getPhysicalShape());
}
}
if (getPartOf() != null) {
sb.append(" partOf#")
.append(getPartOf().getId());
}
if (getCentroid() != null) {
sb.append(" centroid=[")
.append(getCentroid().x)
.append(",")
.append(getCentroid().y)
.append("]");
}
if (isTranslated()) {
sb.append(" trans=[")
.append(getTranslations())
.append("]");
}
if (getResult() != null) {
sb.append(" ")
.append(getResult());
}
return sb.toString();
}
//----------//
// addFacet //
//----------//
/**
* Register a facet
*
* @param facet the facet to register
*/
final void addFacet (GlyphFacet facet)
{
facets.add(facet);
}
}