/* * 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.visualization; import co.foldingmap.map.vector.LinearRing; import co.foldingmap.map.vector.VectorObject; import co.foldingmap.map.vector.MapPoint; import co.foldingmap.map.vector.LineString; import co.foldingmap.map.vector.Polygon; import co.foldingmap.Logger; import co.foldingmap.dataStructures.PropertyValuePair; import co.foldingmap.map.MapView; import co.foldingmap.map.themes.ColorRamp; import co.foldingmap.map.themes.ColorStyle; import co.foldingmap.map.themes.MapTheme; import co.foldingmap.xml.XmlOutput; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.HashMap; /** * A visualization that displays a circle with color and/or area dependant on * a dynamic value; * * @author Alec */ public class BubblePoint extends MapPoint { private boolean changeSize; private float minValue, maxValue; private int maxRadius; private String colorRampID, colorVariable, sizeVariable; private VectorObject object; public BubblePoint(VectorObject object, String colorRampID, String colorVariable, String sizeVariable) { this.changeSize = true; this.colorRampID = colorRampID; this.colorVariable = colorVariable; this.maxRadius = 10; this.sizeVariable = sizeVariable; this.minValue = 4; this.maxValue = 10; this.object = object; if (object instanceof MapPoint) { this.coordinates.add(object.getCoordinateList().get(0)); } else if (object instanceof LinearRing) { this.coordinates.add(object.getBoundingBox().getCenter()); } else if (object instanceof LineString) { this.coordinates.add(object.getBoundingBox().getCenter()); } else if (object instanceof Polygon) { this.coordinates.add(object.getBoundingBox().getCenter()); } else { this.coordinates.add(object.getBoundingBox().getCenter()); } } /** * Adds a custom data field to the object like City_population * * @param pvp The Property Value pair with the info. */ @Override public void addCustomDataField(PropertyValuePair pvp) { object.addCustomDataField(pvp); } /** * Adds a custom data field to the object like City_population * * @param String The field name. * @param String The field value. */ @Override public void addCustomDataField(String field, String value) { object.addCustomDataField(field, value); } /** * Adds Custom Data Fields to the object. * * @param customDataFields An ArrayList of PropertyValuePairs to set as custom data fields. */ @Override public void addCustomDataFields(ArrayList<PropertyValuePair> customDataFields) { object.addCustomDataFields(customDataFields); } /** * * @param g2 * @param mapView * @param colorStyle */ @Override public void drawObject(Graphics2D g2, MapView mapView, ColorStyle colorStyle) { Color drawColor, outlineColor; float x, y, radius;; Point2D pCenter; pCenter = getCoordinateList().get(0).getCenterPoint(); radius = getRadius(); x = (float) (pCenter.getX() - radius / 2.0); y = (float) (pCenter.getY() - radius / 2.0); pointCenter = new Ellipse2D.Float(x, y, radius, radius); //Center BubblePoint if (this.highlighted == false) { drawColor = getColor(mapView.getMapTheme()); outlineColor = drawColor.darker(); } else { drawColor = getColor(mapView.getMapTheme()).darker(); outlineColor = new Color(68, 68, 68, 200); } g2.setColor(outlineColor); g2.draw(pointCenter); if (mapView.getMapProjection().isLeftShown()) { x = (float) (pCenter.getX() - radius / 2.0); y = (float) (pCenter.getY() - radius / 2.0); pointLeft = new Ellipse2D.Float(x, y, radius, radius); g2.draw(pointLeft); } if (mapView.getMapProjection().isRightShown()) { x = (float) (pCenter.getX() - radius / 2.0); y = (float) (pCenter.getY() - radius / 2.0); pointRight = new Ellipse2D.Float(x, y, radius, radius); g2.draw(pointRight); } g2.setColor(drawColor); g2.fill(pointCenter); if (mapView.getMapProjection().isLeftShown()) g2.fill(pointLeft); if (mapView.getMapProjection().isRightShown()) g2.fill(pointRight); } /** * Returns an ArrayList of at the custom data associated with this object. * * @return */ @Override public ArrayList<PropertyValuePair> getAllCustomData() { return object.getAllCustomData(); } /** * Gets all the custom data field names associated with this object. * * @return Vector<String> A Vector containing all of the Custom Field Names. */ @Override public ArrayList<String> getAllCustomDataFields() { return object.getAllCustomDataFields(); } /** * Returns the Color from the ColorRamp to be used for this BubblePoint. * * @param mapTheme * @return */ public Color getColor(MapTheme mapTheme) { Color color; ColorRamp colorRamp; String value; colorRamp = mapTheme.getColorRamp(colorRampID); if (colorRamp != null) { value = object.getCustomDataFieldValue(colorVariable); color = colorRamp.getColor(value); } else { color = Color.RED; } return color; } /** * Returns a HashMap of all the CustomeDataFields * * @return HashMap<String, String> The custom data fields. */ @Override public HashMap<String, String> getCustomDataFields() { return object.getCustomDataFields(); } /** * Returns the value for a specified custom field name * * @param String The field name for the associated value. * @return String The value for the passed in fieldName. */ @Override public String getCustomDataFieldValue(String fieldName) { return object.getCustomDataFieldValue(fieldName); } /** * Returns this Objects Name. * * @return */ @Override public String getName() { return object.getName(); } /** * Returns the current radius of this bubble. * * @return */ public float getRadius() { float radius, range, value; try { if (changeSize) { value = Float.parseFloat(object.getCustomDataFieldValue(sizeVariable)); range = maxValue - minValue; radius = (value / range) * maxRadius; radius += 2; //TODO: This should probably have a Square Root in it somwhere } else { radius = 4; } return radius; } catch (Exception e) { Logger.log(Logger.ERR, "Error in BubblePoint.getRadius() - " + e); return 1; } } /** * Removes a custom data field from this object. * * @param field */ @Override public void removeCustomDataField(String field) { object.removeCustomDataField(field); } /** * Sets the variable to be used when deciding the color of the bubble. * * @param colorVariable */ public void setColorVariable(String colorVariable) { this.colorVariable = colorVariable; } /** * Adds a custom data field to the object like City_population * * @param String The field name. * @param String The field value. */ @Override public void setCustomDataField(String field, String value) { object.setCustomDataField(field, value); } /** * Sets the Custom Data Field HashMap for this VectorObject. * * @param customDataFields */ @Override public void setCustomDataFields(HashMap<String, String> customDataFields) { object.setCustomDataFields(customDataFields); } /** * Sets the variable to be used when adjusting the size of the bubble. * * @param sizeVariable */ public void setSizeVariable(String sizeVariable) { this.sizeVariable = sizeVariable; } @Override public void toXML(XmlOutput kmlWriter) { } }