/* AWE - Amanzi Wireless Explorer * http://awe.amanzi.org * (C) 2008-2009, AmanziTel AB * * This library is provided under the terms of the Eclipse Public License * as described at http://www.eclipse.org/legal/epl-v10.html. Any use, * reproduction or distribution of the library constitutes recipient's * acceptance of this agreement. * * This library is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package org.amanzi.awe.distribution.model.type.impl; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.LinkedHashSet; import java.util.Set; import org.amanzi.awe.distribution.model.type.impl.internal.AbstractDistributionType; import org.amanzi.awe.distribution.model.type.impl.internal.SimpleRange; import org.amanzi.awe.filters.impl.RangeFilter; import org.amanzi.awe.filters.impl.RangeFilter.RangeFilterType; import org.amanzi.neo.models.statistics.IPropertyStatisticalModel; import org.amanzi.neo.nodetypes.INodeType; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Range; import org.apache.commons.math3.util.Precision; /** * TODO Purpose of * <p> * </p> * * @author Nikolay Lagutko (nikolay.lagutko@amanzitel.com) * @since 1.0.0 */ public class NumberDistributionType extends AbstractDistributionType<SimpleRange> { private static final int DOUBLE_SCALE = 4; private static final double PRECISION_DELTA = 0.00001; private static final NumberFormat DECIMAL_FORMAT = new DecimalFormat("#.###"); private final NumberDistributionRange numberDistributionRange; private Set<SimpleRange> ranges; /** * @param model * @param nodeType * @param propertyName * @param canChangeColors */ public NumberDistributionType(final IPropertyStatisticalModel model, final INodeType nodeType, final String propertyName, final NumberDistributionRange numberDistributionRange, final Select select) { super(model, nodeType, propertyName, select); this.numberDistributionRange = numberDistributionRange; } @Override public String getName() { return numberDistributionRange.toString(); } @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Set<SimpleRange> getRanges() { if (ranges == null) { ranges = new LinkedHashSet<SimpleRange>(); double min = Double.MAX_VALUE; double max = -Double.MAX_VALUE; for (final Object value : getModel().getPropertyStatistics().getValues(getNodeType(), getPropertyName())) { final double currentValue = ((Number)value).doubleValue(); min = Math.min(min, currentValue); max = Math.max(max, currentValue); } final double step = getStep(min, max, numberDistributionRange.getDelta()); while (Precision.compareTo(max, min, PRECISION_DELTA) > 0) { final boolean includeMax = Precision.compareTo(max, min + step, PRECISION_DELTA) > 0; final double curMax = includeMax ? increaseMinimum(min, step) : max; final RangeFilterType filterType = includeMax ? RangeFilterType.INCLUDE_START_AND_END : RangeFilterType.INCLUDE_START_EXCLUDE_END; final Range range = Range.between(min, curMax); final RangeFilter filter = new RangeFilter(getPropertyName(), range, filterType); ranges.add(new SimpleRange(getNumberDistributionRangeName(min, curMax), filter)); min = increaseMinimum(min, step); } } return ranges; } protected double increaseMinimum(final double previousMinimum, final double step) { return previousMinimum + step; } private double getStep(final double min, final double max, final int delta) { double res = (max - min) / delta; final double scaleNum = Math.pow(10, DOUBLE_SCALE); res = Math.round(res * scaleNum) / scaleNum; return res; } protected String getNumberDistributionRangeName(final double min, final double max) { final StringBuilder sb = new StringBuilder(); sb.append(DECIMAL_FORMAT.format(min)).append(" - ").append(DECIMAL_FORMAT.format(max)); return sb.toString(); } @Override public boolean equals(final Object o) { if (o instanceof NumberDistributionType) { final NumberDistributionType type = (NumberDistributionType)o; return super.equals(type) && ObjectUtils.equals(numberDistributionRange, type.numberDistributionRange); } return false; } }