/** * 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.util.*; import javax.xml.bind.JAXBElement; import net.opengis.se._2_0.core.MatrixType; import net.opengis.se._2_0.core.ObjectFactory; 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.common.Uom; import org.orbisgis.coremap.renderer.se.parameter.ParameterException; import org.orbisgis.coremap.renderer.se.parameter.SeParameterFactory; import org.orbisgis.coremap.renderer.se.parameter.real.RealLiteral; import org.orbisgis.coremap.renderer.se.parameter.real.RealParameter; import org.orbisgis.coremap.renderer.se.parameter.real.RealParameterContext; import org.orbisgis.coremap.renderer.se.visitors.FeaturesVisitor; /** * Affine Transformation based on RealParameters * Warning: conversion to pixel unit will give strange behavior ! * <p> The matrix as the following form :</p> * <p>{@code [A C E]}<br/> * {@code|B D F|}<br/> * {@code[0 0 1]}<br/></p> * <p>Note that the matrix is filled with {@code RealParameter} instances, not * with {@code double} values. * * @author Maxence Laurent, Alexis Guéganno */ public final class Matrix extends AbstractSymbolizerNode implements Transformation { private static final double DEF_A = 1.0; private static final double DEF_B = 0.0; private static final double DEF_C = 0.0; private static final double DEF_D = 1.0; private static final double DEF_E = 0.0; private static final double DEF_F = 0.0; private RealParameter a; private RealParameter b; private RealParameter c; private RealParameter d; private RealParameter e; private RealParameter f; /** * Create an identity matrix * */ public Matrix() { setA(new RealLiteral(DEF_A)); setB(new RealLiteral(DEF_B)); setC(new RealLiteral(DEF_C)); setD(new RealLiteral(DEF_D)); setE(new RealLiteral(DEF_E)); setF(new RealLiteral(DEF_F)); } /** * Create a new <code>Matrix</code> from <code>double</code> values. * @param a * @param b * @param c * @param d * @param e * @param f */ public Matrix(double a, double b, double c, double d, double e, double f) { setA(new RealLiteral(a)); setB(new RealLiteral(b)); setC(new RealLiteral(c)); setD(new RealLiteral(d)); setE(new RealLiteral(e)); setF(new RealLiteral(f)); } /** * Create a new <code>Matrix</code> from <code>RealParameter</code> instances. * <code>null</code> values will be transformed to <code>new RealLiteral(0.0)</code> * @param a * @param b * @param c * @param d * @param e * @param f */ public Matrix(RealParameter a, RealParameter b, RealParameter c, RealParameter d, RealParameter e, RealParameter f) { this(); if (a != null) { setA(a); } if (b != null) { setB(b); } if (c != null) { setC(c); } if (d != null) { setD(d); } if (e != null) { setE(e); } if (f != null) { setF(f); } } /** * Creates a hard copy of <code>m</code> * @param m * @throws org.orbisgis.coremap.renderer.se.SeExceptions.InvalidStyle */ Matrix(MatrixType m) throws InvalidStyle { this(); if (m.getA() != null) { this.setA(SeParameterFactory.createRealParameter(m.getA())); } if (m.getB() != null) { this.setB(SeParameterFactory.createRealParameter(m.getB())); } if (m.getC() != null) { this.setC(SeParameterFactory.createRealParameter(m.getC())); } if (m.getD() != null) { this.setD(SeParameterFactory.createRealParameter(m.getD())); } if (m.getE() != null) { this.setE(SeParameterFactory.createRealParameter(m.getE())); } if (m.getF() != null) { this.setF(SeParameterFactory.createRealParameter(m.getF())); } } /** * Get the A parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getA() { return a; } /** * Set the A parameter of this {@code Matrix}, as defined in the * description of the class. * @param a * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of A is * set to 0. */ public void setA(RealParameter a) { if (a == null) { this.a = new RealLiteral(0.0); } else { this.a = a; } this.a.setContext(RealParameterContext.REAL_CONTEXT); a.setParent(this); } /** * Get the B parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getB() { return b; } /** * Set the B parameter of this {@code Matrix}, as defined in the * description of the class. * @param b * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of B is * set to 0. */ public void setB(RealParameter b) { if (b == null) { this.b = new RealLiteral(0.0); } else { this.b = b; } this.b.setContext(RealParameterContext.REAL_CONTEXT); this.b.setParent(this); } /** * Get the C parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getC() { return c; } /** * Set the C parameter of this {@code Matrix}, as defined in the * description of the class. * @param c * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of C is * set to 0. */ public void setC(RealParameter c) { if (c == null) { this.c = new RealLiteral(0.0); } else { this.c = c; } this.c.setContext(RealParameterContext.REAL_CONTEXT); this.c.setParent(this); } /** * Get the D parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getD() { return d; } /** * Set the D parameter of this {@code Matrix}, as defined in the * description of the class. * @param d * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of D is * set to 0. */ public void setD(RealParameter d) { if (d == null) { this.d = new RealLiteral(0.0); } else { this.d = d; } this.d.setContext(RealParameterContext.REAL_CONTEXT); this.d.setParent(this); } /** * Get the E parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getE() { return e; } /** * Set the E parameter of this {@code Matrix}, as defined in the * description of the class. * @param e * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of E is * set to 0. */ public void setE(RealParameter e) { if (e == null) { this.e = new RealLiteral(0.0); } else { this.e = e; } this.e.setContext(RealParameterContext.REAL_CONTEXT); this.e.setParent(this); } /** * Get the F parameter of this {@code Matrix}, as defined in the * description of the class. * @return * A {@code RealParameter} that is placed in a * {@link RealParameterContext#REAL_CONTEXT} */ public RealParameter getF() { return f; } /** * Set the F parameter of this {@code Matrix}, as defined in the * description of the class. * @param f * A {@code RealParameter} that is placed (by this method) in a * {@link RealParameterContext#REAL_CONTEXT}. If null, the value of F is * set to 0. */ public void setF(RealParameter f) { if (f == null) { this.f = new RealLiteral(0.0); } else { this.f = f; } this.f.setContext(RealParameterContext.REAL_CONTEXT); this.f.setParent(this); } @Override public List<SymbolizerNode> getChildren() { List<SymbolizerNode> ls = new ArrayList<SymbolizerNode>(); if (a != null) { ls.add(a); } if (b != null) { ls.add(b); } if (c != null) { ls.add(c); } if (d != null) { ls.add(d); } if (e != null) { ls.add(e); } if (f != null) { ls.add(f); } return ls; } @Override public AffineTransform getAffineTransform(Map<String,Object> map, Uom uom, MapTransform mt, Double width, Double height) throws ParameterException { return new AffineTransform( //Uom.toPixel(a.getValue(feat), uom, mt.getDpi(), mt.getScaleDenominator(), null), a.getValue(map), b.getValue(map), c.getValue(map), //Uom.toPixel(b.getValue(feat), uom, mt.getDpi(), mt.getScaleDenominator(), null), //Uom.toPixel(c.getValue(feat), uom, mt.getDpi(), mt.getScaleDenominator(), null), //Uom.toPixel(d.getValue(feat), uom, mt.getDpi(), mt.getScaleDenominator(), null), d.getValue(map), Uom.toPixel(e.getValue(map), uom, mt.getDpi(), mt.getScaleDenominator(), width), Uom.toPixel(f.getValue(map), uom, mt.getDpi(), mt.getScaleDenominator(), height)); } @Override public boolean allowedForGeometries() { return false; } /** * This method simplifiy the matrix. * Every matrix element which doesn't depends on a feature is converted to a single RealLiteral * * @throws ParameterException when something went wrong... */ public void simplify() throws ParameterException { FeaturesVisitor vis = new FeaturesVisitor(); a.acceptVisitor(vis); Set<String> sa = vis.getResult(); b.acceptVisitor(vis); Set<String> sb = vis.getResult(); c.acceptVisitor(vis); Set<String> sc = vis.getResult(); d.acceptVisitor(vis); Set<String> sd = vis.getResult(); e.acceptVisitor(vis); Set<String> se = vis.getResult(); f.acceptVisitor(vis); Set<String> sf = vis.getResult(); if (sa != null && !sa.isEmpty()) { setA(new RealLiteral(a.getValue(null, -1))); } if (sb != null && !sb.isEmpty()) { setB(new RealLiteral(b.getValue(null, -1))); } if (sc != null && !sc.isEmpty()) { setC(new RealLiteral(c.getValue(null, -1))); } if (sd != null && !sd.isEmpty()) { setD(new RealLiteral(d.getValue(null, -1))); } if (se != null && !se.isEmpty()) { setE(new RealLiteral(e.getValue(null, -1))); } if (sf != null && !sf.isEmpty()) { setF(new RealLiteral(f.getValue(null, -1))); } } @Override public JAXBElement<?> getJAXBElement() { MatrixType m = this.getJAXBType(); ObjectFactory of = new ObjectFactory(); return of.createMatrix(m); } @Override public MatrixType getJAXBType() { MatrixType m = new MatrixType(); m.setA(a.getJAXBParameterValueType()); m.setB(b.getJAXBParameterValueType()); m.setC(c.getJAXBParameterValueType()); m.setD(d.getJAXBParameterValueType()); m.setE(e.getJAXBParameterValueType()); m.setF(f.getJAXBParameterValueType()); return m; } @Override public String toString() { return "Matrix"; } }