/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wms;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.image.palette.InverseColorMapOp;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.renderer.lite.RendererUtilities;
/**
* Extends DefaultMapContext to provide the whole set of request parameters a WMS GetMap request can
* have.
*
* <p>
* In particular, adds holding for the following parameter values:
*
* <ul>
* <li>WIDTH</li>
* <li>HEIGHT</li>
* <li>BGCOLOR</li>
* <li>TRANSPARENT</li>
* </ul>
* </p>
*
* @author Gabriel Roldan
* @author Simone Giannecchini - GeoSolutions SAS
* @version $Id$
*/
public class WMSMapContent extends MapContent {
/** requested map image width in output units (pixels) */
private int mapWidth;
/** requested map image height in output units (pixels) */
private int mapHeight;
/** Requested BGCOLOR, defaults to white according to WMS spec */
private Color bgColor = Color.white;
/** true if background transparency is requested */
private boolean transparent;
/** suggested output tile size */
private int tileSize = -1;
/** map rotation in degrees */
private double angle;
public int getTileSize() {
return tileSize;
}
public void setTileSize(int tileSize) {
this.tileSize = tileSize;
}
/**
* the rendering buffer used to avoid issues with tiled rendering and big strokes that may cross
* tile boundaries
*/
private int buffer;
/**
* The {@link InverseColorMapOp} that actually does the color inversion.
*/
private InverseColorMapOp paletteInverter;
private GetMapRequest request; // hold onto it so we can grab info from it
// (request URL etc...)
public WMSMapContent() {
super();
}
public WMSMapContent(GetMapRequest req) {
super();
request = req;
}
public WMSMapContent(Layer[] layers) {
super();
for (Layer layer : layers) {
addLayer(layer);
}
}
public Color getBgColor() {
return this.bgColor;
}
public void setBgColor(Color bgColor) {
this.bgColor = bgColor;
}
public int getMapHeight() {
return this.mapHeight;
}
public void setMapHeight(int mapHeight) {
this.mapHeight = mapHeight;
}
public int getMapWidth() {
return this.mapWidth;
}
public void setMapWidth(int mapWidth) {
this.mapWidth = mapWidth;
}
public boolean isTransparent() {
return this.transparent;
}
public void setTransparent(boolean transparent) {
this.transparent = transparent;
}
public GetMapRequest getRequest() {
return request;
}
public void setRequest(GetMapRequest request) {
this.request = request;
}
public int getBuffer() {
return buffer;
}
public void setBuffer(int buffer) {
this.buffer = buffer;
}
public InverseColorMapOp getPaletteInverter() {
return paletteInverter;
}
public void setPaletteInverter(InverseColorMapOp paletteInverter) {
this.paletteInverter = paletteInverter;
}
/**
* The clockwise rotation angle of the map, in degrees
*
* @return
*/
public double getAngle() {
return angle;
}
public void setAngle(double rotation) {
this.angle = rotation;
}
/**
* Returns the transformation going from the map area space to the screen space taking into
* account map rotation
*
* @return
*/
public AffineTransform getRenderingTransform() {
Rectangle paintArea = new Rectangle(0, 0, getMapWidth(), getMapHeight());
ReferencedEnvelope dataArea = getViewport().getBounds();
AffineTransform tx;
if (getAngle() != 0.0) {
tx = new AffineTransform();
tx.translate(paintArea.width / 2, paintArea.height / 2);
tx.rotate(Math.toRadians(getAngle()));
tx.translate(-paintArea.width / 2, -paintArea.height / 2);
tx.concatenate(RendererUtilities.worldToScreenTransform(dataArea, paintArea));
} else {
tx = RendererUtilities.worldToScreenTransform(dataArea, paintArea);
}
return tx;
}
/**
* Returns the actual area that should be drawn taking into account the map rotation account map
* rotation
*
* @return
*/
public ReferencedEnvelope getRenderingArea() {
ReferencedEnvelope dataArea = getViewport().getBounds();
if (getAngle() == 0)
return dataArea;
AffineTransform tx = new AffineTransform();
double offsetX = dataArea.getMinX() + dataArea.getWidth() / 2;
double offsetY = dataArea.getMinY() + dataArea.getHeight() / 2;
tx.translate(offsetX, offsetY);
tx.rotate(Math.toRadians(getAngle()));
tx.translate(-offsetX, -offsetY);
Rectangle2D dataAreaShape = new Rectangle2D.Double(dataArea.getMinX(), dataArea.getMinY(),
dataArea.getWidth(), dataArea.getHeight());
Rectangle2D transformedBounds = tx.createTransformedShape(dataAreaShape).getBounds2D();
return new ReferencedEnvelope(transformedBounds, dataArea.getCoordinateReferenceSystem());
}
/**
* Get the contact information associated with this context, returns an empty string if
* contactInformation has not been set.
*
* @return the ContactInformation or an empty string if not present
*/
public String getContactInformation(){
String contact = (String) getUserData().get("contact");
return contact == null ? "" : contact;
}
/**
* Set contact information associated with this class.
*
* @param contactInformation
* the ContactInformation.
*/
public void setContactInformation(final String contactInformation){
getUserData().put("contact", contactInformation);
}
/**
* Get an array of keywords associated with this context, returns an empty array if no keywords
* have been set. The array returned is a copy, changes to the returned array won't influence
* the MapContextState
*
* @return array of keywords
*/
public String[] getKeywords(){
Object obj = getUserData().get("keywords");
if (obj == null) {
return new String[0];
} else if (obj instanceof String) {
String keywords = (String) obj;
return keywords.split(",");
} else if (obj instanceof String[]) {
String keywords[] = (String[]) obj;
String[] copy = new String[keywords.length];
System.arraycopy(keywords, 0, copy, 0, keywords.length);
return copy;
} else if (obj instanceof Collection) {
Collection<String> keywords = (Collection) obj;
return keywords.toArray(new String[keywords.size()]);
} else {
return new String[0];
}
}
/**
* Set an array of keywords to associate with this context.
*
* @param keywords
* the Keywords.
*/
public void setKeywords(final String[] keywords){
getUserData().put("keywords", keywords);
}
/**
* Get the abstract which describes this interface, returns an empty string if this has not been
* set yet.
*
* @return The Abstract or an empty string if not present
*/
public String getAbstract(){
String description = (String) getUserData().get("abstract");
return description == null ? "" : description;
}
/**
* Set an abstract which describes this context.
*
* @param conAbstract
* the Abstract.
*/
public void setAbstract(final String contextAbstract){
getUserData().put("abstract", contextAbstract);
}
}