/** * OrbisGIS is a java GIS application dedicated to research in GIScience. * OrbisGIS is developed by the GIS group of the DECIDE team of the * Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>. * * The GIS group of the DECIDE team is located at : * * Laboratoire Lab-STICC – CNRS UMR 6285 * Equipe DECIDE * UNIVERSITÉ DE BRETAGNE-SUD * Institut Universitaire de Technologie de Vannes * 8, Rue Montaigne - BP 561 56017 Vannes Cedex * * OrbisGIS is distributed under GPL 3 license. * * Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488) * Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285) * * This file is part of OrbisGIS. * * OrbisGIS 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. * * OrbisGIS 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 * OrbisGIS. If not, see <http://www.gnu.org/licenses/>. * * For more information, please consult: <http://www.orbisgis.org/> * or contact directly: * info_at_ orbisgis.org */ package org.orbisgis.coremap.renderer.se.stroke; import java.awt.Graphics2D; import java.awt.Shape; import java.io.IOException; import java.util.Map; import javax.xml.bind.JAXBElement; import net.opengis.se._2_0.core.*; import org.orbisgis.coremap.map.MapTransform; import org.orbisgis.coremap.renderer.se.AbstractSymbolizerNode; import org.orbisgis.coremap.renderer.se.SeExceptions.InvalidStyle; import org.orbisgis.coremap.renderer.se.UomNode; import org.orbisgis.coremap.renderer.se.common.Uom; import org.orbisgis.coremap.renderer.se.parameter.ParameterException; /** * Style description for linear features (Area or Line) * * @author Maxence Laurent, Alexis Guéganno. */ public abstract class Stroke extends AbstractSymbolizerNode implements UomNode { private Uom uom; private boolean linearRapport; private boolean offsetRapport; /** * Instanciate a new default {@code Stroke}, with linear and offset rapports * set to false. */ protected Stroke(){ linearRapport = false; offsetRapport = false; } /** * Instanciate a new {@code Stroke}, using the JAXB {@code StrokeType} given * in argument. * @param s */ protected Stroke (StrokeType s){ this(); if (s.getExtension() != null) { for (ExtensionParameterType param : s.getExtension().getExtensionParameter()) { /* Only to handle old styles... */ if (param.getName().equalsIgnoreCase("linearRapport")) { linearRapport = param.getContent().equalsIgnoreCase("on"); } else if (param.getName().equalsIgnoreCase("offsetRapport")) { offsetRapport = param.getContent().equalsIgnoreCase("on"); } } } if (s.isLinearRapport() != null){ linearRapport = s.isLinearRapport(); } } /** * Create a new stroke based on the jaxbelement * * @param s XML Stroke * @return Java Stroke */ public static Stroke createFromJAXBElement(JAXBElement<? extends StrokeType> s) throws InvalidStyle{ if (s.getDeclaredType() == PenStrokeType.class){ return new PenStroke((JAXBElement<PenStrokeType>)s); } else if (s.getDeclaredType() == GraphicStrokeType.class){ return new GraphicStroke((JAXBElement<GraphicStrokeType>)s); }else if (s.getDeclaredType() == CompoundStrokeType.class){ return new CompoundStroke((JAXBElement<CompoundStrokeType>)s); }else if (s.getDeclaredType() == TextStrokeType.class){ return new TextStroke((JAXBElement<TextStrokeType>)s); } //As s.getDeclaredType() os a StrokeType, we are supposed to never throw this Exception... throw new InvalidStyle("Trying to create a Stroke from an invalid input"); } /** * When delineating closed shapes (i.e. a ring), indicate, whether or not, * the length of stroke elements shall be scaled in order to make the pattern * appear a integral number of time. This will make the junction more aesthetical * * @return <cdoe>true</code> if the stroke elements' length shall be scaled, * <code>false</code> otherwise. */ public boolean isLengthRapport() { return linearRapport; } /** * Determines if we want to use an length rapport or not. * @param lengthRapport */ public void setLengthRapport(boolean lengthRapport) { this.linearRapport = lengthRapport; } /** * When delineating a line with a perpendicular offset, indicate whether or not * stroke element shall following the initial line (rapport=true) or should only * be based on the offseted line (rapport=false); * * @return true if offseted element shall follow initial line */ public boolean isOffsetRapport() { return offsetRapport; } /** * Determines if we want to use an offset rapport or not. * @param offsetRapport */ public void setOffsetRapport(boolean offsetRapport) { this.offsetRapport = offsetRapport; } /** * Apply the present Stroke to the geometry stored in sds, at index fid, in * graphics g2. * @param g2 draw within this graphics2d * @param map * @param shp stroke this shape (note this is note a JTS Geometry, because * stroke can be used to delineate graphics (such as MarkGraphic, * PieChart or AxisChart) * @param selected emphasis or not the stroke (e.g invert colours) * @param mt the well known mapTransform * @param offset perpendicular offset to apply * @throws ParameterException * @throws IOException */ public abstract void draw(Graphics2D g2, Map<String,Object> map, Shape shp, boolean selected, MapTransform mt, double offset) throws ParameterException, IOException; /** * Get a JAXB representation of this {@code Label} * @return * A {@code JAXBElement} that contains a {@code LabelType} specialization. */ public abstract JAXBElement<? extends StrokeType> getJAXBElement(); /** * Fill the {@code LabelType} given in argument with this {@code Label}'s * properties. */ protected final void setJAXBProperties(StrokeType s) { ObjectFactory of = new ObjectFactory(); ExtensionType exts = of.createExtensionType(); s.setLinearRapport(this.isLengthRapport()); /*ExtensionParameterType linRap = of.createExtensionParameterType(); linRap.setName("linearRapport"); if (this.linearRapport){ linRap.setContent("on"); } else { linRap.setContent("off"); } exts.getExtensionParameter().add(linRap); */ ExtensionParameterType offRap = of.createExtensionParameterType(); offRap.setName("offsetRapport"); if (this.offsetRapport){ offRap.setContent("on"); } else { offRap.setContent("off"); } exts.getExtensionParameter().add(offRap); s.setExtension(exts); } /** * Returns the stroke pattern natural length, in pixel unit * @param map * @param shp * @param mt * @return * @throws ParameterException * @throws IOException */ public abstract Double getNaturalLength(Map<String,Object> map, Shape shp, MapTransform mt) throws ParameterException, IOException; /** * same as getNaturalLength, but in some case (i.e. PenStroke) the natural length * to use in not the same as returned by the latter : Especially for PenStroke : * To compute a tile for hatching, we need to know the length of the pen stroke * (i.e. only when the stroke is dashed...), but to embed such a stroke in a compound, * the natural length shall be +Inf * * @param map * @param shp * @param mt * @return * @throws ParameterException * @throws IOException */ public Double getNaturalLengthForCompound(Map<String,Object> map, Shape shp, MapTransform mt) throws ParameterException, IOException { return getNaturalLength(map, shp, mt); } @Override public Uom getUom() { if (uom != null) { return uom; } else if(getParent() instanceof UomNode){ return ((UomNode)getParent()).getUom(); } else { return Uom.PX; } } @Override public void setUom(Uom u) { uom = u; } @Override public Uom getOwnUom() { return uom; } }