package uk.me.parabola.mkgmap.osmstyle.function; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import uk.me.parabola.imgfmt.app.Coord; import uk.me.parabola.mkgmap.reader.osm.Element; import uk.me.parabola.mkgmap.reader.osm.MultiPolygonRelation; import uk.me.parabola.mkgmap.reader.osm.Way; /** * Calculates the area size of a polygon in garmin units ^ 2. * * if orderByDecreasingArea then the area of the polygon has already been * calculated and we use it here. * To be totally consistent, ie no possible difference to mkgmap behaviour when * --order-by-decreasing-area is not set, this flag should be set from the option; * However it is now considered that 'fullArea' is what the user might expect, rather * than various different values for the same original because of clipping and cutting to * expose holes. * * @author WanMil */ public class AreaSizeFunction extends CachedFunction { private final DecimalFormat nf = new DecimalFormat("0.0#####################", DecimalFormatSymbols.getInstance(Locale.US)); private final boolean orderByDecreasingArea = true; public AreaSizeFunction() { super(null); } protected String calcImpl(Element el) { if (el instanceof Way) { Way w = (Way)el; // a non closed way has size 0 if (w.hasEqualEndPoints() == false) { return "0"; } double areaSize; if (orderByDecreasingArea) { long fullArea = w.getFullArea(); if (fullArea == Long.MAX_VALUE) return "0"; // convert from high prec to value in map units areaSize = (double) fullArea / (2 * (1<<Coord.DELTA_SHIFT) * (1<<Coord.DELTA_SHIFT)); areaSize = Math.abs(areaSize); } else areaSize = MultiPolygonRelation.calcAreaSize(w.getPoints()); return nf.format(areaSize); } return null; } public String getName() { return "area_size"; } public boolean supportsWay() { return true; } }