Package org.geomajas.puregwt.client.map.gadget

Source Code of org.geomajas.puregwt.client.map.gadget.ScalebarGadget

/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/

package org.geomajas.puregwt.client.map.gadget;

import org.geomajas.configuration.client.ClientMapInfo;
import org.geomajas.configuration.client.UnitType;
import org.geomajas.puregwt.client.map.MapGadget;
import org.geomajas.puregwt.client.map.ViewPort;
import org.geomajas.puregwt.client.map.gfx.ScreenContainer;
import org.vaadin.gwtgraphics.client.shape.Path;
import org.vaadin.gwtgraphics.client.shape.Rectangle;
import org.vaadin.gwtgraphics.client.shape.Text;
import org.vaadin.gwtgraphics.client.shape.path.LineTo;
import org.vaadin.gwtgraphics.client.shape.path.MoveTo;

import com.google.gwt.i18n.client.NumberFormat;

/**
* MapGadget implementation that shows a scale bar on the map.
*
* @author Pieter De Graef
*/
public class ScalebarGadget implements MapGadget {

  private static final double METERS_IN_MILE = 1609.344d;

  private static final double METERS_IN_YARD = 0.9144d;

  private static final double FEET_IN_METER = 3.2808399d;

  private static final int MAX_SIZE_IN_PIXELS = 125;

  private int[] lengths = new int[] { 1, 2, 5, 10, 25, 50, 100, 250, 500, 750, 1000, 2000, 5000, 10000, 25000, 50000,
      75000, 100000, 250000, 500000, 750000, 1000000, 2000000, 5000000, 10000000 };

  // position in lengths array up to where to test for yards (larger values is for miles)
  private static final int YARD_STARTING_POINT = 11;

  private Rectangle backGround;

  private Path distanceMarker;

  private Text distance;

  private UnitType unitType;

  private double unitLength;

  private ViewPort viewPort;

  // -- for internal use, holds the last calculated best value
  private int widthInUnits;

  // -- for internal use, holds the last calculated best value
  private int widthInPixels;

  // -- for internal use, for UnitType.ENGLISH only
  private boolean widthInUnitsIsMiles;

  // ------------------------------------------------------------------------
  // Constructor:
  // ------------------------------------------------------------------------

  public ScalebarGadget(ClientMapInfo mapInfo) {
    this.unitType = mapInfo.getDisplayUnitType();
    this.unitLength = mapInfo.getUnitLength();
  }

  // ------------------------------------------------------------------------
  // MapGadget implementation:
  // ------------------------------------------------------------------------

  public void onDraw(ViewPort viewPort, ScreenContainer container) {
    this.viewPort = viewPort;

    backGround = new Rectangle(0, viewPort.getMapHeight() - 22, 1, 22);
    backGround.setStrokeOpacity(0);
    backGround.setFillOpacity(0.65);
    container.add(backGround);

    distanceMarker = new Path(3, viewPort.getMapHeight() - 18);
    distanceMarker.lineRelativelyTo(0, 14);
    distanceMarker.lineRelativelyTo(92, 0);
    distanceMarker.lineRelativelyTo(0, -14);
    distanceMarker.setFillOpacity(0);
    container.add(distanceMarker);

    distance = new Text(8, viewPort.getMapHeight() - 8, "");
    distance.setFontSize(12);
    distance.setStrokeOpacity(0);
    distance.setFillColor("#000000");
    container.add(distance);

    onScale();
  }

  public void onTranslate() {
  }

  public void onScale() {
    calculateBestFit(viewPort.getScale());
    distance.setText(formatUnits(widthInUnits));
    backGround.setWidth(widthInPixels + 6);
    distanceMarker.setStep(2, new LineTo(true, widthInPixels, 0));
  }

  public void onResize() {
    backGround.setY(viewPort.getMapHeight() - 22);
    distanceMarker.setStep(0, new MoveTo(false, 3, viewPort.getMapHeight() - 18));
    distance.setY(viewPort.getMapHeight() - 8);
  }

  public void onDestroy() {
  }

  // ------------------------------------------------------------------------
  // Private methods:
  // ------------------------------------------------------------------------

  /**
   * Find the rounded value (from the lengths array) which fits the closest into the maxSizeInPixels for the given
   * scale.
   *
   * @param scale
   * @return closest fit in units (will be miles or yards for English, m for metric, unit for CRS)
   */
  private void calculateBestFit(double scale) {
    int len = 0;
    long px = 0;
    if (UnitType.ENGLISH.equals(unitType)) {
      // try miles.
      for (int i = lengths.length - 1; i > -1; i--) {
        len = this.lengths[i];
        px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
        if (px < MAX_SIZE_IN_PIXELS) {
          break;
        }
      }
      // try yards.
      if (px > MAX_SIZE_IN_PIXELS) {
        for (int i = YARD_STARTING_POINT; i > -1; i--) {
          len = this.lengths[i];
          px = Math.round((len * scale / unitLength) * METERS_IN_YARD);
          if (px < MAX_SIZE_IN_PIXELS) {
            break;
          }
        }
        widthInUnitsIsMiles = false;
      } else {
        widthInUnitsIsMiles = true;
      }
    } else if (UnitType.ENGLISH_FOOT.equals(unitType)) {
       // try miles.
      for (int i = lengths.length - 1; i > -1; i--) {
        len = this.lengths[i];
        px = Math.round((len * scale / unitLength) * METERS_IN_MILE);
        if (px < MAX_SIZE_IN_PIXELS) {
          break;
        }
      }
      // try feet.
      if (px > MAX_SIZE_IN_PIXELS) {
        for (int i = YARD_STARTING_POINT; i > -1; i--) {
          len = this.lengths[i];
          px = Math.round((len * scale / unitLength) / FEET_IN_METER);
          if (px < MAX_SIZE_IN_PIXELS) {
            break;
          }
        }
        widthInUnitsIsMiles = false;
      } else {
        widthInUnitsIsMiles = true;
      }
    } else {
      for (int i = lengths.length - 1; i > -1; i--) {
        len = this.lengths[i];
        px = Math.round(len * scale / unitLength);
        if (px < MAX_SIZE_IN_PIXELS) {
          break;
        }
      }
    }

    widthInUnits = len;
    widthInPixels = (int) px;
  }

  /**
   * format to human readable string converting to unit type.
   *
   * @param units
   * @return
   */
  private String formatUnits(int units) {
    switch (unitType) {
      case ENGLISH:
        return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " yd");
      case ENGLISH_FOOT:
        return NumberFormat.getDecimalFormat().format(units) + (widthInUnitsIsMiles ? " mi" : " ft");
      case METRIC:
        if (units < 10000) {
          return NumberFormat.getDecimalFormat().format(units) + " m";
        } else {
          return NumberFormat.getDecimalFormat().format((double) units / 1000) + " km";
        }

      case CRS:
        return NumberFormat.getDecimalFormat().format(units) + " u";

      default:
        return "??";
    }
  }
}
TOP

Related Classes of org.geomajas.puregwt.client.map.gadget.ScalebarGadget

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.