/*
* Copyright (C) 2014 Alec Dhuse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package co.foldingmap.map;
import co.foldingmap.Logger;
import co.foldingmap.map.labeling.LabelManager;
import co.foldingmap.map.themes.MapTheme;
import co.foldingmap.map.vector.Coordinate;
import co.foldingmap.map.vector.LatLonBox;
import co.foldingmap.map.vector.NodeMap;
import java.util.ArrayList;
/**
* Bundles various aspects of how the map is viewed into one class
*
* @author Alec
*/
public class MapView {
//Values for Map wraping for Longitude < -180 and > 180.
public static final int NO_WRAP = 0;
public static final int WRAP_LEFT = -1;
public static final int WRAP_RIGHT = 1;
private ArrayList<Coordinate> viewPortCoordinates;
private boolean displayAll; //Insure that the whole map is drawn, does not affect labeling
private boolean dragging, showPointsInMapObject;
private float mouseLatitude, mouseLongitude;
private LabelManager labelManager;
private MapProjection projection;
private MapTheme mapTheme;
private NodeMap nodeMap;
/**
* Constructor for objects of class MapView.
* Uses the MercatorProjection as the default Projection.
*/
public MapView() {
this.displayAll = false;
this.dragging = false;
this.showPointsInMapObject = false;
this.projection = new MercatorProjection();
this.labelManager = new LabelManager();
}
public MapView(MapProjection projection) {
this.displayAll = false;
this.dragging = false;
this.labelManager = new LabelManager();
this.projection = projection;
this.showPointsInMapObject = false;
}
/**
* Returns if the Map should show object component points.
*
* @return
*/
public boolean arePointsShown() {
return showPointsInMapObject;
}
/**
* Creates a copy of this MapView.
*
* @return
*/
@Override
public MapView clone() {
MapView mapViewCopy = new MapView(projection);
mapViewCopy.setShowPoints(showPointsInMapObject);
mapViewCopy.setLabelManager(this.labelManager);
mapViewCopy.setMapTheme(this.mapTheme);
return mapViewCopy;
}
/**
* Returns if all the MapObjects are to be drawn. Normal drawing only
* draws objects within the View Port. But when outputting images this
* may need to be true.
*
* @return
*/
public boolean displayAll() {
return displayAll;
}
/**
* Returns the Height of the View Port.
*
* @return
*/
public float getDisplayHeight() {
return projection.getDisplayHeight();
}
/**
* Returns the Width of the View Port.
*
* @return
*/
public float getDisplayWidth() {
return projection.getDisplayWidth();
}
/**
* Returns the Maps Label Manager.
*
* @return
*/
public LabelManager getLabelManager() {
return this.labelManager;
}
/**
* Returns a Coordinate of the last click location of the mouse.
*
* @return
*/
public Coordinate getLastMouseClickCoordinate() {
return new Coordinate(0, mouseLatitude, mouseLongitude);
}
/**
* Translates a screen point (x, y) to a Latitude.
*
* @param x
* @param y
* @return
*/
public float getLatitude(float x, float y) {
return (float) projection.getLatitude(x, y);
}
/**
* Translates a screen point (x, y) to a Longitude.
*
* @param x
* @param y
* @return
*/
public float getLongitude(float x, float y) {
return (float) projection.getLongitude(x, y);
}
/**
* Returns the Projection being used by the Map.
*
* @return
*/
public MapProjection getMapProjection() {
return projection;
}
/**
* Returns the Map's Theme
*
* @return
*/
public MapTheme getMapTheme() {
return mapTheme;
}
/**
* Returns the View Port dimensions as a LatLonAltBox.
* If any problems occur a view bounds for the while globe is returned.
*
* @return
*/
public LatLonBox getViewBounds() {
float north, south, east, west;
LatLonBox viewBounds;
try {
north = this.getLatitude(0, 0);
south = this.getLatitude(0, this.getDisplayHeight());
east = this.getLongitude(this.getDisplayWidth(), 0);
west = this.getLongitude(0, 0);
while (east > 180)
east = -180 + ((180 - east) * -1);
while (west < -180)
west = 180 - Math.abs(west + 180);
viewBounds = new LatLonBox(north, south, east, west);
return viewBounds;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in MapView.getViewBounds() - " + e);
return new LatLonBox(90, -90, 180, -180);
}
}
/**
* Returns all coordinates within this view port.
*
* @return
*/
public ArrayList<Coordinate> getViewPortCoordinates() {
return viewPortCoordinates;
}
/**
* Translates a Coordinate (Altitude, Latitude, Longitude) to a
* screen x value.
*
* @param c
* @param wrap
* @return
*/
public float getX(Coordinate c, int wrap) {
Coordinate m1, m2; //Meridians
double idl, x;
double r, d, n;
m1 = new Coordinate(0, 0, -180);
m2 = new Coordinate(0, 0, 180);
//non-modified value
x = projection.getX(c);
switch (wrap) {
case NO_WRAP:
break;
case WRAP_LEFT:
idl = projection.getX(m1);
r = projection.getX(m2);
d = x - r;
n = d + idl;
x = n;
break;
case WRAP_RIGHT:
idl = projection.getX(m1);
r = projection.getX(m2);
d = x - idl;
n = d + r;
x = n;
break;
}
return (float) (x);
}
/**
* Translates a Coordinate (Altitude, Latitude, Longitude) to a
* screen y value.
*
* @param c
* @return
*/
public float getY(Coordinate c) {
return (float) projection.getY(c);
}
/**
* Returns the current zoom level being used to display the map.
* Values are dependant on the projection being used.
*
* @return
*/
public float getZoomLevel() {
return projection.getZoomLevel();
}
/**
* Returns if the map is being dragged. This is to allow different levels
* of rendering quality or object displaying while dragging the map.
*
* @return
*/
public boolean isDragging() {
return dragging;
}
/**
* Shifts the map reference of the projection.
* This is used to construct the view port.
*
* @param x
* @param y
*/
public void shiftMapReference(double x, double y) {
this.projection.shiftMapReference(x, y);
this.update();
}
/**
* Set if all objects are to be drawn, not just those within the View Port.
*
* @param displayAll
*/
public void setDisplayAll(boolean displayAll) {
this.displayAll = displayAll;
}
/**
* Set if the map is being dragged.
*
* @param dragging
*/
public void setDragging(boolean dragging) {
this.dragging = dragging;
}
/**
* Sets the LabelManager to be used when rendering this map.
*
* @param labelManager
*/
public void setLabelManager(LabelManager labelManager) {
this.labelManager = labelManager;
}
/**
* Set the location on the map and screen of the last mouse click.
*
* @param mouseX
* @param mouseY
*/
public void setLastMouseClickPosition(float mouseX, float mouseY) {
this.mouseLatitude = getLatitude(mouseX, mouseY);
this.mouseLongitude = getLongitude(mouseX, mouseY);
}
/**
* Sets the MapProjection to be used when rendering this map.
*
* @param projection
*/
public void setMapProjection(MapProjection projection) {
this.projection = projection;
}
/**
* Set the theme to use drawing the map.
*
* @param theme
*/
public void setMapTheme(MapTheme theme) {
this.mapTheme = theme;
}
/**
* Sets the Node map for this MapView
*
* @param nodeMap
*/
public void setNodeMap(NodeMap nodeMap) {
this.nodeMap = nodeMap;
}
/**
* Set if MapObjects component points are to be drawn.
*
* @param showPoints
*/
public void setShowPoints(boolean showPoints) {
this.showPointsInMapObject = showPoints;
}
/**
* Updates the view point coordinates and maybe some other stuff later.
*/
public void update() {
viewPortCoordinates = nodeMap.getCoordinatesWithinBoundary(getViewBounds());
}
}