001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
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 */
029
030package org.ecoinformatics.seek.gis.java_gis;
031
032import java.awt.Shape;
033import java.awt.geom.Rectangle2D;
034import java.io.File;
035
036import ptolemy.actor.TypedAtomicActor;
037import ptolemy.actor.TypedIOPort;
038import ptolemy.data.BooleanToken;
039import ptolemy.data.DoubleToken;
040import ptolemy.data.IntToken;
041import ptolemy.data.StringToken;
042import ptolemy.data.expr.Parameter;
043import ptolemy.data.type.BaseType;
044import ptolemy.kernel.CompositeEntity;
045import ptolemy.kernel.util.IllegalActionException;
046import ptolemy.kernel.util.NameDuplicationException;
047
048/**
049 * <p>
050 * This actor creates a spatial raster grid usng the ConvexHull polygon. Raster
051 * points within the ConvexHull are set to a value of 1. Points outside have a
052 * value of "NO_DATA". The raster is thus a 'mask'.
053 * </p>
054 * <p>
055 *'hullFileName' is a text file with the (x,y) values of the convex hull (one
056 * pair per line, space delimited)<br/>
057 *'rasterFileName' is the name to be given to the raster output<br/>
058 *'numrows' is the number of rows for the raster<br/>
059 *'numcols' is the number of columns for the raster<br/>
060 *'xllcorner' is the x value for the lower left corner (if empty, set to the
061 * minimum x in the convexHull)<br/>
062 *'yllcorner' is the x value for the lower left corner (if empty set to the
063 * minimum x in the convexHull)<br/>
064 *'cellsize' is the (square) cellsize (if empty, 50 cells in x direction are
065 * assumed; and nuber of y-cells (ncols) is recalculated to y-extent of
066 * convexHull<br/>
067 * </p>
068 * <p>
069 * This is a pure java implementation equivalent to the GISRasterActor based on
070 * grass JNI
071 * </p>
072 * 
073 * @author Dan Higgins NCEAS UC Santa Barbara
074 */
075public class CVHull2Raster extends TypedAtomicActor {
076        /**
077         * x-value of the lower left corner of the grid to be created. This is a
078         * double value.
079         */
080        public Parameter xllcorner;
081        /**
082         * y-value of the lower left corner of the grid to be created. This is a
083         * double value.
084         */
085        public Parameter yllcorner;
086        /**
087         * Cell size of the grid to be created (assumed square). This is a double
088         * value.
089         */
090        public Parameter cellsize;
091        /**
092         * Number of rows in the grid to be created. This is an integer
093         */
094        public Parameter numrows;
095        /**
096         * Number of columns in the grid to be created. This is an integer
097         */
098        public Parameter numcols;
099
100        /**
101         * Boolean setting to determine whether or not to use disk for storing grid
102         * data rather than putting all data in RAM arrays. This option in much
103         * slower but allows for very large grids
104         */
105        public Parameter useDisk;
106
107        // input ports
108        /**
109         * The name of the Convex Hull file of data points. 'hullFileName' is a text
110         * file with the (x,y) values of the convex hull (one pair per line, space
111         * delimited)
112         */
113        public TypedIOPort hullFileName = new TypedIOPort(this, "hullFileName",
114                        true, false);
115        /**
116         * The name to be given to the resulting raster grid file
117         */
118        public TypedIOPort rasterFileName = new TypedIOPort(this, "rasterFileName",
119                        true, false);
120
121        /**
122         * The output raster file result (it is in *.asc format).
123         */
124        public TypedIOPort rasterFileResult = new TypedIOPort(this,
125                        "rasterFileResult", false, true);
126
127        private double interior_value = 0.0;
128        private double exterior_value = 1.0E120;
129
130        /**
131   *
132   */
133        public CVHull2Raster(CompositeEntity container, String name)
134                        throws NameDuplicationException, IllegalActionException {
135                super(container, name);
136                xllcorner = new Parameter(this, "xllcorner");
137                yllcorner = new Parameter(this, "yllcorner");
138                cellsize = new Parameter(this, "cellsize");
139                numrows = new Parameter(this, "numrows");
140                numcols = new Parameter(this, "numcols");
141
142                xllcorner.setExpression("0.0");
143                xllcorner.setTypeEquals(BaseType.DOUBLE);
144                yllcorner.setExpression("0.0");
145                yllcorner.setTypeEquals(BaseType.DOUBLE);
146                cellsize.setExpression("0.5");
147                cellsize.setTypeEquals(BaseType.DOUBLE);
148                numrows.setExpression("50");
149                numrows.setTypeEquals(BaseType.INT);
150                numcols.setExpression("50");
151                numcols.setTypeEquals(BaseType.INT);
152
153                hullFileName.setTypeEquals(BaseType.STRING);
154                rasterFileName.setTypeEquals(BaseType.STRING);
155                rasterFileResult.setTypeEquals(BaseType.STRING);
156
157                useDisk = new Parameter(this, "useDisk");
158                useDisk.setDisplayName("Use disk storage (for large grids)");
159                useDisk.setTypeEquals(BaseType.BOOLEAN);
160                useDisk.setToken(BooleanToken.TRUE);
161        }
162
163        /**
164   *
165   */
166        public void initialize() throws IllegalActionException {
167        }
168
169        /**
170   *
171   */
172        public boolean prefire() throws IllegalActionException {
173                return super.prefire();
174        }
175
176        /**
177   *
178   */
179        public void fire() throws IllegalActionException {
180                super.fire();
181
182                StringToken inputFileToken = (StringToken) hullFileName.get(0);
183                String inputFileNameStr = inputFileToken.stringValue();
184                File pointFile = new File(inputFileToken.stringValue());
185                ConvexHull ch = new ConvexHull(pointFile);
186                Shape cvshape = ch.createShape();
187                Rectangle2D boundingBox = cvshape.getBounds2D();
188                double bbMinX = boundingBox.getMinX();
189                double bbMaxX = boundingBox.getMaxX();
190                double bbMinY = boundingBox.getMinY();
191                double bbMaxY = boundingBox.getMaxY();
192
193                StringToken outputFileToken = (StringToken) rasterFileName.get(0);
194                String outFileStr = outputFileToken.stringValue();
195
196                boolean useDiskValue = ((BooleanToken) useDisk.getToken())
197                                .booleanValue();
198
199                int nrows;
200                try {
201                        nrows = ((IntToken) numrows.getToken()).intValue();
202                } catch (Exception w) {
203                        nrows = 50;
204                }
205
206                int ncols;
207                try {
208                        ncols = ((IntToken) numcols.getToken()).intValue();
209                } catch (Exception w) {
210                        ncols = 50;
211                }
212
213                double xmin;
214                try {
215                        xmin = ((DoubleToken) xllcorner.getToken()).doubleValue();
216                } catch (Exception w) {
217                        xmin = bbMinX;
218                }
219
220                double ymin;
221                try {
222                        ymin = ((DoubleToken) yllcorner.getToken()).doubleValue();
223                } catch (Exception w) {
224                        ymin = bbMinY;
225                }
226
227                double cs;
228                try {
229                        cs = ((DoubleToken) cellsize.getToken()).doubleValue();
230                } catch (Exception w) {
231                        cs = (bbMaxX - bbMinX) / ncols;
232                        // set the cellsize based on x-values; then recalc nrows
233                        nrows = (int) ((bbMaxY - bbMinY) / cs) + 1;
234                }
235
236                Grid grid = new Grid(ncols, nrows, cs, cs, xmin, ymin);
237                if (!useDiskValue) {
238                        grid.inMemFlag = true;
239                        grid.dataArray = new double[ncols][nrows];
240                }
241                grid.createShapeMask(cvshape, exterior_value, interior_value);
242                grid.createAsc(outFileStr);
243
244                rasterFileResult.broadcast(new StringToken(outFileStr));
245        }
246}