//----------------------------------------------------------------------------// // // // B a s i c G e o m e t r y // // // //----------------------------------------------------------------------------// // <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.glyph.GlyphSignature; import omr.glyph.Shape; import omr.lag.Section; import omr.math.Circle; import omr.math.PointsCollector; import omr.moments.ARTMoments; import omr.moments.BasicARTExtractor; import omr.moments.BasicARTMoments; import omr.moments.GeometricMoments; import omr.ui.symbol.ShapeSymbol; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Point; import java.awt.Rectangle; /** * Class {@code BasicGeometry} is the basic implementation of the * geometry facet. * * @author Hervé Bitteur */ class BasicGeometry extends BasicFacet implements GlyphGeometry { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( BasicGeometry.class); //~ Instance fields -------------------------------------------------------- /** Interline of the containing staff (or sheet) */ private final int interline; /** Total weight of this glyph */ private Integer weight; /** Computed ART Moments of this glyph */ private ARTMoments artMoments; /** Computed geometric Moments of this glyph */ private GeometricMoments geometricMoments; /** Mass center coordinates */ private Point centroid; /** Box center coordinates */ private Point center; /** Absolute contour box */ private Rectangle bounds; /** Current signature */ private GlyphSignature signature; /** Signature used for registration */ private GlyphSignature registeredSignature; /** Approximating circle, if any */ private Circle circle; //~ Constructors ----------------------------------------------------------- //---------------// // BasicGeometry // //---------------// /** * Create a new BasicGeometry object. * * @param glyph our glyph * @param interline the interline scaling value */ public BasicGeometry (Glyph glyph, int interline) { super(glyph); this.interline = interline; } //~ Methods ---------------------------------------------------------------- //--------// // dumpOf // //--------// @Override public String dumpOf () { StringBuilder sb = new StringBuilder(); sb.append(String.format(" bounds=%s%n", getBounds())); sb.append(String.format(" centroid=%s%n", getCentroid())); sb.append(String.format(" interline=%s%n", getInterline())); sb.append(String.format(" location=%s%n", getLocation())); sb.append(String.format(" geoMoments=%s%n", getGeometricMoments())); sb.append(String.format(" artMoments=%s%n", getARTMoments())); sb.append(String.format(" weight=%s%n", getWeight())); if (circle != null) { sb.append(String.format(" circle=%s%n", circle)); } return sb.toString(); } //---------------// // getARTMoments // //---------------// @Override public ARTMoments getARTMoments () { if (artMoments == null) { computeARTMoments(); } return artMoments; } //---------------// // getAreaCenter // //---------------// @Override public Point getAreaCenter () { if (center == null) { Rectangle box = glyph.getBounds(); center = new Point( box.x + (box.width / 2), box.y + (box.height / 2)); } return center; } //-----------// // getBounds // //-----------// @Override public Rectangle getBounds () { if (bounds == null) { Rectangle box = null; for (Section section : glyph.getMembers()) { if (box == null) { box = section.getBounds(); } else { box.add(section.getBounds()); } } bounds = box; } if (bounds != null) { return new Rectangle(bounds); // Return a COPY } else { return null; } } //-------------// // getCentroid // //-------------// @Override public Point getCentroid () { if (centroid == null) { centroid = getGeometricMoments() .getCentroid(); } return centroid; } //-----------// // getCircle // //-----------// @Override public Circle getCircle () { return circle; } //------------// // getDensity // //------------// @Override public double getDensity () { Rectangle rect = getBounds(); int surface = (rect.width + 1) * (rect.height + 1); return (double) getWeight() / (double) surface; } //---------------------// // getGeometricMoments // //---------------------// @Override public GeometricMoments getGeometricMoments () { if (geometricMoments == null) { computeGeometricMoments(); } return geometricMoments; } //--------------// // getInterline // //--------------// @Override public int getInterline () { return interline; } //-------------// // getLocation // //-------------// @Override public Point getLocation () { Shape shape = glyph.getShape(); // No shape: use area center if (shape == null) { return getAreaCenter(); } // Text shape: use specific reference if (shape.isText()) { Point loc = glyph.getTextLocation(); if (loc != null) { return loc; } } // Other shape: check with the related symbol if any ShapeSymbol symbol = shape.getSymbol(); if (symbol != null) { return symbol.getRefPoint(getBounds()); } // Default: use area center return getAreaCenter(); } //---------------------// // getNormalizedHeight // //---------------------// @Override public double getNormalizedHeight () { return getGeometricMoments() .getHeight(); } //---------------------// // getNormalizedWeight // //---------------------// @Override public double getNormalizedWeight () { return getGeometricMoments() .getWeight(); } //--------------------// // getNormalizedWidth // //--------------------// @Override public double getNormalizedWidth () { return getGeometricMoments() .getWidth(); } //--------------------// // getPointsCollector // //--------------------// @Override public PointsCollector getPointsCollector () { // Cumulate point from member sections PointsCollector collector = new PointsCollector(null, getWeight()); // Append all points, whatever section orientation for (Section section : glyph.getMembers()) { section.cumulate(collector); } return collector; } //------------------------// // getRegisteredSignature // //------------------------// @Override public GlyphSignature getRegisteredSignature () { return registeredSignature; } //--------------// // getSignature // //--------------// @Override public GlyphSignature getSignature () { if (signature == null) { signature = new GlyphSignature(glyph); } return signature; } //-----------// // getWeight // //-----------// @Override public int getWeight () { if (weight == null) { weight = 0; for (Section section : glyph.getMembers()) { weight += section.getWeight(); } } return weight; } //------------// // intersects // //------------// @Override public boolean intersects (Rectangle rectangle) { // First make a rough test if (rectangle.intersects(glyph.getBounds())) { // Then make sure at least one section intersects the rectangle for (Section section : glyph.getMembers()) { if (rectangle.intersects(section.getBounds())) { return true; } } } return false; } //-----------------// // invalidateCache // //-----------------// @Override public void invalidateCache () { signature = null; center = null; centroid = null; bounds = null; artMoments = null; geometricMoments = null; weight = null; circle = null; } //-----------// // setCircle // //-----------// @Override public void setCircle (Circle circle) { this.circle = circle; } //---------------// // setContourBox // //---------------// @Override public void setContourBox (Rectangle contourBox) { this.bounds = contourBox; } //------------------------// // setRegisteredSignature // //------------------------// @Override public void setRegisteredSignature (GlyphSignature sig) { registeredSignature = sig; } //-----------// // translate // //-----------// @Override public void translate (Point vector) { for (Section section : glyph.getMembers()) { section.translate(vector); } glyph.invalidateCache(); } //-------------------// // computeARTMoments // //-------------------// private void computeARTMoments () { // Retrieve glyph foreground points PointsCollector collector = glyph.getPointsCollector(); // Then compute the ART moments with this collector artMoments = new BasicARTMoments(); BasicARTExtractor extractor = new BasicARTExtractor(); extractor.setDescriptor(artMoments); extractor.extract( collector.getXValues(), collector.getYValues(), collector.getSize()); } //-------------------------// // computeGeometricMoments // //-------------------------// private void computeGeometricMoments () { // Retrieve glyph foreground points PointsCollector collector = glyph.getPointsCollector(); // Then compute the geometric moments with this collector try { geometricMoments = new GeometricMoments( collector.getXValues(), collector.getYValues(), collector.getSize(), getInterline()); } catch (Exception ex) { logger.warn( "Glyph #{} Cannot compute moments with unit set to 0", glyph.getId()); } } }