//----------------------------------------------------------------------------// // // // B a s i c R o i // // // //----------------------------------------------------------------------------// // <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.lag; import omr.glyph.Glyphs; import omr.glyph.facets.Glyph; import omr.math.Histogram; import omr.run.Orientation; import omr.run.Run; import omr.run.RunsTable; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Class {@code BasicRoi} implements an Roi * * @author Hervé Bitteur */ public class BasicRoi implements Roi { //~ Instance fields -------------------------------------------------------- /** Region of interest with absolute coordinates */ final Rectangle absContour; //~ Constructors ----------------------------------------------------------- //----------// // BasicRoi // //----------// /** * Define a region of interest * * @param absoluteContour the absolute contour of the region of interest, * specified in the usual (x, y, width, height) form. */ public BasicRoi (Rectangle absoluteContour) { this.absContour = absoluteContour; } //~ Methods ---------------------------------------------------------------- //--------------------// // getAbsoluteContour // //--------------------// @Override public Rectangle getAbsoluteContour () { return new Rectangle(absContour); } //-------------------// // getGlyphHistogram // //-------------------// @Override public Histogram<Integer> getGlyphHistogram (Orientation projection, Collection<Glyph> glyphs) { return getSectionHistogram( projection, Glyphs.sectionsOf(glyphs)); } //-----------------// // getRunHistogram // //-----------------// @Override public Histogram<Integer> getRunHistogram (Orientation projection, RunsTable table) { final Orientation tableOrient = table.getOrientation(); final boolean alongTheRuns = projection == tableOrient; final Histogram<Integer> histo = new Histogram<>(); final Rectangle tableContour = new Rectangle( table.getDimension()); final Rectangle inter = new Rectangle( absContour.intersection(tableContour)); final Rectangle oriInter = tableOrient.oriented(inter); final int minPos = oriInter.y; final int maxPos = (oriInter.y + oriInter.height) - 1; final int minCoord = oriInter.x; final int maxCoord = (oriInter.x + oriInter.width) - 1; for (int pos = minPos; pos <= maxPos; pos++) { List<Run> seq = table.getSequence(pos); for (Run run : seq) { final int cMin = Math.max(minCoord, run.getStart()); final int cMax = Math.min(maxCoord, run.getStop()); // Clipping on coord if (cMin <= cMax) { if (alongTheRuns) { // Along the runs histo.increaseCount(pos, cMax - cMin + 1); } else { // Across the runs for (int i = cMin; i <= cMax; i++) { histo.increaseCount(i, 1); } } } } } return histo; } //---------------------// // getSectionHistogram // //---------------------// @Override public Histogram<Integer> getSectionHistogram (Orientation projection, Collection<Section> sections) { // Split the sections into 2 populations along & across wrt projection List<Section> along = new ArrayList<>(); List<Section> across = new ArrayList<>(); for (Section section : sections) { if (section.isVertical() == projection.isVertical()) { along.add(section); } else { across.add(section); } } final Histogram<Integer> histo = new Histogram<>(); populate(histo, projection, along, true); populate(histo, projection.opposite(), across, false); return histo; } //----------// // toString // //----------// @Override public String toString () { return "Roi " + getAbsoluteContour(); } //----------// // populate // //----------// /** * Populate an histo with a collection of sections * * @param histo the histo to populate * @param sectionOrientation orientation of the sections * @param sections the collections of (parallel) sections * @param alongTheRuns true if sections are parallel to projection */ private void populate (Histogram<Integer> histo, Orientation sectionOrientation, List<Section> sections, boolean alongTheRuns) { final Rectangle oriContour = sectionOrientation.oriented(absContour); final int minPos = oriContour.y; final int maxPos = (oriContour.y + oriContour.height) - 1; final int minCoord = oriContour.x; final int maxCoord = (oriContour.x + oriContour.width) - 1; for (Section section : sections) { int pos = section.getFirstPos() - 1; for (Run run : section.getRuns()) { pos++; // Clipping on pos if ((pos < minPos) || (pos > maxPos)) { continue; } final int cMin = Math.max(minCoord, run.getStart()); final int cMax = Math.min(maxCoord, run.getStop()); // Clipping on coord if (cMin <= cMax) { if (alongTheRuns) { // Along the runs histo.increaseCount(pos, cMax - cMin + 1); } else { // Across the runs for (int i = cMin; i <= cMax; i++) { histo.increaseCount(i, 1); } } } } } } }