001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009package imagingbook.pub.regions.geometry; 010 011import java.awt.Point; 012import java.awt.geom.Point2D; 013import java.util.ArrayList; 014import java.util.Collection; 015 016import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; 017import org.apache.commons.math3.geometry.euclidean.twod.hull.ConvexHull2D; 018import org.apache.commons.math3.geometry.euclidean.twod.hull.MonotoneChain; 019 020import imagingbook.pub.regions.Contour; 021import imagingbook.pub.regions.RegionLabeling.BinaryRegion; 022 023/** 024 * This class serves to calculate the convex hull of a binary region 025 * or a closed contour, given as a sequence of point coordinates. 026 * It is based on the convex hull implementation provided by the 027 * Apache Commons Math library, in particular the classes 028 * {@link ConvexHull2D} and {@link MonotoneChain}. 029 * If a region provides an outer contour, then this is used for 030 * the convex hull computation, otherwise the entire (inner) region 031 * is used. 032 * 033 * @author W. Burger 034 * @version 2015-12-02 035 */ 036public class ConvexHull { 037 038 private final ConvexHull2D hull; 039 040 // public constructors ------------------------ 041 042 public ConvexHull(BinaryRegion r) { 043 Contour c = r.getOuterContour(); 044 if (c != null) { 045 hull = makeConvexHull(collectPointList(c)); 046 } 047 else { 048 hull = makeConvexHull(collectPointList(r)); 049 } 050 } 051 052 public ConvexHull(Contour ctr) { 053 hull = makeConvexHull(collectPointList(ctr)); 054 } 055 056 // public methods ------------------------ 057 058 public Point2D[] getVertices() { 059 return toPoint2D(hull.getVertices()); 060 } 061 062 // -------------------------------------------------------------------- 063 064 private Collection<Vector2D> collectPointList(Contour ctr) { 065// IJ.log("making hull from contour"); 066 Collection<Vector2D> points = new ArrayList<Vector2D>(); 067 for (Point p : ctr.getPointArray()) { 068 points.add(new Vector2D(p.x, p.y)); 069 } 070 return points; 071 } 072 073 private Collection<Vector2D> collectPointList(BinaryRegion r) { 074// IJ.log("making hull from all region points"); 075 Collection<Vector2D> points = new ArrayList<Vector2D>(); 076 for (Point p : r) { 077 points.add(new Vector2D(p.x, p.y)); 078 } 079 return points; 080 } 081 082 private ConvexHull2D makeConvexHull(Collection<Vector2D> points) { 083 return new MonotoneChain().generate(points); 084 } 085 086 private Point2D[] toPoint2D(Vector2D[] vecs) { 087 Point2D[] pnts = new Point2D[vecs.length]; 088 for (int i = 0; i < vecs.length; i++) { 089 pnts[i] = new Point2D.Double(vecs[i].getX(), vecs[i].getY()); 090 } 091 return pnts; 092 } 093 094}