Package org.geomajas.gwt.client.spatial

Source Code of org.geomajas.gwt.client.spatial.WorldViewTransformer

/*
* 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.gwt.client.spatial;

import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.map.MapView;
import org.geomajas.gwt.client.spatial.geometry.Geometry;
import org.geomajas.gwt.client.spatial.geometry.LineString;
import org.geomajas.gwt.client.spatial.geometry.LinearRing;
import org.geomajas.gwt.client.spatial.geometry.MultiLineString;
import org.geomajas.gwt.client.spatial.geometry.MultiPoint;
import org.geomajas.gwt.client.spatial.geometry.MultiPolygon;
import org.geomajas.gwt.client.spatial.geometry.Point;
import org.geomajas.gwt.client.spatial.geometry.Polygon;

/**
* <p>
* This class is able to transform coordinates, geometries and bounding boxes from world space to view space, and the
* other way around. World space means that the objects are expressed in the coordinate system of the map they are in,
* while view space is expressed in the pixel coordinates on the GraphicsContext.
* </p>
* <p>
* Note that this class has no support for rotating maps, perhaps in the future we might need this...
* </p>
*
* @author Pieter De Graef
*/
public class WorldViewTransformer {

  /**
   * The central viewing object on a map. It contains all the necessary parameters to calculate correct
   * transformations.
   */
  private MapView mapView;

  // -------------------------------------------------------------------------
  // Constructors:
  // -------------------------------------------------------------------------

  /**
   * Creates a transformation object, based on a <code>MapView</code> object. This <code>MapView</code> is the central
   * viewing object of a map.
   */
  public WorldViewTransformer(MapView mapView) {
    this.mapView = mapView;
  }

  // -------------------------------------------------------------------------
  // Transformation functions:
  // -------------------------------------------------------------------------

  /**
   * Transform a single coordinate from world space to view space.
   *
   * @param coordinate
   *            The coordinate in world space.
   * @return Returns a new coordinate that is the view space equivalent of the given coordinate.
   */
  public Coordinate worldToView(Coordinate coordinate) {
    if (coordinate != null) {
      Vector2D position = new Vector2D(coordinate);
      double scale = mapView.getCurrentScale();
      position.scale(scale, -scale);
      double translateX = -(mapView.getViewState().getX() * scale) + (mapView.getWidth() / 2);
      double translateY = (mapView.getViewState().getY() * scale) + (mapView.getHeight() / 2);
      position.translate(translateX, translateY);
      // TODO: implement rotation support.
      return new Coordinate(position.getX(), position.getY());
    }
    return null;
  }

  /**
   * Transform an entire geometry from world space to view space.
   *
   * @param geometry
   *            The geometry to transform.
   * @return Returns a new geometry that is the view space equivalent of the given geometry.
   */
  public Geometry worldToView(Geometry geometry) {
    if (geometry != null) {
      if (geometry instanceof Point) {
        Coordinate transformed = worldToView(geometry.getCoordinate());
        return geometry.getGeometryFactory().createPoint(transformed);
      } else if (geometry instanceof LinearRing) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = worldToView(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLinearRing(coordinates);
      } else if (geometry instanceof LineString) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = worldToView(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLineString(coordinates);
      } else if (geometry instanceof Polygon) {
        Polygon polygon = (Polygon) geometry;
        LinearRing shell = (LinearRing) worldToView(polygon.getExteriorRing());
        LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
        for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
          holes[n] = (LinearRing) worldToView(polygon.getInteriorRingN(n));
        }
        return polygon.getGeometryFactory().createPolygon(shell, holes);
      } else if (geometry instanceof MultiPoint) {
        Point[] points = new Point[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          points[n] = (Point) worldToView(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPoint(points);
      } else if (geometry instanceof MultiLineString) {
        LineString[] lineStrings = new LineString[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          lineStrings[n] = (LineString) worldToView(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiLineString(lineStrings);
      } else if (geometry instanceof MultiPolygon) {
        Polygon[] polygons = new Polygon[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          polygons[n] = (Polygon) worldToView(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPolygon(polygons);
      }
    }
    return null;
  }

  /**
   * Transform a bounding box from world- to view space.
   *
   * @param bbox
   *            The bounding box in world coordinates.
   * @returns The view space equivalent of the given bounding box.
   */
  public Bbox worldToView(Bbox bbox) {
    if (bbox != null) {
      Coordinate c1 = worldToView(bbox.getOrigin());
      Coordinate c2 = worldToView(bbox.getEndPoint());
      double x = (c1.getX() < c2.getX()) ? c1.getX() : c2.getX();
      double y = (c1.getY() < c2.getY()) ? c1.getY() : c2.getY();
      return new Bbox(x, y, Math.abs(c1.getX() - c2.getX()), Math.abs(c1.getY() - c2.getY()));
    }
    return null;
  }

  public Coordinate worldToPan(Coordinate coordinate) {
    if (coordinate != null) {
      Vector2D position = new Vector2D(coordinate);
      double scale = mapView.getCurrentScale();
      position.scale(scale, -scale);
      Coordinate panOrigin = mapView.getPanOrigin();
      position.translate(-(panOrigin.getX() * scale), panOrigin.getY() * scale);
      // TODO: implement rotation support.
      return new Coordinate(position.getX(), position.getY());
    }
    return null;
  }

  public Bbox worldToPan(Bbox bbox) {
    if (bbox != null) {
      Coordinate c1 = worldToPan(bbox.getOrigin());
      Coordinate c2 = worldToPan(bbox.getEndPoint());
      double x = (c1.getX() < c2.getX()) ? c1.getX() : c2.getX();
      double y = (c1.getY() < c2.getY()) ? c1.getY() : c2.getY();
      return new Bbox(x, y, Math.abs(c1.getX() - c2.getX()), Math.abs(c1.getY() - c2.getY()));
    }
    return null;
  }

  public Geometry worldToPan(Geometry geometry) {
    if (geometry != null) {
      if (geometry instanceof Point) {
        Coordinate transformed = worldToPan(geometry.getCoordinate());
        return geometry.getGeometryFactory().createPoint(transformed);
      } else if (geometry instanceof LinearRing) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = worldToPan(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLinearRing(coordinates);
      } else if (geometry instanceof LineString) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = worldToPan(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLineString(coordinates);
      } else if (geometry instanceof Polygon) {
        Polygon polygon = (Polygon) geometry;
        LinearRing shell = (LinearRing) worldToPan(polygon.getExteriorRing());
        LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
        for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
          holes[n] = (LinearRing) worldToPan(polygon.getInteriorRingN(n));
        }
        return polygon.getGeometryFactory().createPolygon(shell, holes);
      } else if (geometry instanceof MultiPoint) {
        Point[] points = new Point[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          points[n] = (Point) worldToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPoint(points);
      } else if (geometry instanceof MultiLineString) {
        LineString[] lineStrings = new LineString[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          lineStrings[n] = (LineString) worldToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiLineString(lineStrings);
      } else if (geometry instanceof MultiPolygon) {
        Polygon[] polygons = new Polygon[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          polygons[n] = (Polygon) worldToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPolygon(polygons);
      }
    }
    return null;
  }

  /**
   * Transform a coordinate from view space to pan space.
   *
   * @param coordinate
   *            The views pace coordinate.
   * @return Returns the pan space equivalent of the given coordinate.
   */
  public Coordinate viewToPan(Coordinate coordinate) {
    if (coordinate != null) {
      Vector2D position = new Vector2D(coordinate);
      double scale = mapView.getCurrentScale();
      Coordinate panOrigin = mapView.getPanOrigin();
     
      double translateX = (mapView.getViewState().getX() - panOrigin.getX()) * scale - (mapView.getWidth() / 2);
      double translateY = -(mapView.getViewState().getY() - panOrigin.getY()) * scale - (mapView.getHeight() / 2);
      position.translate(translateX , translateY);
        // TODO: implement rotation support.
      return new Coordinate(position.getX(), position.getY());
    }
    return null;
  }

  public Bbox viewToPan(Bbox bbox) {
    if (bbox != null) {
      Coordinate c1 = viewToPan(bbox.getOrigin());
      Coordinate c2 = viewToPan(bbox.getEndPoint());
      double x = (c1.getX() < c2.getX()) ? c1.getX() : c2.getX();
      double y = (c1.getY() < c2.getY()) ? c1.getY() : c2.getY();
      return new Bbox(x, y, Math.abs(c1.getX() - c2.getX()), Math.abs(c1.getY() - c2.getY()));
    }
    return null;
  }

  public Geometry viewToPan(Geometry geometry) {
    if (geometry != null) {
      if (geometry instanceof Point) {
        Coordinate transformed = viewToPan(geometry.getCoordinate());
        return geometry.getGeometryFactory().createPoint(transformed);
      } else if (geometry instanceof LinearRing) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = viewToPan(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLinearRing(coordinates);
      } else if (geometry instanceof LineString) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = viewToPan(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLineString(coordinates);
      } else if (geometry instanceof Polygon) {
        Polygon polygon = (Polygon) geometry;
        LinearRing shell = (LinearRing) worldToPan(polygon.getExteriorRing());
        LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
        for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
          holes[n] = (LinearRing) viewToPan(polygon.getInteriorRingN(n));
        }
        return polygon.getGeometryFactory().createPolygon(shell, holes);
      } else if (geometry instanceof MultiPoint) {
        Point[] points = new Point[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          points[n] = (Point) viewToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPoint(points);
      } else if (geometry instanceof MultiLineString) {
        LineString[] lineStrings = new LineString[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          lineStrings[n] = (LineString) viewToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiLineString(lineStrings);
      } else if (geometry instanceof MultiPolygon) {
        Polygon[] polygons = new Polygon[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          polygons[n] = (Polygon) viewToPan(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPolygon(polygons);
      }
    }
    return null;
  }

  /**
   * Transform a coordinate from view space to world space.
   *
   * @param coordinate
   *            The views pace coordinate.
   * @return Returns the world space equivalent of the given coordinate.
   */
  public Coordinate viewToWorld(Coordinate coordinate) {
    if (coordinate != null) {
      Vector2D position = new Vector2D(coordinate);
      double inverseScale = 1 / mapView.getCurrentScale();
      position.scale(inverseScale, -inverseScale);

      Bbox bounds = mapView.getBounds();
      // -cam: center X axis around cam. +bbox.w/2: to place the origin in the center of the screen
      double translateX = -mapView.getViewState().getX() + (bounds.getWidth() / 2);
      double translateY = -mapView.getViewState().getY() - (bounds.getHeight() / 2); // Inverted Y-axis here...
      position.translate(-translateX, -translateY);
      // TODO: implement rotation support.
      return new Coordinate(position.getX(), position.getY());
    }
    return null;
  }

  /**
   * Transform an entire geometry from view space to world space.
   *
   * @param geometry
   *            The geometry to transform.
   * @return Returns a new geometry that is the world space equivalent of the given geometry.
   */
  public Geometry viewToWorld(Geometry geometry) {
    if (geometry != null) {
      if (geometry instanceof Point) {
        Coordinate transformed = viewToWorld(geometry.getCoordinate());
        return geometry.getGeometryFactory().createPoint(transformed);
      } else if (geometry instanceof LinearRing) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = viewToWorld(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLinearRing(coordinates);
      } else if (geometry instanceof LineString) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = viewToWorld(geometry.getCoordinates()[i]);
        }
        return geometry.getGeometryFactory().createLineString(coordinates);
      } else if (geometry instanceof Polygon) {
        Polygon polygon = (Polygon) geometry;
        LinearRing shell = (LinearRing) viewToWorld(polygon.getExteriorRing());
        LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
        for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
          holes[n] = (LinearRing) viewToWorld(polygon.getInteriorRingN(n));
        }
        return polygon.getGeometryFactory().createPolygon(shell, holes);
      } else if (geometry instanceof MultiPoint) {
        Point[] points = new Point[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          points[n] = (Point) viewToWorld(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPoint(points);
      } else if (geometry instanceof MultiLineString) {
        LineString[] lineStrings = new LineString[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          lineStrings[n] = (LineString) viewToWorld(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiLineString(lineStrings);
      } else if (geometry instanceof MultiPolygon) {
        Polygon[] polygons = new Polygon[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          polygons[n] = (Polygon) viewToWorld(geometry.getGeometryN(n));
        }
        return geometry.getGeometryFactory().createMultiPolygon(polygons);
      }
    }
    return null;
  }

  /**
   * Transform a bounding box from view space to world space.
   *
   * @param bbox
   *            The bounding box in view coordinates.
   * @returns The world space equivalent of the given bounding box.
   */
  public Bbox viewToWorld(Bbox bbox) {
    if (bbox != null) {
      Coordinate c1 = viewToWorld(bbox.getOrigin());
      Coordinate c2 = viewToWorld(bbox.getEndPoint());
      double x = (c1.getX() < c2.getX()) ? c1.getX() : c2.getX();
      double y = (c1.getY() < c2.getY()) ? c1.getY() : c2.getY();
      return new Bbox(x, y, Math.abs(c1.getX() - c2.getX()), Math.abs(c1.getY() - c2.getY()));
    }
    return null;
  }

  /**
   * Transform a bounding box by a given <code>Matrix</code>.
   *
   * @param bbox
   *            The bounding box to transform.
   * @param matrix
   *            The transformation matrix.
   * @return Returns a transformed bounding box, or null if one of the given parameters was null.
   */
  public Bbox transform(Bbox bbox, Matrix matrix) {
    if (bbox != null) {
      Coordinate c1 = transform(bbox.getOrigin(), matrix);
      Coordinate c2 = transform(bbox.getEndPoint(), matrix);
      double x = (c1.getX() < c2.getX()) ? c1.getX() : c2.getX();
      double y = (c1.getY() < c2.getY()) ? c1.getY() : c2.getY();
      return new Bbox(x, y, Math.abs(c1.getX() - c2.getX()), Math.abs(c1.getY() - c2.getY()));
    }
    return null;
  }

  /**
   * Transform a single coordinate by a given <code>Matrix</code>.
   *
   * @param coordinate
   *            The coordinate to transform.
   * @param matrix
   *            The transformation matrix.
   * @return Returns a transformed coordinate, or null if one of the given parameters was null.
   */
  public Coordinate transform(Coordinate coordinate, Matrix matrix) {
    if (coordinate != null && matrix != null) {
      double x = matrix.getXx() * coordinate.getX() + matrix.getXy() * coordinate.getY() + matrix.getDx();
      double y = matrix.getYx() * coordinate.getX() + matrix.getYy() * coordinate.getY() + matrix.getDy();
      return new Coordinate(x, y);
    }
    return null;
  }

  public Geometry transform(Geometry geometry, Matrix matrix) {
    if (geometry != null) {
      if (geometry instanceof Point) {
        Coordinate transformed = transform(geometry.getCoordinate(), matrix);
        return geometry.getGeometryFactory().createPoint(transformed);
      } else if (geometry instanceof LinearRing) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = transform(geometry.getCoordinates()[i], matrix);
        }
        return geometry.getGeometryFactory().createLinearRing(coordinates);
      } else if (geometry instanceof LineString) {
        Coordinate[] coordinates = new Coordinate[geometry.getNumPoints()];
        for (int i = 0; i < coordinates.length; i++) {
          coordinates[i] = transform(geometry.getCoordinates()[i], matrix);
        }
        return geometry.getGeometryFactory().createLineString(coordinates);
      } else if (geometry instanceof Polygon) {
        Polygon polygon = (Polygon) geometry;
        LinearRing shell = (LinearRing) transform(polygon.getExteriorRing(), matrix);
        LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
        for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
          holes[n] = (LinearRing) transform(polygon.getInteriorRingN(n), matrix);
        }
        return polygon.getGeometryFactory().createPolygon(shell, holes);
      } else if (geometry instanceof MultiPoint) {
        Point[] points = new Point[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          points[n] = (Point) transform(geometry.getGeometryN(n), matrix);
        }
        return geometry.getGeometryFactory().createMultiPoint(points);
      } else if (geometry instanceof MultiLineString) {
        LineString[] lineStrings = new LineString[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          lineStrings[n] = (LineString) transform(geometry.getGeometryN(n), matrix);
        }
        return geometry.getGeometryFactory().createMultiLineString(lineStrings);
      } else if (geometry instanceof MultiPolygon) {
        Polygon[] polygons = new Polygon[geometry.getNumGeometries()];
        for (int n = 0; n < geometry.getNumGeometries(); n++) {
          polygons[n] = (Polygon) transform(geometry.getGeometryN(n), matrix);
        }
        return geometry.getGeometryFactory().createMultiPolygon(polygons);
      }
    }
    return null;
  }
}
TOP

Related Classes of org.geomajas.gwt.client.spatial.WorldViewTransformer

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.