/** * 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.transform; import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; 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.SymbolizerNode; import org.orbisgis.coremap.renderer.se.UomNode; import org.orbisgis.coremap.renderer.se.common.Uom; import org.orbisgis.coremap.renderer.se.parameter.ParameterException; /** * * This class contains a collection of {@code Transformation}s. * * @author Maxence Laurent, Alexis Guéganno */ public class Transform extends AbstractSymbolizerNode implements UomNode { private Uom uom; private AffineTransform consolidated; private ArrayList<Transformation> transformations; /** * Gets a {@code String} representation of this {@code Transform}, by * printing the {@code String} representation of each inner * {@code Transformation}. * @return * A {@code String} representation of this {@code Transform} */ @Override public String toString() { String r = ""; for (Transformation t : transformations) { r += t.toString(); } return r; } /** * Build a new {@code Transform}, that does not contain any {@code * Transformation} */ public Transform() { transformations = new ArrayList<Transformation>(); consolidated = null; } /** * Build a new {@code Transform}, that will conatin only the * {@code Transformation} represented by {@code t}. * @param t * @throws org.orbisgis.coremap.renderer.se.SeExceptions.InvalidStyle */ public Transform(TransformType t) throws InvalidStyle { transformations = new ArrayList<Transformation>(); consolidated = null; if (t.getUom() != null) { this.setUom(Uom.fromOgcURN(t.getUom())); } for (Object o : t.getTranslateOrRotateOrScale()) { Transformation trans = getTransformationFromJAXB(o); if(trans != null){ this.transformations.add(trans); trans.setParent(this); } } } private Transformation getTransformationFromJAXB(Object o) throws InvalidStyle { if (o instanceof TranslateType) { return new Translate((TranslateType) o); } else if (o instanceof RotateType) { return new Rotate((RotateType) o); } else if (o instanceof ScaleType) { return new Scale((ScaleType) o); } else if (o instanceof MatrixType) { return new Matrix((MatrixType) o); } return null; } /** * Move the ith {@code Transformation} up in this {@code Transform}. * @param i * @return * {@code true} if the ith exists and has been moved successfully (ie * if i represents an existing element that is not the last one.) */ public boolean moveDown(int i) { if (i >= 0 && i < transformations.size() - 1) { Transformation remove = transformations.remove(i); transformations.add(i + 1, remove); return true; } else { return false; } } /** * Move the ith {@code Transformation} down in this {@code Transform}. * @param i * @return * {@code true} if the ith exists and has been moved successfully (ie * if i represents an existing element that is not the first one.) */ public boolean moveUp(int i) { if (i > 0 && i < transformations.size()) { Transformation remove = transformations.remove(i); transformations.add(i - 1, remove); return true; } else { return false; } } /** * Return an affine transformation for java Shape object. * The purpose is to transfom se.graphics * @param isForSpatialFeatures * @param map * @param mt * @param width * @param height * @return * @throws ParameterException * @throws IOException */ public AffineTransform getGraphicalAffineTransform(boolean isForSpatialFeatures, Map<String,Object> map, MapTransform mt, Double width, Double height) throws ParameterException, IOException { //return consolidateTrasformations(false).getGraphicalAffineTransform(); this.consolidateTransformations(map, isForSpatialFeatures, mt, width, height); return consolidated; } /** * Ensure that this {@code Transform} instance contains actually the * representation of the combination of its inner {@code Transformation} * instances. * This method must be called after each modification of one of its transformations ! * @param sds * @param fid * @param forGeometries * @param mt * @param width * @param height * @throws ParameterException * @throws IOException */ public void consolidateTransformations(Map<String,Object> map, boolean forGeometries, MapTransform mt, Double width, Double height) throws ParameterException, IOException { // Result is Identity consolidated = new AffineTransform(); for (Transformation t : transformations) { if (!forGeometries || t.allowedForGeometries()) { AffineTransform at = t.getAffineTransform(map, this.getUom(), mt, width, height); consolidated.preConcatenate(at); } } } /** * Add a {@code Transformation} to this {@code Transform}. * @param t */ public void addTransformation(Transformation t) { transformations.add(t); } /** * Remove the ith {@code Transformation} of this {@code Transform} * @param i * @return * {@code true} if the removal has been successful. */ public boolean removeTransformation(int i) { try { transformations.remove(i); return true; } catch (Exception e) { return false; } } /** * Get the number of {@code Transformation}s registered in this * {@code Transform}. * @return */ public int getNumTransformation() { return transformations.size(); } /** * Get the ith {@code Transformation} registered in this {@code * Transform}. * @param i * @return */ public Transformation getTransformation(int i) { return transformations.get(i); } /** * Get a new representation of this {@code Transform} as a JAXB * {@code TransformType} * @return */ public TransformType getJAXBType() { TransformType t = new TransformType(); if (getOwnUom() != null) { t.setUom(getOwnUom().toURN()); } List<Object> list = t.getTranslateOrRotateOrScale(); for (Transformation tr : transformations) { list.add(tr.getJAXBType()); } return t; } @Override public List<SymbolizerNode> getChildren() { List<SymbolizerNode> ls = new ArrayList<SymbolizerNode>(); ls.addAll(transformations); return ls; } @Override public Uom getUom() { if (uom != null) { return uom; } else if(getParent() instanceof UomNode){ return ((UomNode)getParent()).getUom(); } else { return Uom.PX; } } @Override public Uom getOwnUom() { return uom; } @Override public void setUom(Uom uom) { this.uom = uom; } }