001/*
002 * Copyright (c) 2016 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2016-04-21 00:24:40 +0000 (Thu, 21 Apr 2016) $' 
007 * '$Revision: 34472 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029package org.kepler.gis.actor.bbox;
030
031import org.geotools.geometry.jts.ReferencedEnvelope;
032import org.kepler.gis.actor.CRSActor;
033import org.kepler.gis.actor.GetBoundingBox;
034import org.kepler.gis.data.BoundingBoxToken;
035import org.kepler.gis.data.GISToken;
036
037import ptolemy.actor.TypedIOPort;
038import ptolemy.actor.parameters.PortParameter;
039import ptolemy.data.DoubleToken;
040import ptolemy.data.Token;
041import ptolemy.data.type.BaseType;
042import ptolemy.kernel.CompositeEntity;
043import ptolemy.kernel.util.Attribute;
044import ptolemy.kernel.util.IllegalActionException;
045import ptolemy.kernel.util.NameDuplicationException;
046
047/** Scale the bounding box for a GIS data set.
048 *  <p>
049 *  If the coordinate reference system is specified in <i>crs</i>
050 *  and is different than the crs in the input data set, then the
051 *  bounding box will be reprojected.
052 *  </p>
053 * 
054 *  @author Daniel Crawl
055 *  @version $Id: ScaleBoundingBox.java 34472 2016-04-21 00:24:40Z crawl $ 
056 */
057public class ScaleBoundingBox extends CRSActor {
058
059    public ScaleBoundingBox(CompositeEntity container, String name)
060            throws NameDuplicationException, IllegalActionException {
061        super(container, name);
062
063        input = new TypedIOPort(this, "input", true, false);
064        input.setTypeAtMost(GISToken.GIS);
065        
066        output = new TypedIOPort(this, "output", false, true);
067        output.setTypeEquals(BoundingBoxToken.BOUNDING_BOX);
068        
069        scale = new PortParameter(this, "scale");
070        scale.setTypeEquals(BaseType.DOUBLE);
071        scale.getPort().setTypeEquals(BaseType.DOUBLE);
072        new Attribute(scale.getPort(), "_showName");
073        
074        /*
075        type = new StringParameter(this, "type");
076        type.addChoice("absolute");
077        // TODO
078        //type.addChoice("relative");
079        type.setToken("absolute");
080        */
081        
082    }
083    
084    /*
085    @Override
086    public void attributeChanged(Attribute attribute) throws IllegalActionException {
087        
088        if(attribute == type) {
089            Token token = type.getToken();
090            if(token != null) {
091                String val = ((StringToken)token).stringValue();
092                if(!val.trim().equals("absolute")) {
093                    throw new IllegalActionException(this, "Only absolute scaling supported.");
094                }
095            }
096        } else {
097            super.attributeChanged(type);
098        }
099    }
100    */
101    
102    @Override
103    public void fire() throws IllegalActionException {
104        
105        super.fire();
106        
107        scale.update();
108        Token token = scale.getToken();
109        if(token == null) {
110            throw new IllegalActionException(this, "Must specify scale.");
111        }
112        
113        double scaleVal = ((DoubleToken)token).doubleValue();
114        
115        if(scaleVal == 0) {
116            throw new IllegalActionException(this, "Scale must not be 0.");
117        }
118        
119        token = input.get(0);
120        ReferencedEnvelope envelope = GetBoundingBox.getBoundingBox(token, _crs);
121        
122        //System.out.println("orig " + envelope);
123        
124        ReferencedEnvelope scaledEnvelope = new ReferencedEnvelope(
125                envelope.getMinX() - scaleVal,
126                envelope.getMaxX() + scaleVal,
127                envelope.getMinY() - scaleVal,
128                envelope.getMaxY() + scaleVal,
129                envelope.getCoordinateReferenceSystem()
130        );
131
132        //System.out.println("new " + envelope);
133
134        output.broadcast(new BoundingBoxToken(scaledEnvelope));
135    }
136    
137    /** The input GIS data set. */
138    public TypedIOPort input;
139    
140    /** The bounding box of the data set. */
141    public TypedIOPort output;
142
143    /** The amount to scale the bounding box by. The units are the
144     *  the same as the coordinate reference system of the input data set.
145     */
146    public PortParameter scale;
147    //public StringParameter type;
148
149}