package org.openjump.core.ui.plugin.tools; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.util.Assert; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.model.MeasureLayerFinder; import com.vividsolutions.jump.workbench.ui.Viewport; import com.vividsolutions.jump.workbench.ui.renderer.style.Style; import com.vividsolutions.jump.workbench.ui.renderer.style.VertexStyle; import de.latlon.deejump.plugin.style.VertexStylesFactory; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.font.TextLayout; import java.awt.geom.Point2D; import java.text.DecimalFormat; /** * A special Style for usage in the AdvancedMeasureTool. * This Style paints the area and distance in the center of the Geometry's * Envelope. At every vertex the actual distance will be painted. * * @author Matthias Scholz <ms@jammerhund.de> */ public class MeasurementStyle implements Style { private Layer layer; private boolean enabled = false; private String areaAttribute = MeasureLayerFinder.FEATURE_ATTRIBUTE_AREA; private String lengthAttribute = MeasureLayerFinder.FEATURE_ATTRIBUTE_LENGTH; // summary variables private boolean paintSummaryLength = AdvancedMeasureOptionsPanel.DEFAULT_SUMMARY_PAINT_LENGTH; private boolean paintSummaryArea = AdvancedMeasureOptionsPanel.DEFAULT_SUMMARY_PAINT_AREA; private Font summaryFont = AdvancedMeasureOptionsPanel.DEFAULT_SUMMARY_FONT; private Color summaryColor = AdvancedMeasureOptionsPanel.DEFAULT_SUMMARY_COLOR; // vertex variables private boolean vertexPaintDistance = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_PAINT_DISTANCE; private Font vertexFont = new Font("Dialog", Font.PLAIN, 12); private Color vertexFontColor = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FONT_COLOR; private boolean vertexPaint = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_PAINT; private Color vertexFirstColor = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FIRST_COLOR; private String vertexFirstForm = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FIRST_FORM; private int vertexFirstSize = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FIRST_SIZE; private Color vertexFollowingColor = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FOLLOWING_COLOR; private String vertexFollowingForm = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FOLLOWING_FORM; private int vertexFollowingSize = AdvancedMeasureOptionsPanel.DEFAULT_VERTEX_FOLLOWING_SIZE; private VertexStyle vertexStyleFirst; private VertexStyle vertexStyleFollowing; public MeasurementStyle() { // create the both VertexStyle's vertexStyleFirst = VertexStylesFactory.createVertexStyle(vertexFirstForm); vertexStyleFirst.setFillColor(vertexFirstColor); vertexStyleFirst.setAlpha(255); vertexStyleFirst.setSize(vertexFirstSize); vertexStyleFollowing = VertexStylesFactory.createVertexStyle(vertexFollowingForm); vertexStyleFollowing.setFillColor(vertexFollowingColor); vertexStyleFollowing.setAlpha(255); vertexStyleFollowing.setSize(vertexFollowingSize); } public void paint(Feature f, Graphics2D g, Viewport viewport) throws Exception { Point2D centerPoint; TextLayout layout; // get area and length values Double area = (Double) f.getAttribute(areaAttribute); Double length = (Double) f.getAttribute(lengthAttribute); // formatting area and length values DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(); String formatPattern = "#,##0.00"; // adaptive format pattern, thanks to Michaƫl Michaud for his idea! if (length >= 10) { formatPattern = "#,##0.00"; } else if (length >= 1) { formatPattern = "#,##0.000"; } else if (length >= 0.1) { formatPattern = "#,##0.0000"; } else if (length >= 0.01) { formatPattern ="#,##0.00000"; } else formatPattern = "#,##0.000000"; decimalFormat.applyPattern(formatPattern); // length per vertex and vertex himself Coordinate[] coordinates = f.getGeometry().getCoordinates(); double actualLength = 0; // in area mode we do not paint the last vertex, because we paint only the first one (which is at the same coordinate) int numberOfCoordinates = coordinates.length; for (int i = 0; i < numberOfCoordinates; i++) { centerPoint = viewport.toViewPoint(coordinates[i]); if (i > 0) { // paint the vertex only if vertexPaint is true AND ( in area mode it's not the last vertex OR in distance mode ) if (vertexPaint && (area > 0 && i < numberOfCoordinates - 1 || area == 0)) { vertexStyleFollowing.paint(g, centerPoint); } if (vertexPaintDistance) { actualLength += coordinates[i].distance(coordinates[i-1]); layout = new TextLayout(decimalFormat.format(actualLength) + "m", vertexFont, g.getFontRenderContext()); g.setColor(vertexFontColor); layout.draw(g, (float) centerPoint.getX() - layout.getAdvance() / 2, (float) centerPoint.getY() - layout.getAscent()); } } else { if (vertexPaint) { vertexStyleFirst.paint(g, centerPoint); } if (vertexPaintDistance) { layout = new TextLayout(decimalFormat.format(actualLength) + "m", vertexFont, g.getFontRenderContext()); g.setColor(vertexFontColor); layout.draw(g, (float) centerPoint.getX() - layout.getAdvance() / 2, (float) centerPoint.getY() + layout.getAscent() + 5); } } } // paint summary or not ;-) // paint the area (if area measurement) and length g.setColor(summaryColor); centerPoint = viewport.toViewPoint(f.getGeometry().getEnvelope().getCentroid().getCoordinate()); double x = centerPoint.getX(); double y = centerPoint.getY(); if (paintSummaryLength) { layout = new TextLayout(I18N.get("org.openjump.core.ui.plugin.tools.MeasurementStyle.distance") + " " + decimalFormat.format(length) + "m", summaryFont, g.getFontRenderContext()); x -= layout.getAdvance() / 2; layout.draw(g, (float) x, (float) y); y += layout.getAscent(); } if (area > 0 && paintSummaryArea) { layout = new TextLayout(I18N.get("org.openjump.core.ui.plugin.tools.MeasurementStyle.area") + " " + decimalFormat.format(area) + "m\u00B2", summaryFont, g.getFontRenderContext()); if (!paintSummaryLength) x -= layout.getAdvance() / 2; layout.draw(g, (float) x, (float) y); } } public void initialize(Layer layer) { this.layer = layer; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return enabled; } @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException ex) { Assert.shouldNeverReachHere(); return null; } } /** * @return the areaAttribute */ public String getAreaAttribute() { return areaAttribute; } /** * @param areaAttribute the areaAttribute to set */ public void setAreaAttribute(String areaAttribute) { this.areaAttribute = areaAttribute; } /** * @return the lengthAttribute */ public String getLengthAttribute() { return lengthAttribute; } /** * @param lengthAttribute the lengthAttribute to set */ public void setLengthAttribute(String lengthAttribute) { this.lengthAttribute = lengthAttribute; } /** * @return the font */ public Font getSummaryFont() { return summaryFont; } /** * @param font the font to set */ public void setSummaryFont(Font font) { this.summaryFont = font; } /** * @return the summaryColor */ public Color getSummaryColor() { return summaryColor; } /** * @param summaryColor the summaryColor to set */ public void setSummaryColor(Color summaryColor) { this.summaryColor = summaryColor; } /** * @return the paintSummary */ public boolean isPaintSummaryLength() { return paintSummaryLength; } /** * @param paintSummary the paintSummary to set */ public void setPaintSummaryLength(boolean paintSummary) { this.paintSummaryLength = paintSummary; } /** * @return the paintSummaryArea */ public boolean isPaintSummaryArea() { return paintSummaryArea; } /** * @param paintSummaryArea the paintSummaryArea to set */ public void setPaintSummaryArea(boolean paintSummaryArea) { this.paintSummaryArea = paintSummaryArea; } /** * @return the vertexFont */ public Font getVertexFont() { return vertexFont; } /** * @param vertexFont the vertexFont to set */ public void setVertexFont(Font vertexFont) { this.vertexFont = vertexFont; } /** * @return the vertexFontColor */ public Color getVertexFontColor() { return vertexFontColor; } /** * @param vertexFontColor the vertexFontColor to set */ public void setVertexFontColor(Color vertexFontColor) { this.vertexFontColor = vertexFontColor; } /** * @return the vertexPaintDistance */ public boolean isVertexPaintDistance() { return vertexPaintDistance; } /** * @param vertexPaintDistance the vertexPaintDistance to set */ public void setVertexPaintDistance(boolean vertexPaintDistance) { this.vertexPaintDistance = vertexPaintDistance; } /** * @return the vertexPaint */ public boolean isVertexPaint() { return vertexPaint; } /** * @param vertexPaint the vertexPaint to set */ public void setVertexPaint(boolean vertexPaint) { this.vertexPaint = vertexPaint; } /** * @return the vertexFirstColor */ public Color getVertexFirstColor() { return vertexFirstColor; } /** * @param vertexFirstColor the vertexFirstColor to set */ public void setVertexFirstColor(Color vertexFirstColor) { this.vertexFirstColor = vertexFirstColor; vertexStyleFirst.setFillColor(vertexFirstColor); } /** * @return the vertexFirstForm */ public String getVertexFirstForm() { return vertexFirstForm; } /** * @param vertexFirstForm the vertexFirstForm to set */ public void setVertexFirstForm(String vertexFirstForm) { this.vertexFirstForm = vertexFirstForm; vertexStyleFirst = VertexStylesFactory.createVertexStyle(vertexFirstForm); vertexStyleFirst.setFillColor(vertexFirstColor); vertexStyleFirst.setAlpha(255); vertexStyleFirst.setSize(vertexFirstSize); } /** * @return the vertexFirstSize */ public int getVertexFirstSize() { return vertexFirstSize; } /** * @param vertexFirstSize the vertexFirstSize to set */ public void setVertexFirstSize(int vertexFirstSize) { this.vertexFirstSize = vertexFirstSize; vertexStyleFirst.setSize(vertexFirstSize); } /** * @return the vertexFollowingColor */ public Color getVertexFollowingColor() { return vertexFollowingColor; } /** * @param vertexFollowingColor the vertexFollowingColor to set */ public void setVertexFollowingColor(Color vertexFollowingColor) { this.vertexFollowingColor = vertexFollowingColor; vertexStyleFollowing.setFillColor(vertexFollowingColor); } /** * @return the vertexFollowingForm */ public String getVertexFollowingForm() { return vertexFollowingForm; } /** * @param vertexFollowingForm the vertexFollowingForm to set */ public void setVertexFollowingForm(String vertexFollowingForm) { this.vertexFollowingForm = vertexFollowingForm; vertexStyleFollowing = VertexStylesFactory.createVertexStyle(vertexFollowingForm); vertexStyleFollowing.setFillColor(vertexFollowingColor); vertexStyleFollowing.setAlpha(255); vertexStyleFollowing.setSize(vertexFollowingSize); } /** * @return the vertexFollowingSize */ public int getVertexFollowingSize() { return vertexFollowingSize; } /** * @param vertexFollowingSize the vertexFollowingSize to set */ public void setVertexFollowingSize(int vertexFollowingSize) { this.vertexFollowingSize = vertexFollowingSize; vertexStyleFollowing.setSize(vertexFollowingSize); } }