package com.revolsys.swing.map.layer.record.renderer;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.beans.PropertyChangeEvent;
import java.util.Map;
import javax.swing.Icon;
import com.revolsys.collection.map.MapEx;
import com.revolsys.geometry.model.BoundingBox;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.Polygon;
import com.revolsys.geometry.model.impl.PointDoubleXYOrientation;
import com.revolsys.geometry.model.segment.Segment;
import com.revolsys.geometry.model.vertex.Vertex;
import com.revolsys.io.BaseCloseable;
import com.revolsys.logging.Logs;
import com.revolsys.swing.Icons;
import com.revolsys.swing.component.Form;
import com.revolsys.swing.map.Viewport2D;
import com.revolsys.swing.map.layer.AbstractLayer;
import com.revolsys.swing.map.layer.LayerRenderer;
import com.revolsys.swing.map.layer.record.AbstractRecordLayer;
import com.revolsys.swing.map.layer.record.LayerRecord;
import com.revolsys.swing.map.layer.record.style.MarkerStyle;
import com.revolsys.swing.map.layer.record.style.marker.Marker;
import com.revolsys.swing.map.layer.record.style.panel.MarkerStylePanel;
import com.revolsys.util.Property;
public class MarkerStyleRenderer extends AbstractRecordLayerRenderer {
private static final Icon ICON = Icons.getIcon("style_marker");
private static <G extends Geometry> G getGeometry(final Viewport2D viewport, final G geometry) {
final BoundingBox viewExtent = viewport.getBoundingBox();
if (geometry != null) {
if (!viewExtent.isEmpty()) {
final BoundingBox geometryExtent = geometry.getBoundingBox();
if (geometryExtent.intersects(viewExtent)) {
final GeometryFactory geometryFactory = viewport.getGeometryFactory2dFloating();
return geometry.convertGeometry(geometryFactory);
}
}
}
return null;
}
public static PointDoubleXYOrientation getMarkerLocation(final Viewport2D viewport,
final Geometry geometry, final MarkerStyle style) {
final String placementType = style.getMarkerPlacementType();
return getPointWithOrientation(viewport, geometry, placementType);
}
public static void renderMarker(final Viewport2D viewport, final Geometry geometry,
final MarkerStyle style) {
try (
BaseCloseable transformClosable = viewport.setUseModelCoordinates(false)) {
@SuppressWarnings("deprecation")
final Graphics2D graphics = viewport.getGraphics();
if (graphics != null && geometry != null) {
if ("vertices".equals(style.getMarkerPlacementType())) {
renderMarkerVertices(viewport, graphics, geometry, style);
} else if ("segments".equals(style.getMarkerPlacementType())) {
renderMarkerSegments(viewport, graphics, geometry, style);
} else {
for (int i = 0; i < geometry.getGeometryCount(); i++) {
final Geometry part = geometry.getGeometry(i);
if (part instanceof Point) {
final Point point = (Point)part;
renderMarker(viewport, graphics, point, style, 0);
} else if (part instanceof LineString) {
final LineString line = (LineString)part;
renderMarker(viewport, graphics, line, style);
} else if (part instanceof Polygon) {
final Polygon polygon = (Polygon)part;
renderMarker(viewport, graphics, polygon, style);
}
}
}
}
}
}
private static void renderMarker(final Viewport2D viewport, final Graphics2D graphics,
final LineString line, final MarkerStyle style) {
final PointDoubleXYOrientation point = getMarkerLocation(viewport, line, style);
if (point != null) {
final double orientation = point.getOrientation();
renderMarker(viewport, graphics, point, style, orientation);
}
}
/**
* Point must be in the same geometry factory as the view.
*
* @param viewport
* @param graphics
* @param point
* @param style
*/
public static void renderMarker(final Viewport2D viewport, final Graphics2D graphics, Point point,
final MarkerStyle style, final double orientation) {
point = getGeometry(viewport, point);
if (Property.hasValue(point)) {
final Paint paint = graphics.getPaint();
try (
BaseCloseable transformClosable = viewport.setUseModelCoordinates(graphics, false)) {
final Marker marker = style.getMarker();
final double x = point.getX();
final double y = point.getY();
marker.render(viewport, graphics, style, x, y, orientation);
} catch (final Throwable e) {
Logs.debug(MarkerStyleRenderer.class, "Unable to render marker: " + style, e);
} finally {
graphics.setPaint(paint);
}
}
}
private static void renderMarker(final Viewport2D viewport, final Graphics2D graphics,
final Polygon polygon, final MarkerStyle style) {
final Point point = polygon.getPointWithin();
renderMarker(viewport, graphics, point, style, 0);
}
public static void renderMarkers(final Viewport2D viewport, final Graphics2D graphics,
LineString line, final MarkerStyle styleFirst, final MarkerStyle styleLast,
final MarkerStyle styleVertex) {
if (line != null) {
final GeometryFactory geometryFactory = viewport.getGeometryFactory2dFloating();
line = line.convertGeometry(geometryFactory);
for (final Vertex vertex : line.vertices()) {
MarkerStyle style;
if (vertex.isFrom()) {
style = styleFirst;
} else if (vertex.isTo()) {
style = styleLast;
} else {
style = styleVertex;
}
final double orientation = vertex.getOrientaton();
renderMarker(viewport, graphics, vertex, style, orientation);
}
}
}
public static final void renderMarkerSegments(final Viewport2D viewport,
final Graphics2D graphics, Geometry geometry, final MarkerStyle style) {
geometry = getGeometry(viewport, geometry);
if (Property.hasValue(geometry)) {
final String orientationType = style.getMarkerOrientationType();
if ("none".equals(orientationType)) {
for (final Segment segment : geometry.segments()) {
final Point point = segment.midPoint();
renderMarker(viewport, graphics, point, style, 0);
}
} else {
for (final Segment segment : geometry.segments()) {
final Point point = segment.midPoint();
final double orientation = segment.getOrientaton();
renderMarker(viewport, graphics, point, style, orientation);
}
}
}
}
public static final void renderMarkerVertices(final Viewport2D viewport,
final Graphics2D graphics, Geometry geometry, final MarkerStyle style) {
geometry = getGeometry(viewport, geometry);
if (Property.hasValue(geometry)) {
final String orientationType = style.getMarkerOrientationType();
if ("none".equals(orientationType)) {
for (final Vertex vertex : geometry.vertices()) {
renderMarker(viewport, graphics, vertex, style, 0);
}
} else {
for (final Vertex vertex : geometry.vertices()) {
final double orientation = vertex.getOrientaton();
renderMarker(viewport, graphics, vertex, style, orientation);
}
}
}
}
private MarkerStyle style = new MarkerStyle();
public MarkerStyleRenderer(final AbstractRecordLayer layer, final LayerRenderer<?> parent) {
super("markerStyle", "Marker Style", layer, parent);
setIcon(ICON);
}
public MarkerStyleRenderer(final AbstractRecordLayer layer, final LayerRenderer<?> parent,
final MarkerStyle style) {
super("markerStyle", "Marker Style", layer, parent);
setStyle(style);
}
public MarkerStyleRenderer(final AbstractRecordLayer layer, final MarkerStyle style) {
this(layer, null, style);
}
public MarkerStyleRenderer(final Map<String, ? extends Object> properties) {
super("markerStyle", "Marker Style");
setIcon(ICON);
setProperties(properties);
}
@Override
public MarkerStyleRenderer clone() {
final MarkerStyleRenderer clone = (MarkerStyleRenderer)super.clone();
if (this.style != null) {
clone.setStyle(this.style.clone());
}
return clone;
}
public MarkerStyle getStyle() {
return this.style;
}
@Override
public Icon newIcon() {
if (this.style == null) {
return ICON;
} else {
return this.style.newIcon();
}
}
@Override
public Form newStylePanel() {
return new MarkerStylePanel(this);
}
@Override
public void propertyChange(final PropertyChangeEvent event) {
final Object source = event.getSource();
if (source == this.style) {
final Icon icon = this.style.newIcon();
setIcon(icon);
}
super.propertyChange(event);
}
@Override
public void renderRecord(final Viewport2D viewport, final BoundingBox visibleArea,
final AbstractLayer layer, final LayerRecord record) {
if (isVisible(record)) {
final Geometry geometry = record.getGeometry();
renderMarker(viewport, geometry, this.style);
}
}
@Override
public void setProperties(final Map<String, ? extends Object> properties) {
super.setProperties(properties);
if (this.style != null) {
this.style.setProperties(properties);
final Icon icon = this.style.newIcon();
setIcon(icon);
}
}
public void setStyle(final MarkerStyle style) {
if (this.style != null) {
this.style.removePropertyChangeListener(this);
}
this.style = style;
if (this.style != null) {
this.style.addPropertyChangeListener(this);
}
firePropertyChange("style", null, style);
refreshIcon();
}
@Override
public MapEx toMap() {
final MapEx map = super.toMap();
if (this.style != null) {
final Map<String, Object> styleMap = this.style.toMap();
map.putAll(styleMap);
}
return map;
}
}