Issue #2791 Switch contouring to use DataSource for data access.

Former-commit-id: 7c8332a30f [formerly fbf6371c8e] [formerly 4b7f3b2a5b] [formerly 23ce77d864 [formerly 4b7f3b2a5b [formerly 6c90be7554bcbbf0aeb363b6e76c455d3896be83]]]
Former-commit-id: 23ce77d864
Former-commit-id: 527028ea9c54386652ea6e4a25326acedb61a15d [formerly a7787a7ff2]
Former-commit-id: 278ef9f0d4
This commit is contained in:
Ben Steffensmeier 2014-02-27 18:03:33 -06:00
parent 61be7a7225
commit b747a91eaa
20 changed files with 710 additions and 728 deletions

View file

@ -1,23 +1,21 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Contours Plug-in
Bundle-SymbolicName: com.raytheon.viz.core.contours;singleton:=true
Bundle-Version: 1.12.1174.qualifier
Bundle-Activator: com.raytheon.viz.core.contours.Activator
Bundle-Name: Contour Generation and Display
Bundle-SymbolicName: com.raytheon.viz.core.contours
Bundle-Version: 1.14.0.qualifier
Bundle-Vendor: Raytheon
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui,
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.common.util;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.common.wxmath;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Require-Bundle: com.raytheon.uf.viz.core;bundle-version="1.14.1",
org.eclipse.core.runtime,
org.eclipse.ui,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.util,
com.raytheon.uf.common.wxmath,
com.raytheon.uf.common.style,
com.raytheon.uf.common.status,
org.apache.commons.collections
Import-Package: com.raytheon.viz.core.interval
Export-Package: com.raytheon.viz.core.contours,
com.raytheon.viz.core.contours.rsc.displays,
com.raytheon.viz.core.contours.util
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.raytheon.uf.common.style,
com.raytheon.uf.common.style.contour,
com.raytheon.viz.core.interval

View file

@ -1,5 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml
.

View file

@ -1,69 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.contours;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "com.raytheon.viz.core.contours";
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
}

View file

@ -21,7 +21,7 @@ package com.raytheon.viz.core.contours;
import org.geotools.coverage.grid.GeneralGridGeometry;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.style.contour.ContourPreferences;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
@ -39,9 +39,11 @@ import com.raytheon.viz.core.contours.ContourSupport.ContourGroup;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 25, 2011 ekladstrup Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Feb 25, 2011 ekladstrup Initial creation
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource
*
*
* </pre>
*
@ -50,14 +52,14 @@ import com.raytheon.viz.core.contours.ContourSupport.ContourGroup;
*/
public class ContourCreateRequest {
public ContourCreateRequest(String identifier, IDataRecord[] record,
public ContourCreateRequest(String identifier, DataSource[] source,
float level, IExtent pixelExtent, double currentDensity,
double currentMagnification, GeneralGridGeometry imageGridGeometry,
IGraphicsTarget target, IMapDescriptor descriptor,
ContourPreferences prefs, float zoom) {
super();
this.identifier = identifier;
this.record = record;
this.source = source;
this.level = level;
this.pixelExtent = pixelExtent;
this.imageGridGeometry = imageGridGeometry;
@ -79,12 +81,12 @@ public class ContourCreateRequest {
this.identifier = identifier;
}
public IDataRecord[] getRecord() {
return record;
public DataSource[] getSource() {
return source;
}
public void setRecord(IDataRecord[] record) {
this.record = record;
public void setSource(DataSource[] source) {
this.source = source;
}
public float getLevel() {
@ -183,7 +185,7 @@ public class ContourCreateRequest {
private String identifier;
private IDataRecord[] record;
private DataSource[] source;
private float level;

View file

@ -37,9 +37,10 @@ import com.raytheon.viz.core.contours.ContourSupport.ContourGroup;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 24, 2007 chammack Initial Creation.
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Oct 24, 2007 chammack Initial Creation.
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource
*
* </pre>
*
@ -114,9 +115,10 @@ public class ContourManagerJob extends Job {
;// request has been canceled or contours exist
} else {
long t0 = System.currentTimeMillis();
ContourGroup cg = ContourSupport.createContours(
req.getRecord(), req.getLevel(),
req.getPixelExtent(), req.getCurrentDensity(),
ContourGroup cg = null;
cg = ContourSupport.createContours(req.getSource(),
req.getLevel(), req.getPixelExtent(),
req.getCurrentDensity(),
req.getCurrentMagnification(),
req.getImageGridGeometry(), req.getTarget(),
req.getDescriptor(), req.getPrefs(), req.getZoom());
@ -126,7 +128,8 @@ public class ContourManagerJob extends Job {
+ (System.currentTimeMillis() - t0));
}
} catch (Throwable e) {
return new Status(Status.ERROR, Activator.PLUGIN_ID,
return new Status(Status.ERROR, ContourManagerJob.class
.getPackage().getName(),
"Error creating contours", e);
}

View file

@ -28,16 +28,20 @@ import org.eclipse.swt.graphics.RGB;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.JTS;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.interpolation.data.DataCopy;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArrayWrapper;
import com.raytheon.uf.common.style.contour.ContourPreferences;
import com.raytheon.uf.common.wxmath.Constants;
import com.raytheon.uf.common.wxmath.DistFilter;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
import com.raytheon.uf.viz.core.PixelExtent;
import com.raytheon.uf.viz.core.datastructure.LoopProperties;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IRenderable;
@ -56,11 +60,13 @@ import com.vividsolutions.jts.geom.Coordinate;
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 10, 2008 #1233 chammack Initial creation
* Jul 18, 2013 #2199 mschenke Made code only smooth data once
* Aug 23, 2013 #2157 dgilling Remove meteolib dependency.
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jul 10, 2008 1233 chammack Initial creation
* Jul 18, 2013 2199 mschenke Made code only smooth data once
* Aug 23, 2013 2157 dgilling Remove meteolib dependency.
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource and
* reduce loop freezing.
*
* </pre>
*
@ -88,7 +94,7 @@ public abstract class ContourRenderable implements IRenderable {
private final String uuid;
private IDataRecord[] data;
private DataSource[] data;
// This is the width of CONUS
private static final double METERS_AT_BASE_ZOOMLEVEL = 5878649.0;
@ -99,7 +105,7 @@ public abstract class ContourRenderable implements IRenderable {
private static final int NUMBER_CONTOURING_LEVELS = 10;
public abstract IDataRecord[] getData() throws VizException;
public abstract DataSource[] getData() throws VizException;
public abstract GeneralGridGeometry getGridGeometry() throws VizException;
@ -124,7 +130,7 @@ public abstract class ContourRenderable implements IRenderable {
this.requestMap = new HashMap<String, ContourCreateRequest>();
}
private IDataRecord[] getContourData() throws VizException {
private DataSource[] getContourData() throws VizException {
if (data == null) {
data = getData();
if (data != null) {
@ -280,7 +286,7 @@ public abstract class ContourRenderable implements IRenderable {
return;
}
IDataRecord[] dataRecord = getContourData();
DataSource[] dataRecord = getContourData();
if (dataRecord == null) {
return;
}
@ -317,25 +323,38 @@ public abstract class ContourRenderable implements IRenderable {
}
int retries = 0;
LoopProperties loopProps = paintProps
.getLoopProperties();
if (loopProps != null && loopProps
.isLooping()) {
/**
* If the display is looping, wait a few ms to
* let contouring finish so that if the
* contouring is fast enough the user is not
* presented with empty frames. If too many
* resources do this, it freezes the UI so scale
* the sleep time based off the number of
* resources because empty frames are better
* than freezing. This scaling also gives
* everyone a chance to queue up work so that
* multiprocessing is done more efficiently.
*/
retries = 100 / descriptor.getResourceList()
.size();
}
do {
// grab request from map
request = requestMap.get(identifier);
cg = request.getContourGroup();
retries--;
try {
if (cg == null
&& paintProps.getLoopProperties() != null
&& paintProps.getLoopProperties()
.isLooping()) {
Thread.sleep(50);
if (cg == null && retries > 0) {
Thread.sleep(10);
}
} catch (InterruptedException e) {
// ignore
retries = 0;
}
retries++;
} while (cg == null
&& paintProps.getLoopProperties() != null
&& paintProps.getLoopProperties()
.isLooping() && retries < 10);
} while (cg == null && retries > 0);
if (cg != null) {
if (cg != contourGroup[i]) {
@ -396,7 +415,7 @@ public abstract class ContourRenderable implements IRenderable {
}
}
private IDataRecord[] smoothData(IDataRecord[] dataRecord,
private DataSource[] smoothData(DataSource[] dataRecord,
GeneralGridGeometry gridGeometry, ContourPreferences contourPrefs)
throws VizException {
if (contourPrefs != null && contourPrefs.getSmoothingDistance() != null) {
@ -424,32 +443,23 @@ public abstract class ContourRenderable implements IRenderable {
} catch (Exception e) {
throw new VizException(e);
}
// Calculate the Dagnol Distance in Points
FloatDataRecord rec = (FloatDataRecord) dataRecord[0];
float[] data = rec.getFloatData();
int nx = (int) rec.getSizes()[0];
int ny = (int) rec.getSizes()[1];
// Calculate the Diagnol Distance in Points
GridEnvelope range = gridGeometry.getGridRange();
int nx = range.getSpan(0);
int ny = range.getSpan(1);
double distanceInPoints = Math.sqrt(nx * nx + ny * ny);
// Determine the number of points to smooth, assume
// smoothingDistance is in km
float npts = (float) (distanceInPoints
* contourPrefs.getSmoothingDistance() / (distanceInM / 1000));
// Replace our NaN with their NaN
for (int j = 0; j < data.length; j++) {
if (data[j] == -999999) {
data[j] = 1.0E37f;
}
}
data = DistFilter.filter(data, npts, nx, ny, 1);
// Replace their NaN with our NaN
for (int j = 0; j < data.length; j++) {
if (data[j] == 1.0E37f) {
data[j] = -999999;
}
}
rec = new FloatDataRecord(rec.getName(), rec.getGroup(), data,
rec.getDimension(), rec.getSizes());
return new IDataRecord[] { rec };
FloatArrayWrapper data = new FloatArrayWrapper(gridGeometry);
data.setFillValue(Constants.LEGACY_NAN);
DataCopy.copy(dataRecord[0], data, nx, ny);
float[] dataArray = data.getArray();
dataArray = DistFilter.filter(dataArray, npts, nx, ny, 1);
data = new FloatArrayWrapper(dataArray, gridGeometry);
data.setFillValue(Constants.LEGACY_NAN);
return new DataSource[] {data};
} else {
return dataRecord;
}

View file

@ -36,21 +36,25 @@ import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.CRSCache;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.interpolation.data.DataCopy;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArrayWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.OffsetDataSource;
import com.raytheon.uf.common.geospatial.util.GridGeometryWrapChecker;
import com.raytheon.uf.common.geospatial.util.WorldWrapChecker;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.style.LabelingPreferences;
import com.raytheon.uf.common.style.contour.ContourPreferences;
import com.raytheon.uf.common.util.GridUtil;
import com.raytheon.uf.viz.core.DrawableString;
import com.raytheon.uf.viz.core.IExtent;
@ -72,7 +76,6 @@ import com.raytheon.viz.core.contours.util.StreamLineContainer.StreamLinePoint;
import com.raytheon.viz.core.contours.util.StrmPak;
import com.raytheon.viz.core.contours.util.StrmPakConfig;
import com.raytheon.viz.core.interval.XFormFunctions;
import com.raytheon.uf.common.style.contour.ContourPreferences;
import com.vividsolutions.jts.geom.Geometry;
/**
@ -82,19 +85,23 @@ import com.vividsolutions.jts.geom.Geometry;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 22, 2007 chammack Initial Creation.
* May 26, 2009 #2172 chammack Use zoomLevel to calculate label spacing
* Apr 26, 2010 #4583 rjpeter Replaced fortran fortconbuf with java port.
* Mar 04, 2011 #7747 njensen Cached subgrid envelopes
* Jul 09, 2012 DR14940 M.Porricelli Adjust arrow size for streamlines
* Feb 15, 2013 1638 mschenke Moved edex.common Util functions into common Util
* Jun 26, 2013 #1999 dgilling Replace native fortran strmpak call
* with java port.
* Date Ticket# Engineer Description
* ------------- -------- ------------ ----------------------------------------
* Oct 22, 2007 chammack Initial Creation.
* May 26, 2009 2172 chammack Use zoomLevel to calculate label spacing
* Apr 26, 2010 4583 rjpeter Replaced fortran fortconbuf with java
* port.
* Mar 04, 2011 7747 njensen Cached subgrid envelopes
* Jul 09, 2012 14940 M.Porricelli Adjust arrow size for streamlines
* Feb 15, 2013 1638 mschenke Moved edex.common Util functions into
* common Util
* Jun 26, 2013 1999 dgilling Replace native fortran strmpak call
* with java port.
* Jul 18, 2013 2199 mschenke Ensured contouring is only occurring
* over visible area
* Jul 23, 2013 2157 dgilling Remove legacy stream line drawing code.
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource
*
* Jul 18, 2013 2199 mschenke Ensured contouring is only occurring over visible area
* Jul 23, 2013 #2157 dgilling Remove legacy stream line drawing code.
* </pre>
*
* @author chammack
@ -105,6 +112,23 @@ public class ContourSupport {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ContourSupport.class);
/*
* By default contour any data source that is passed in. This is much more
* efficient than copying the data and allows us to contour any DataSource.
*
* The downside is that FortConBuf accesses each data point multiple times
* and it is possible that DataSources with lots of transformation will have
* poor performance. Since different sources will exhibit different behavior
* and it is impossible to test all sources this field provides a runtime
* flag to copy all the data so that slow sources will only need to access
* each point once at the cost of more memory and taking the time to copy.
* Hopefully this is just paranoia and this flag can be removed in the
* future. If it turns out this is necessary we will likely want to find a
* more fine grained approach to tuning this.
*/
private static boolean copyData = Boolean.getBoolean(ContourSupport.class
.getPackage().getName() + ".copyData");
private static float smallestContourValue = GridUtil.GRID_FILL_VALUE - 1;
private static float largestContourValue = GridUtil.GRID_FILL_VALUE + 1;
@ -206,7 +230,7 @@ public class ContourSupport {
/**
* Create contours from provided parameters
*
* @param records
* @param sources
* @param level
* @param extent
* @param currentDensity
@ -220,7 +244,7 @@ public class ContourSupport {
* @return the ContourGroup
* @throws VizException
*/
public static ContourGroup createContours(IDataRecord[] records,
public static ContourGroup createContours(DataSource[] sources,
float level, IExtent extent, double currentDensity,
double currentMagnification, GeneralGridGeometry imageGridGeometry,
IGraphicsTarget target, IMapDescriptor descriptor,
@ -297,49 +321,37 @@ public class ContourSupport {
// Step 3: Get the actual data
if (records.length == 1 && records[0] != null) {
IDataRecord record = records[0];
float[] data1D = null;
long[] sz = record.getSizes();
if (record instanceof ByteDataRecord) {
byte[] data1Db = ((ByteDataRecord) record).getByteData();
data1D = new float[data1Db.length];
for (int i = 0; i < data1D.length; i++) {
data1D[i] = data1Db[i] & 0xFF;
}
} else if (record instanceof FloatDataRecord) {
data1D = ((FloatDataRecord) record).getFloatData();
} else {
throw new UnsupportedOperationException(
"Contouring is not supported for data type: "
+ record.getClass().getName());
}
if (sources.length == 1 && sources[0] != null) {
// Step 4: Determine the subgrid, if any
GridEnvelope imageRange = imageGridGeometry.getGridRange();
int minX = (int) Math.floor(Math.max(env.getMinimum(0), 0));
int minY = (int) Math.floor(Math.max(env.getMinimum(1), 0));
int maxX = (int) Math.ceil(Math.min(env.getMaximum(0), sz[0] - 1));
int maxY = (int) Math.ceil(Math.min(env.getMaximum(1), sz[1] - 1));
int maxX = (int) Math.ceil(Math.min(env.getMaximum(0),
imageRange.getHigh(0)));
int maxY = (int) Math.ceil(Math.min(env.getMaximum(1),
imageRange.getHigh(1)));
int szX = (maxX - minX) + 1;
int szY = (maxY - minY) + 1;
if (szX * szY <= 0) {
return contourGroup;
}
float[][] subgriddedData = new float[szX][szY];
/* Make contours continous for world wrapping grids. */
int wrapNumber = GridGeometryWrapChecker
.checkForWrapping(imageGridGeometry);
if (wrapNumber - 1 >= szX) {
szX = wrapNumber + 1;
}
for (int j = 0; j < szY; j++) {
for (int i = 0; i < szX; i++) {
float val = data1D[((int) sz[0] * (j + minY)) + (i + minX)];
if (Float.isNaN(val)) {
val = GridUtil.GRID_FILL_VALUE;
}
subgriddedData[i][j] = val;
}
DataSource subgridSource = sources[0];
if (minX != 0 || minY != 0) {
subgridSource = new OffsetDataSource(sources[0], minX, minY);
}
if (copyData) {
subgridSource = DataCopy.copy(subgridSource,
new FloatArrayWrapper(szX, szY), szX, szY);
}
// Use ported legacy code to determine contour interval
@ -358,12 +370,12 @@ public class ContourSupport {
// Awips 1
config.xOffset = minX;
config.yOffset = minY;
config.labelSpacingLine = subgriddedData.length / 3;
config.labelSpacingLine = szX / 3;
if (config.labelSpacingLine < 1) {
config.labelSpacingLine = 1;
}
config.labelSpacingOverall = (int) (subgriddedData.length * 60
config.labelSpacingOverall = (int) (szX * 60
* currentMagnification / ((PixelExtent) extent).getWidth() + 0.5);
// If nothing provided, attempt to get approximately 50 contours
@ -371,10 +383,13 @@ public class ContourSupport {
// TODO this is fairly inefficient to do every time.
float min = Float.POSITIVE_INFINITY;
float max = Float.NEGATIVE_INFINITY;
for (float f : data1D) {
if (f != GridUtil.GRID_FILL_VALUE && !Float.isNaN(f)) {
min = Math.min(min, f);
max = Math.max(max, f);
for (int j = 0; j < szY; j++) {
for (int i = 0; i < szX; i++) {
float f = (float) subgridSource.getDataValue(i, j);
if (!Float.isNaN(f)) {
min = Math.min(min, f);
max = Math.max(max, f);
}
}
}
float interval = XFormFunctions
@ -383,12 +398,12 @@ public class ContourSupport {
true, "", 10);
config.seed = new float[] { interval };
config.mode = -50;
contours = FortConBuf.contour(subgriddedData, config);
contours = FortConBuf.contour(subgridSource, szX, szY, config);
} else {
LabelingPreferences contourLabeling = prefs
.getContourLabeling();
if (contourLabeling.getLabelSpacing() > 0) {
config.labelSpacingLine = subgriddedData.length
config.labelSpacingLine = szX
/ contourLabeling.getLabelSpacing();
if (config.labelSpacingLine < 1) {
config.labelSpacingLine = 1;
@ -425,14 +440,14 @@ public class ContourSupport {
.getIncrement();
float interval;
if (contourLabeling.getNumberOfContours() > 0) {
float minData = 1e37f;
float maxData = -1e37f;
for (float[] dataRow : subgriddedData) {
for (float data : dataRow) {
if (data < minData && data != -999999) {
minData = data;
} else if (data < 999998 && data > maxData) {
maxData = data;
float minData = Float.POSITIVE_INFINITY;
float maxData = Float.NEGATIVE_INFINITY;
for (int j = 0; j < szY; j++) {
for (int i = 0; i < szX; i++) {
float f = (float) subgridSource.getDataValue(i, j);
if (!Float.isNaN(f)) {
minData = Math.min(minData, f);
maxData = Math.max(maxData, f);
}
}
}
@ -463,7 +478,7 @@ public class ContourSupport {
config.mode = 0;
config.seed = controls;
contours = FortConBuf.contour(subgriddedData, config);
contours = FortConBuf.contour(subgridSource, szX, szY, config);
} else if (prefs.getContourLabeling().getValues() != null) {
// explicit contouring values provided
@ -497,7 +512,7 @@ public class ContourSupport {
} else {
config.mode = vals.length;
}
contours = FortConBuf.contour(subgriddedData, config);
contours = FortConBuf.contour(subgridSource, szX, szY, config);
}
}
@ -528,7 +543,7 @@ public class ContourSupport {
long tZ1 = System.currentTimeMillis();
tMinMaxAccum += tZ1 - tZ0;
checkWorldWrapping(contours, descriptor, rastPosToLatLon);
correctWorldWrapping(contours, descriptor, rastPosToLatLon);
int size = contours.xyContourPoints.size();
// total coordinates
@ -613,19 +628,9 @@ public class ContourSupport {
} catch (Throwable e) {
throw new VizException("Error postprocessing contours", e);
}
} else if (records.length == 2) {
float[] uW = null;
float[] vW = null;
long[] sz = records[0].getSizes();
if (records[0] instanceof FloatDataRecord) {
uW = ((FloatDataRecord) records[0]).getFloatData();
vW = ((FloatDataRecord) records[1]).getFloatData();
} else {
throw new UnsupportedOperationException(
"Streamlining is not supported for data type: "
+ records.getClass().getName());
}
} else if (sources.length == 2) {
GridEnvelope range = imageGridGeometry.getGridRange();
long[] sz = { range.getSpan(0), range.getSpan(1) };
// Step 4: Determine the subgrid, if any
@ -634,7 +639,8 @@ public class ContourSupport {
int maxX = (int) Math.ceil(Math.min(env.getMaximum(0), sz[0] - 1));
int maxY = (int) Math.ceil(Math.min(env.getMaximum(1), sz[1] - 1));
makeStreamLines(uW, vW, minX, minY, maxX, maxY, sz, contourGroup,
makeStreamLines(sources[0], sources[1], minX, minY, maxX, maxY, sz,
contourGroup,
currentMagnification, zoom, contourGroup.lastDensity,
rastPosToWorldGrid);
}
@ -645,7 +651,7 @@ public class ContourSupport {
public static GeneralEnvelope calculateSubGrid(IExtent workingExtent,
GeneralGridGeometry mapGridGeometry,
GeneralGridGeometry imageGridGeometry) throws VizException {
GeneralGridGeometry imageGridGeometry) {
GeneralEnvelope env = new GeneralEnvelope(2);
try {
GridGeometry2D imageGeometry2D = GridGeometry2D
@ -723,7 +729,6 @@ public class ContourSupport {
final double threshold1 = (200.0 / screenToPixel);
final double threshold2 = (50.0 / screenToPixel);
long tAccum = 0;
double q1, q2, p1, p2;
for (int n = 0; n < valsArr.length; n++) {
@ -764,11 +769,9 @@ public class ContourSupport {
}
if (!tooClose
/* || (labeledAtLeastOnce == false && n == valsArr.length - 1) */) {
long t0 = System.currentTimeMillis();
shapeToAddTo.addLabel(label, valsArr[n]);
labelPoints.add(valsArr[n]);
lastPoint = valsArr[n];
tAccum += (System.currentTimeMillis() - t0);
}
}
}
@ -1087,7 +1090,13 @@ public class ContourSupport {
int maxX = (int) (sz[0] - 1);
int maxY = (int) (sz[1] - 1);
makeStreamLines(uW, vW, minX, minY, maxX, maxY, sz, contourGroup,
DataSource uWSource = new FloatArrayWrapper(uW, (int) sz[0],
(int) sz[1]);
DataSource vWSource = new FloatArrayWrapper(vW, (int) sz[0],
(int) sz[1]);
makeStreamLines(uWSource, vWSource, minX, minY, maxX, maxY, sz,
contourGroup,
1, 1, contourGroup.lastDensity * 2, gridToPixel);
return contourGroup;
@ -1099,7 +1108,7 @@ public class ContourSupport {
}
private static void makeStreamLines(float[] uW, float[] vW, int minX,
private static void makeStreamLines(DataSource uW, DataSource vW, int minX,
int minY, int maxX, int maxY, long[] sz, ContourGroup contourGroup,
double currentMagnification, float zoom, double density,
MathTransform rastPosToWorldGrid) throws VizException {
@ -1113,24 +1122,6 @@ public class ContourSupport {
int x = (int) sz[0];
int y = (int) sz[1];
float[][] adjustedUw = new float[szX][szY];
float[][] adjustedVw = new float[szX][szY];
for (int j = 0; j < szY; j++) {
for (int i = 0; i < szX; i++) {
float uWVal = uW[(x * (j + minY)) + (i + minX)];
if (Float.isNaN(uWVal)) {
uWVal = GridUtil.GRID_FILL_VALUE;
}
adjustedUw[szX - 1 - i][j] = uWVal;
float vWVal = vW[(x * (j + minY)) + (i + minX)];
if (Float.isNaN(vWVal)) {
vWVal = GridUtil.GRID_FILL_VALUE;
}
adjustedVw[szX - 1 - i][j] = vWVal;
}
}
// Use ported legacy code to determine contour interval
long t0 = System.currentTimeMillis();
@ -1180,8 +1171,8 @@ public class ContourSupport {
StrmPakConfig config = new StrmPakConfig(arrowSize, minspc, maxspc,
-1000000f, -999998f);
StreamLineContainer container = StrmPak.strmpak(adjustedUw, adjustedVw,
szX, szX, szY, config);
StreamLineContainer container = StrmPak.strmpak(uW, vW,
szX, szY, config);
long t1 = System.currentTimeMillis();
System.out.println("Contouring took: " + (t1 - t0));
@ -1351,13 +1342,30 @@ public class ContourSupport {
return rval;
}
private static void checkWorldWrapping(ContourContainer contours,
/**
* Check the contour lines in a ContourContainer and split any lines that
* need to wrap over the "seam" in the display crs. If changes are needed
* the lines within contours are modified directly.
*
* @param contours
* container holding contour lines
* @param descriptor
* the discriptor for the dispaly
* @param rastPosToLatLon
* transform for converting the coordinates within contours to
* LatLon coordinates.
* @throws TransformException
*/
private static void correctWorldWrapping(ContourContainer contours,
IMapDescriptor descriptor, MathTransform rastPosToLatLon)
throws TransformException {
long tZ0 = System.currentTimeMillis();
WorldWrapChecker wwc = new WorldWrapChecker(
descriptor.getGridGeometry());
if (!wwc.needsChecking()) {
return;
}
List<float[]> splitLines = new ArrayList<float[]>();
List<Float> dupValues = new ArrayList<Float>();

View file

@ -64,6 +64,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Sep 10, 2013 16257 MPorricelli Fix so that wind for global grids displays on
* mercator maps.
* Sep 23, 2013 2363 bsteffen Add more vector configuration options.
* Feb 27, 2014 2791 bsteffen Remove Unnecessary throws
*
* </pre>
*
@ -432,7 +433,7 @@ public abstract class AbstractGriddedDisplay<T> implements IRenderable {
}
public void reproject() throws VizException {
public void reproject() {
initPlotLocations();
issueRefresh();
}

View file

@ -24,23 +24,24 @@ import java.nio.FloatBuffer;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatBufferWrapper;
import com.raytheon.uf.common.style.contour.ContourPreferences;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
import com.raytheon.viz.core.contours.ContourRenderable;
import com.raytheon.uf.common.style.contour.ContourPreferences;
/**
* Displays contours from GFE Grid Data
* Displays contours from any data source
*
* Currently implemented using the D2D contouring capability
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 11, 2008 #1233 chammack Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jul 11, 2008 1233 chammack Initial creation
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource
*
* </pre>
*
@ -54,21 +55,23 @@ public class GriddedContourDisplay extends ContourRenderable {
protected GridGeometry2D gridGeometry;
protected FloatBuffer fb;
protected DataSource source;
public GriddedContourDisplay(IMapDescriptor descriptor,
final GridGeometry2D gridGeometry, final FloatBuffer fb) {
this(descriptor, gridGeometry, new FloatBufferWrapper(fb, gridGeometry));
}
public GriddedContourDisplay(IMapDescriptor descriptor,
final GridGeometry2D gridGeometry, final DataSource source) {
super(descriptor);
this.gridGeometry = gridGeometry;
this.fb = fb;
this.source = source;
}
@Override
public IDataRecord[] getData() throws VizException {
FloatDataRecord fdr = new FloatDataRecord("Data", "", fb.array(), 2,
new long[] { gridGeometry.getGridRange2D().width,
gridGeometry.getGridRange2D().height });
return new IDataRecord[] { fdr };
public DataSource[] getData() throws VizException {
return new DataSource[] { source };
}
@Override

View file

@ -23,8 +23,8 @@ import java.nio.FloatBuffer;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatBufferWrapper;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
@ -39,11 +39,12 @@ import com.raytheon.uf.viz.core.map.IMapDescriptor;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 22, 2010 bsteffen Initial creation
* Feb 07, 2011 7948 bkowal added a public method to get
* the direction.
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jun 22, 2010 bsteffen Initial creation
* Feb 07, 2011 7948 bkowal added a public method to get the
* direction.
* Feb 27, 2014 2791 bsteffen Switch from IDataRecord to DataSource
*
* </pre>
*
@ -52,23 +53,23 @@ import com.raytheon.uf.viz.core.map.IMapDescriptor;
*/
public class GriddedStreamlineDisplay extends GriddedContourDisplay {
private FloatBuffer vfb;
private DataSource vSource;
public GriddedStreamlineDisplay(IMapDescriptor descriptor,
GridGeometry2D gridGeometry, FloatBuffer ufb, FloatBuffer vfb) {
super(descriptor, gridGeometry, ufb);
this.vfb = vfb;
this.vSource = new FloatBufferWrapper(vfb, gridGeometry);
}
public GriddedStreamlineDisplay(IMapDescriptor descriptor,
GridGeometry2D gridGeometry, DataSource ufb, DataSource vfb) {
super(descriptor, gridGeometry, ufb);
this.vSource = vfb;
}
@Override
public IDataRecord[] getData() throws VizException {
FloatDataRecord ufdr = new FloatDataRecord("uData", "", fb.array(), 2,
new long[] { gridGeometry.getGridRange2D().width,
gridGeometry.getGridRange2D().height });
FloatDataRecord vfdr = new FloatDataRecord("vData", "", vfb.array(), 2,
new long[] { gridGeometry.getGridRange2D().width,
gridGeometry.getGridRange2D().height });
return new IDataRecord[] { ufdr, vfdr };
public DataSource[] getData() throws VizException {
return new DataSource[] { source, vSource };
}
}

View file

@ -34,20 +34,19 @@ import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
/**
*
* TODO Add Description
* Caches reprojected plot location for quick display.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 13, 2011 bsteffen Initial creation
* Sep 10, 2013 DR 16257 MPorricelli Eliminate values that
* fail to be tranformed,e.g.
* when too close to pole for
* mercator projections
* Date Ticket# Engineer Description
* ------------- -------- ----------- -----------------------------------------
* Oct 13, 2011 bsteffen Initial creation
* Sep 10, 2013 16257 MPorricelli Eliminate values that fail to be
* tranformed,e.g. when too close to pole
* for mercator projections
* Feb 27, 2014 2791 bsteffen Remove Unnecessary catch
*
* </pre>
*
@ -169,8 +168,6 @@ public class PlotLocationCache {
throw new RuntimeException(e);
} catch (NoninvertibleTransformException e) {
throw new RuntimeException(e);
} catch (TransformException e) {
throw new RuntimeException(e);
}
cache.put(key, new SoftReference<float[]>(result));
}

View file

@ -24,6 +24,11 @@ import java.text.ParseException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.raytheon.uf.common.geospatial.interpolation.data.AxisSwapDataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArray2DWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.InvalidRangeDataSource;
/**
* Port of the fortCon.f routine. Minimal changes made to make it perform better
* in java. Not object orientated and not thread safe!
@ -31,9 +36,10 @@ import java.util.concurrent.ConcurrentLinkedQueue;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 22, 2010 #4583 rjpeter Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 22, 2010 4583 rjpeter Initial creation
* Feb 27, 2014 2791 bsteffen Use DataSource for generic data access.
*
* </pre>
*
@ -68,13 +74,9 @@ public class FortConBuf {
}
}
private PointBuffer ijPntBuffer = new PointBuffer(2000, 1000, true);
private PointBuffer ijPntBuffer = new PointBuffer(2000, 1000);
private float[][] dataToContour;
private int nx;
private int ny;
private DataSource dataToContour;
private int nxMaxIndex;
@ -96,16 +98,6 @@ public class FortConBuf {
private float[] MxAvg = new float[maxContours];
private int dlx;
private int dly;
private int dld;
private int labsep;
private int celcnt;
private int c;
private int labsep2;
@ -119,6 +111,34 @@ public class FortConBuf {
private static Queue<FortConBuf> instancePool = new ConcurrentLinkedQueue<FortConBuf>();
public static ContourContainer contour(float[][] data, FortConConfig config) {
int ny = data.length;
int nx = data[0].length;
DataSource source = new FloatArray2DWrapper(data, nx, ny);
source = new AxisSwapDataSource(source);
if (config.badlo < config.badhi) {
source = new InvalidRangeDataSource(source, config.badlo,
config.badhi);
}
return contour(source, ny, nx, config);
}
/**
* Perform contouring. This method ignores config.badlo and config.badhi and
* only treats NaN as bad data.
*
* @param data
* the source for data to contouring.
* @param nx
* The number of points to contour in the x direction
* @param ny
* The number of points to contour in the y direction
* @param config
* configuration options
* @return a ContourContainer
*/
public static ContourContainer contour(DataSource data, int nx, int ny,
FortConConfig config) {
ContourContainer rval = null;
FortConBuf instance = null;
try {
@ -127,7 +147,7 @@ public class FortConBuf {
instance = new FortConBuf();
}
rval = instance.contourInternal(data, config);
rval = instance.contourInternal(data, nx, ny, config);
} finally {
if (instance != null) {
instancePool.add(instance);
@ -137,141 +157,76 @@ public class FortConBuf {
return rval;
}
private ContourContainer contourInternal(float[][] data,
private ContourContainer contourInternal(DataSource data, int nx, int ny,
FortConConfig config) {
dataToContour = data;
nx = dataToContour.length;
ny = dataToContour[0].length;
nxMaxIndex = nx - 1;
nyMaxIndex = ny - 1;
ijPntBuffer.setSize(0);
ijPntBuffer.setXOffset(config.xOffset);
ijPntBuffer.setYOffset(config.yOffset);
float rawmax = -Float.MAX_VALUE;
float rawmin = Float.MAX_VALUE;
double rawmax = -Double.MAX_VALUE;
double rawmin = Double.MAX_VALUE;
work1 = new byte[nx][ny];
work2 = new byte[nx][ny];
work3 = new byte[nx][ny];
work4 = new byte[nx][ny];
int ldwork = Math.min(Math.min(nx, ny),
Math.max(1, config.labelSpacingLine));
// contourCount is number of contour values
int contourCount, mmm;
int i, j, xmode, turn1, turn2, turn3, turn4, ii, jj;
float val, val1, val2, dval, minval, maxval, D2;
String[] LabStr = new String[maxContours];
double val, val1, val2, dval, minval, maxval, D2;
Byte bbb;
// map out missing values
if (config.badlo < config.badhi) {
// Figure out which vertical sides can accept contours.
for (int cIdx = 0; cIdx < nx; cIdx++) {
val2 = dataToContour[cIdx][nyMaxIndex];
for (int rIdx = nyMaxIndex - 1; rIdx >= 0; rIdx--) {
val1 = dataToContour[cIdx][rIdx];
if (val1 < val2) {
if (val1 > config.badhi || val2 < config.badlo) {
if (val1 < rawmin) {
rawmin = val1;
}
work4[cIdx][rIdx] = b40;
} else {
work4[cIdx][rIdx] = 1;
}
} else {
if (val2 > config.badhi || val1 < config.badlo) {
if (val2 < rawmin) {
rawmin = val2;
}
if (val2 < val1) {
work4[cIdx][rIdx] = bC0;
}
} else {
work4[cIdx][rIdx] = 1;
}
// Figure out which vertical sides can accept contours.
for (int cIdx = 0; cIdx < nx; cIdx++) {
val2 = dataToContour.getDataValue(cIdx, nyMaxIndex);
for (int rIdx = nyMaxIndex - 1; rIdx >= 0; rIdx--) {
val1 = dataToContour.getDataValue(cIdx, rIdx);
if (val1 < val2) {
if (val1 < rawmin) {
rawmin = val1;
}
val2 = val1;
}
}
// Figure out which horizontal sides can accept contours.
for (int rIdx = 0; rIdx < ny; rIdx++) {
val2 = dataToContour[nxMaxIndex][rIdx];
for (int cIdx = nxMaxIndex - 1; cIdx >= 0; cIdx--) {
val1 = dataToContour[cIdx][rIdx];
if (val1 < val2) {
if (val1 > config.badhi || val2 < config.badlo) {
if (val2 > rawmax) {
rawmax = val2;
}
work3[cIdx][rIdx] = b40;
} else {
work3[cIdx][rIdx] = 1;
}
} else {
if (val2 > config.badhi || val1 < config.badlo) {
if (val1 > rawmax) {
rawmax = val1;
}
if (val2 < val1) {
work3[cIdx][rIdx] = bC0;
}
} else {
work3[cIdx][rIdx] = 1;
}
work4[cIdx][rIdx] = b40;
} else if (Double.isNaN(val1) || Double.isNaN(val2)) {
work4[cIdx][rIdx] = 1;
} else {
if (val2 < rawmin) {
rawmin = val2;
}
val2 = val1;
}
}
} else { // no missing value
// Determine "sense" of vertical sides.
for (int cIdx = 0; cIdx < nx; cIdx++) {
val2 = dataToContour[cIdx][nyMaxIndex];
for (int rIdx = nyMaxIndex - 1; rIdx >= 0; rIdx--) {
val1 = dataToContour[cIdx][rIdx];
if (val1 < val2) {
if (val1 < rawmin) {
rawmin = val1;
}
work4[cIdx][rIdx] = b40;
} else {
if (val2 < rawmin) {
rawmin = val2;
}
if (val2 < val1) {
work4[cIdx][rIdx] = bC0;
}
val2 = val1;
}
val2 = val1;
}
}
// determine "sense" of horizontal size
for (int rIdx = 0; rIdx < ny; rIdx++) {
val2 = dataToContour[nxMaxIndex][rIdx];
for (int cIdx = nxMaxIndex - 1; cIdx >= 0; cIdx--) {
val1 = dataToContour[cIdx][rIdx];
if (val1 < val2) {
if (val2 > rawmax) {
rawmax = val2;
}
work3[cIdx][rIdx] = b40;
} else {
if (val1 > rawmax) {
rawmax = val1;
}
// Figure out which horizontal sides can accept contours.
for (int rIdx = 0; rIdx < ny; rIdx++) {
val2 = dataToContour.getDataValue(nxMaxIndex, rIdx);
for (int cIdx = nxMaxIndex - 1; cIdx >= 0; cIdx--) {
val1 = dataToContour.getDataValue(cIdx, rIdx);
if (val1 < val2) {
if (val2 > rawmax) {
rawmax = val2;
}
work3[cIdx][rIdx] = b40;
} else if (Double.isNaN(val1) || Double.isNaN(val2)) {
work3[cIdx][rIdx] = 1;
} else {
if (val1 > rawmax) {
rawmax = val1;
}
if (val2 < val1) {
work3[cIdx][rIdx] = bC0;
}
val2 = val1;
}
val2 = val1;
}
}
@ -355,7 +310,7 @@ public class FortConBuf {
// e.g. dont calculate contours with an offset of 1.5 when
// contours are printed as integers, will cause contours
// to go missing in that case
if (config != null && config.labelFormat != null) {
if (config.labelFormat != null) {
DecimalFormat df = new DecimalFormat(config.labelFormat);
float temp = Float.valueOf(df.format(dval));
if (temp != 0) {
@ -379,7 +334,7 @@ public class FortConBuf {
int numSteps = (int) ((val2 - val1) / dval + 1);
val = val1;
for (contourCount = 0; contourCount < numSteps; contourCount++) {
ConVal[contourCount] = val;
ConVal[contourCount] = (float) val;
val = val + dval;
}
// remove ncon-- as now ncon is the number of contour values
@ -468,8 +423,8 @@ public class FortConBuf {
// mmtol processing always amount to 0
float dmm = 0;
float mmlim1 = 0;
float mmlim2 = 0;
double mmlim1 = 0;
double mmlim2 = 0;
// Figure out limits of values which may be marked for.
if (mmm > 1 && val2 < 0) {
@ -496,7 +451,7 @@ public class FortConBuf {
continue MIN_MAX_SEARCH;
}
// check that this falls within markable limits
val = dataToContour[i][j];
val = dataToContour.getDataValue(i, j);
if (val < mmlim1 || val > mmlim2) {
continue MIN_MAX_SEARCH;
}
@ -508,19 +463,23 @@ public class FortConBuf {
continue MIN_MAX_SEARCH;
}
// check corner points
if ((work3[im][jm] >= 2 && work4[im][jm] >= 2 && dataToContour[i][j] >= dataToContour[im][jm])
|| (work3[im][jp] >= 2 && work4[im][j] <= -2 && dataToContour[i][j] >= dataToContour[im][jp])
|| (work3[i][jm] <= -2 && work4[ip][jm] >= 2 && dataToContour[i][j] >= dataToContour[ip][jm])
|| (work3[i][jp] <= -2 && work4[ip][j] <= -2 && dataToContour[i][j] >= dataToContour[ip][jp])) {
if ((work3[im][jm] >= 2 && work4[im][jm] >= 2 && val >= dataToContour
.getDataValue(im, jm))
|| (work3[im][jp] >= 2 && work4[im][j] <= -2 && val >= dataToContour
.getDataValue(jp, im))
|| (work3[i][jm] <= -2 && work4[ip][jm] >= 2 && val >= dataToContour
.getDataValue(ip, jm))
|| (work3[i][jp] <= -2 && work4[ip][j] <= -2 && val >= dataToContour
.getDataValue(ip, jp))) {
continue MIN_MAX_SEARCH;
}
// sharp min check
if (dmm > 0) {
val = dataToContour[i][j] + dmm;
if (val > dataToContour[im][j]
|| val > dataToContour[i][jm]
|| val > dataToContour[ip][j]
|| val > dataToContour[i][jp]) {
val = val + dmm;
if (val > dataToContour.getDataValue(im, j)
|| val > dataToContour.getDataValue(i, jm)
|| val > dataToContour.getDataValue(ip, j)
|| val > dataToContour.getDataValue(i, jp)) {
continue MIN_MAX_SEARCH;
}
}
@ -558,19 +517,23 @@ public class FortConBuf {
continue MIN_MAX_SEARCH;
}
// check corner points
if ((work3[im][jm] <= -2 && work4[im][jm] <= -2 && dataToContour[i][j] <= dataToContour[im][jm])
|| (work3[im][jp] <= -2 && work4[im][j] >= 2 && dataToContour[i][j] <= dataToContour[im][jp])
|| (work3[i][jm] >= 2 && work4[ip][jm] <= -2 && dataToContour[i][j] <= dataToContour[ip][jm])
|| (work3[i][jp] >= 2 && work4[ip][j] >= 2 && dataToContour[i][j] <= dataToContour[ip][jp])) {
if ((work3[im][jm] <= -2 && work4[im][jm] <= -2 && val <= dataToContour
.getDataValue(im, jm))
|| (work3[im][jp] <= -2 && work4[im][j] >= 2 && val <= dataToContour
.getDataValue(ip, jp))
|| (work3[i][jm] >= 2 && work4[ip][jm] <= -2 && val <= dataToContour
.getDataValue(ip, jm))
|| (work3[i][jp] >= 2 && work4[ip][j] >= 2 && val <= dataToContour
.getDataValue(ip, jp))) {
continue MIN_MAX_SEARCH;
}
// sharp max check
if (dmm > 0) {
val = dataToContour[i][j] - dmm;
if (val < dataToContour[im][j]
|| val < dataToContour[i][jm]
|| val < dataToContour[ip][j]
|| val < dataToContour[i][jp]) {
val = val - dmm;
if (val < dataToContour.getDataValue(im, j)
|| val < dataToContour.getDataValue(i, jm)
|| val < dataToContour.getDataValue(ip, j)
|| val < dataToContour.getDataValue(i, jp)) {
continue MIN_MAX_SEARCH;
}
}
@ -629,12 +592,6 @@ public class FortConBuf {
// Initialize counters for total cells, labels, and label separations on
// lines.
// TODO account for fortran 1 index?
dlx = 2;
dly = 2;
dld = 3;
labsep = dld * ldwork;
celcnt = labsep / 2;
labsep2 = config.labelSpacingOverall;
// Fill line pattern array, scale contour value array, and set use count
@ -693,7 +650,7 @@ public class FortConBuf {
}
// Cell side does not have missing values, reinitialize search.
D2 = dataToContour[i][j];
D2 = dataToContour.getDataValue(i, j);
if (bbb > 0) {
for (c = 0; c < contourCount; c++) {
if (ConVal[c] > D2) {
@ -748,7 +705,7 @@ public class FortConBuf {
}
case 10022: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] < D2) {
@ -801,7 +758,7 @@ public class FortConBuf {
}
case 10032: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] > D2) {
@ -840,7 +797,7 @@ public class FortConBuf {
}
// Cell side does not have missing values, reinitialize search.
D2 = dataToContour[i][j];
D2 = dataToContour.getDataValue(i, j);
if (bbb > 0) {
for (c = 0; c < contourCount; c++) {
if (ConVal[c] > D2) {
@ -895,7 +852,7 @@ public class FortConBuf {
}
case 20022: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] < D2) {
@ -948,7 +905,7 @@ public class FortConBuf {
}
case 20032: {
// Find group of contours which are bracketed
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] > D2) {
@ -987,7 +944,7 @@ public class FortConBuf {
}
// Cell side does not have missing values, reinitialize search.
D2 = dataToContour[i][j];
D2 = dataToContour.getDataValue(i, j);
if (bbb < 0) {
for (c = 0; c < contourCount; c++) {
if (ConVal[c] > D2) {
@ -1042,7 +999,7 @@ public class FortConBuf {
}
case 30022: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] < D2) {
@ -1095,7 +1052,7 @@ public class FortConBuf {
}
case 30032: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] > D2) {
@ -1134,7 +1091,7 @@ public class FortConBuf {
}
// Cell side does not have missing values, reinitialize search.
D2 = dataToContour[i][j];
D2 = dataToContour.getDataValue(i, j);
if (bbb < 0) {
for (c = 0; c < contourCount; c++) {
if (ConVal[c] > D2) {
@ -1189,7 +1146,7 @@ public class FortConBuf {
}
case 40022: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] < D2) {
@ -1242,7 +1199,7 @@ public class FortConBuf {
}
case 40032: {
// Step through possible contours we can start
D2 = dataToContour[ii][jj];
D2 = dataToContour.getDataValue(ii, jj);
boolean keepProcessing = true;
while (keepProcessing) {
if (ConVal[c] > D2) {
@ -1276,12 +1233,14 @@ public class FortConBuf {
bbb = work3[i][j];
if (bbb == b52) {
// minima
rval.minVals.add(dataToContour[i][j]);
rval.minVals.add((float) dataToContour.getDataValue(i,
j));
rval.minLabelPoints.add(new float[] {
i + config.xOffset, j + config.yOffset });
} else if (bbb == bD2) {
// maxima
rval.maxVals.add(dataToContour[i][j]);
rval.maxVals.add((float) dataToContour.getDataValue(i,
j));
rval.maxLabelPoints.add(new float[] {
i + config.xOffset, j + config.yOffset });
}
@ -1341,8 +1300,6 @@ public class FortConBuf {
// | |
// point 1 (i,j)-------side 1------(i+1,j) point 2
float val = ConVal[c];
float minavg = MnAvg[c];
float maxavg = MxAvg[c];
byte cmw = CMask[c];
boolean GGG1 = false;
boolean GGG2 = false;
@ -1363,7 +1320,6 @@ public class FortConBuf {
float D2 = 0;
float D3 = 0;
float D4 = 0;
float DDQ = 0;
// reset point buffer
ijPntBuffer.setSize(0);
@ -1400,8 +1356,8 @@ public class FortConBuf {
icell = istart;
iplus = istart + 1;
clos1 = true;
D3 = dataToContour[iplus][jcell];
D4 = dataToContour[icell][jcell];
D3 = (float) dataToContour.getDataValue(iplus, jcell);
D4 = (float) dataToContour.getDataValue(icell, jcell);
GGG3 = val >= D3;
GGG4 = val >= D4;
if (GGG3 == GGG4) {
@ -1427,8 +1383,8 @@ public class FortConBuf {
jcell = jstart;
jplus = jstart + 1;
clos2 = true;
D1 = dataToContour[iplus][jcell];
D4 = dataToContour[iplus][jplus];
D1 = (float) dataToContour.getDataValue(iplus, jcell);
D4 = (float) dataToContour.getDataValue(iplus, jplus);
GGG1 = val >= D1;
GGG4 = val >= D4;
if (GGG1 == GGG4) {
@ -1454,8 +1410,8 @@ public class FortConBuf {
icell = istart;
iplus = istart + 1;
clos3 = true;
D1 = dataToContour[icell][jplus];
D2 = dataToContour[iplus][jplus];
D1 = (float) dataToContour.getDataValue(icell, jplus);
D2 = (float) dataToContour.getDataValue(iplus, jplus);
GGG1 = val >= D1;
GGG2 = val >= D2;
if (GGG1 == GGG2) {
@ -1481,8 +1437,8 @@ public class FortConBuf {
jcell = jstart;
jplus = jstart + 1;
clos4 = true;
D3 = dataToContour[icell][jplus];
D2 = dataToContour[icell][jcell];
D3 = (float) dataToContour.getDataValue(icell, jplus);
D2 = (float) dataToContour.getDataValue(icell, jcell);
GGG3 = val >= D3;
GGG2 = val >= D2;
if (GGG3 == GGG2) {
@ -1501,8 +1457,8 @@ public class FortConBuf {
D1 = D4;
GGG2 = GGG3;
D2 = D3;
D3 = dataToContour[iplus][jplus];
D4 = dataToContour[icell][jplus];
D3 = (float) dataToContour.getDataValue(iplus, jplus);
D4 = (float) dataToContour.getDataValue(icell, jplus);
GGG3 = val >= D3;
GGG4 = val >= D4;
@ -1513,7 +1469,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 4422;
continue JUMP_LOOP;
} else if ((work4[iplus][jcell] & 1) == 0) {
@ -1521,7 +1476,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 2244;
continue JUMP_LOOP;
}
@ -1531,7 +1485,6 @@ public class FortConBuf {
// Determine proper path through cell from side one
if (GGG3 == GGG4) {
celcnt += dld;
if (GGG2 == GGG3) {
jumpLabel = 4422;
continue JUMP_LOOP;
@ -1540,11 +1493,9 @@ public class FortConBuf {
continue JUMP_LOOP;
} else {
if (GGG1 == GGG4) {
celcnt += dly;
jumpLabel = 3311;
continue JUMP_LOOP;
}
celcnt += dld;
GGGD = val4 >= (D1 + D2 + D3 + D4);
if (GGG1 != GGGD) {
jumpLabel = 4422;
@ -1560,8 +1511,8 @@ public class FortConBuf {
D2 = D1;
GGG3 = GGG4;
D3 = D4;
D1 = dataToContour[icell][jcell];
D4 = dataToContour[icell][jplus];
D1 = (float) dataToContour.getDataValue(icell, jcell);
D4 = (float) dataToContour.getDataValue(icell, jplus);
GGG1 = val >= D1;
GGG4 = val >= D4;
@ -1572,7 +1523,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 3311;
continue JUMP_LOOP;
} else if ((work3[icell][jcell] & 1) == 0) {
@ -1580,7 +1530,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 1133;
continue JUMP_LOOP;
}
@ -1590,7 +1539,6 @@ public class FortConBuf {
// Determine proper path through cell from side two.
if (GGG1 == GGG4) {
celcnt += dld;
if (GGG3 == GGG4) {
jumpLabel = 1133;
continue JUMP_LOOP;
@ -1599,11 +1547,9 @@ public class FortConBuf {
continue JUMP_LOOP;
} else {
if (GGG1 == GGG2) {
celcnt += dlx;
jumpLabel = 4422;
continue JUMP_LOOP;
}
celcnt += dld;
GGGD = val4 >= (D1 + D2 + D3 + D4);
if (GGG2 != GGGD) {
jumpLabel = 1133;
@ -1619,8 +1565,8 @@ public class FortConBuf {
D3 = D2;
GGG4 = GGG1;
D4 = D1;
D1 = dataToContour[icell][jcell];
D2 = dataToContour[iplus][jcell];
D1 = (float) dataToContour.getDataValue(icell, jcell);
D2 = (float) dataToContour.getDataValue(iplus, jcell);
GGG1 = val >= D1;
GGG2 = val >= D2;
@ -1631,7 +1577,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 2244;
continue JUMP_LOOP;
} else if ((work4[icell][jcell] & 1) == 0) {
@ -1639,7 +1584,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 4422;
continue JUMP_LOOP;
}
@ -1649,7 +1593,6 @@ public class FortConBuf {
// Determine proper path through cell from side three
if (GGG1 == GGG2) {
celcnt += dld;
if (GGG1 == GGG4) {
jumpLabel = 2244;
continue JUMP_LOOP;
@ -1658,11 +1601,9 @@ public class FortConBuf {
continue JUMP_LOOP;
} else {
if (GGG2 == GGG3) {
celcnt += dly;
jumpLabel = 1133;
continue JUMP_LOOP;
}
celcnt += dld;
GGGD = val4 >= (D1 + D2 + D3 + D4);
if (GGG3 != GGGD) {
jumpLabel = 2244;
@ -1678,8 +1619,8 @@ public class FortConBuf {
D4 = D3;
GGG1 = GGG2;
D1 = D2;
D3 = dataToContour[iplus][jplus];
D2 = dataToContour[iplus][jcell];
D3 = (float) dataToContour.getDataValue(iplus, jplus);
D2 = (float) dataToContour.getDataValue(iplus, jcell);
GGG3 = val >= D3;
GGG2 = val >= D2;
@ -1690,7 +1631,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 1133;
continue JUMP_LOOP;
} else if ((work3[icell][jplus] & 1) == 0) {
@ -1698,7 +1638,6 @@ public class FortConBuf {
jumpLabel = 9000;
continue JUMP_LOOP;
}
celcnt += dld;
jumpLabel = 3311;
continue JUMP_LOOP;
}
@ -1708,7 +1647,6 @@ public class FortConBuf {
// Determine proper path through cell from side four.
if (GGG2 == GGG3) {
celcnt += dld;
if (GGG1 == GGG2) {
jumpLabel = 3311;
continue JUMP_LOOP;
@ -1717,11 +1655,9 @@ public class FortConBuf {
continue JUMP_LOOP;
} else {
if (GGG3 == GGG4) {
celcnt += dlx;
jumpLabel = 2244;
continue JUMP_LOOP;
}
celcnt += dld;
GGGD = val4 >= (D1 + D2 + D3 + D4);
if (GGG4 != GGGD) {
jumpLabel = 3311;
@ -1866,150 +1802,6 @@ public class FortConBuf {
}
}
private void markHrz(byte[][] workH, byte[][] workV, int i, int j) {
markCheck(workH, i, j);
if (labsep2 <= 0)
return;
markCheck(workV, i, j - 1);
markCheck(workV, i + 1, j - 1);
markCheck(workV, i, j);
markCheck(workV, i + 1, j);
markCheck(workH, i - 1, j);
markCheck(workH, i + 1, j);
if (labsep2 <= 1)
return;
markCheck(workV, i, j - 2);
markCheck(workV, i + 1, j - 2);
markCheck(workV, i - 1, j - 1);
markCheck(workV, i + 2, j - 1);
markCheck(workV, i - 1, j);
markCheck(workV, i + 2, j);
markCheck(workV, i, j + 1);
markCheck(workV, i + 1, j + 1);
markCheck(workH, i - 1, j - 1);
markCheck(workH, i, j - 1);
markCheck(workH, i + 1, j - 1);
markCheck(workH, i - 2, j);
markCheck(workH, i + 2, j);
markCheck(workH, i - 1, j + 1);
markCheck(workH, i, j + 1);
markCheck(workH, i + 1, j + 1);
if (labsep2 <= 2)
return;
markCheck(workV, i, j - 3);
markCheck(workV, i + 1, j - 3);
markCheck(workV, i - 1, j - 2);
markCheck(workV, i + 2, j - 2);
markCheck(workV, i - 2, j - 1);
markCheck(workV, i + 3, j - 1);
markCheck(workV, i - 2, j);
markCheck(workV, i + 3, j);
markCheck(workV, i - 1, j + 1);
markCheck(workV, i + 2, j + 1);
markCheck(workV, i, j + 2);
markCheck(workV, i + 1, j + 2);
markCheck(workH, i - 1, j - 2);
markCheck(workH, i, j - 2);
markCheck(workH, i + 1, j - 2);
markCheck(workH, i - 2, j - 1);
markCheck(workH, i + 2, j - 1);
markCheck(workH, i - 3, j);
markCheck(workH, i + 3, j);
markCheck(workH, i - 2, j + 1);
markCheck(workH, i + 2, j + 1);
markCheck(workH, i - 1, j + 2);
markCheck(workH, i, j + 2);
markCheck(workH, i + 1, j + 2);
if (labsep2 <= 3)
return;
markCheck(workV, i, j - 4);
markCheck(workV, i + 1, j - 4);
markCheck(workV, i - 1, j - 3);
markCheck(workV, i + 2, j - 3);
markCheck(workV, i - 2, j - 2);
markCheck(workV, i + 3, j - 2);
markCheck(workV, i - 3, j - 1);
markCheck(workV, i + 4, j - 1);
markCheck(workV, i - 3, j);
markCheck(workV, i + 4, j);
markCheck(workV, i - 2, j + 1);
markCheck(workV, i + 3, j + 1);
markCheck(workV, i - 1, j + 2);
markCheck(workV, i + 2, j + 2);
markCheck(workV, i, j + 3);
markCheck(workV, i + 1, j + 3);
markCheck(workH, i - 1, j - 3);
markCheck(workH, i, j - 3);
markCheck(workH, i + 1, j - 3);
markCheck(workH, i - 2, j - 2);
markCheck(workH, i + 2, j - 2);
markCheck(workH, i - 3, j - 1);
markCheck(workH, i + 3, j - 1);
markCheck(workH, i - 4, j);
markCheck(workH, i + 4, j);
markCheck(workH, i - 3, j + 1);
markCheck(workH, i + 3, j + 1);
markCheck(workH, i - 2, j + 2);
markCheck(workH, i + 2, j + 2);
markCheck(workH, i - 1, j + 3);
markCheck(workH, i, j + 3);
markCheck(workH, i + 1, j + 3);
if (labsep2 <= 4)
return;
markCheck(workV, i, j - 5);
markCheck(workV, i + 1, j - 5);
markCheck(workV, i - 1, j - 4);
markCheck(workV, i + 2, j - 4);
markCheck(workV, i - 2, j - 3);
markCheck(workV, i + 3, j - 3);
markCheck(workV, i - 3, j - 2);
markCheck(workV, i + 4, j - 2);
markCheck(workV, i - 4, j - 1);
markCheck(workV, i + 5, j - 1);
markCheck(workV, i - 4, j);
markCheck(workV, i + 5, j);
markCheck(workV, i - 3, j + 1);
markCheck(workV, i + 4, j + 1);
markCheck(workV, i - 2, j + 2);
markCheck(workV, i + 3, j + 2);
markCheck(workV, i - 1, j + 3);
markCheck(workV, i + 2, j + 3);
markCheck(workV, i, j + 4);
markCheck(workV, i + 1, j + 4);
markCheck(workH, i - 1, j - 4);
markCheck(workH, i, j - 4);
markCheck(workH, i + 1, j - 4);
markCheck(workH, i - 2, j - 3);
markCheck(workH, i + 2, j - 3);
markCheck(workH, i - 3, j - 2);
markCheck(workH, i + 3, j - 2);
markCheck(workH, i - 4, j - 1);
markCheck(workH, i + 4, j - 1);
markCheck(workH, i - 5, j);
markCheck(workH, i + 5, j);
markCheck(workH, i - 4, j + 1);
markCheck(workH, i + 4, j + 1);
markCheck(workH, i - 3, j + 2);
markCheck(workH, i + 3, j + 2);
markCheck(workH, i - 2, j + 3);
markCheck(workH, i + 2, j + 3);
markCheck(workH, i - 1, j + 4);
markCheck(workH, i, j + 4);
markCheck(workH, i + 1, j + 4);
if (labsep2 <= 5)
return;
}
private void markVrt(byte[][] workH, byte[][] workV, int i, int j) {
markCheck(workV, i, j);
if (labsep2 <= 0)

View file

@ -25,9 +25,10 @@ package com.raytheon.viz.core.contours.util;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 23, 2010 #4583 rjpeter Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 23, 2010 4583 rjpeter Initial creation
* Feb 27, 2014 2791 bsteffen Remove unused constructor arg
*
* </pre>
*
@ -59,7 +60,7 @@ public class PointBuffer {
* @param initialIndex
* @param forwardDirection
*/
public PointBuffer(int capacity, int initialIndex, boolean forwardDirection) {
public PointBuffer(int capacity, int initialIndex) {
buffer = new float[capacity * 2];
minIndex = initialIndex;
index = initialIndex;

View file

@ -24,6 +24,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.geospatial.interpolation.data.AxisSwapDataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArray2DWrapper;
import com.raytheon.viz.core.contours.util.StreamLineContainer.StreamLinePoint;
/**
@ -35,9 +38,10 @@ import com.raytheon.viz.core.contours.util.StreamLineContainer.StreamLinePoint;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 10, 2013 #1999 dgilling Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jun 10, 2013 1999 dgilling Initial creation
* Feb 27, 2014 2791 bsteffen Use DataSource for generic data access.
*
* </pre>
*
@ -126,11 +130,52 @@ public final class StrmPak {
private final PointValueBuffer<Float> JPnt;
/**
* Generate streamlines using column major float data.
*
* @param uComp
* data values for the u component of the vector
* @param vComp
* data values for the v component of the vector
* @param xSize
* unused
* @param nx
* number of x coordinates
* @param ny
* number of y coordinates
* @param config
* configuration options
* @return
*/
public static StreamLineContainer strmpak(float[][] uComp, float[][] vComp,
int xSize, int nx, int ny, StrmPakConfig config) {
DataSource uSource = new FloatArray2DWrapper(uComp, ny, nx);
DataSource vSource = new FloatArray2DWrapper(vComp, ny, nx);
uSource = new AxisSwapDataSource(uSource);
vSource = new AxisSwapDataSource(vSource);
return strmpak(uSource, vSource, nx, ny, config);
}
/**
* Generate streamlines using any data source.
*
* @param uComp
* data values for the u component of the vector
* @param vComp
* data values for the v component of the vector
* @param nx
* number of x coordinates
* @param ny
* number of y coordinates
* @param config
* configuration options
* @return
*/
public static StreamLineContainer strmpak(DataSource uComp,
DataSource vComp, int nx, int ny, StrmPakConfig config) {
StrmPak instance = new StrmPak();
StreamLineContainer rval = instance.strmpakInternal(uComp, vComp,
xSize, nx, ny, config);
StreamLineContainer rval = instance.strmpakInternal(uComp, vComp, nx,
ny, config);
return rval;
}
@ -150,8 +195,6 @@ public final class StrmPak {
* Array of U components
* @param V
* Array of V components
* @param mnx
* First dimension of data arrays.
* @param nx
* Inner dimension of grid.
* @param ny
@ -163,8 +206,8 @@ public final class StrmPak {
* the stream lines. Line segments will be divided by the sentinel
* value (-99999, -99999).
*/
private StreamLineContainer strmpakInternal(float[][] U, float[][] V,
int mnx, int nx, int ny, StrmPakConfig config) {
private StreamLineContainer strmpakInternal(DataSource U, DataSource V,
int nx, int ny, StrmPakConfig config) {
StreamLineContainer rVal = new StreamLineContainer();
// Initialize environment of streamline output.
@ -189,14 +232,22 @@ public final class StrmPak {
for (int j = jll; j <= jum; j++) {
int jj = j + 1;
if ((!((U[i][j] < config.badlo) || U[i][j] > config.badhi))
|| (!((U[i][jj] < config.badlo) || U[i][jj] > config.badhi))
|| (!((U[ii][j] < config.badlo) || U[ii][j] > config.badhi))
|| (!((U[ii][jj] < config.badlo) || U[ii][jj] > config.badhi))
|| (!((V[i][j] < config.badlo) || V[i][j] > config.badhi))
|| (!((V[i][jj] < config.badlo) || V[i][jj] > config.badhi))
|| (!((V[ii][j] < config.badlo) || V[ii][j] > config.badhi))
|| (!((V[ii][jj] < config.badlo) || V[ii][jj] > config.badhi))) {
if ((!((U.getDataValue(i, j) < config.badlo) || U.getDataValue(
i, j) > config.badhi))
|| (!((U.getDataValue(i, jj) < config.badlo) || U
.getDataValue(i, jj) > config.badhi))
|| (!((U.getDataValue(ii, j) < config.badlo) || U
.getDataValue(ii, j) > config.badhi))
|| (!((U.getDataValue(ii, jj) < config.badlo) || U
.getDataValue(ii, jj) > config.badhi))
|| (!((V.getDataValue(i, j) < config.badlo) || V
.getDataValue(i, j) > config.badhi))
|| (!((V.getDataValue(i, jj) < config.badlo) || V
.getDataValue(i, jj) > config.badhi))
|| (!((V.getDataValue(ii, j) < config.badlo) || V
.getDataValue(ii, j) > config.badhi))
|| (!((V.getDataValue(ii, jj) < config.badlo) || V
.getDataValue(ii, jj) > config.badhi))) {
Work[0][i][j] = -1;
Work[1][i][j] = -1;
continue;
@ -205,19 +256,23 @@ public final class StrmPak {
if ((minmag <= 0.0f) && (maxmag >= config.badlo)) {
continue;
}
float mag2 = U[i][j] * U[i][j] + V[i][j] * V[i][j];
double mag2 = U.getDataValue(i, j) * U.getDataValue(i, j)
+ V.getDataValue(i, j) * V.getDataValue(i, j);
if ((mag2 >= minmag2) && (mag2 <= maxmag2)) {
continue;
}
mag2 = U[ii][j] * U[ii][j] + V[ii][j] * V[ii][j];
mag2 = U.getDataValue(ii, j) * U.getDataValue(ii, j)
+ V.getDataValue(ii, j) * V.getDataValue(ii, j);
if ((mag2 >= minmag2) && (mag2 <= maxmag2)) {
continue;
}
mag2 = U[i][jj] * U[i][jj] + V[i][jj] * V[i][jj];
mag2 = U.getDataValue(i, jj) * U.getDataValue(i, jj)
+ V.getDataValue(i, jj) * V.getDataValue(i, jj);
if ((mag2 >= minmag2) && (mag2 <= maxmag2)) {
continue;
}
mag2 = U[ii][jj] * U[ii][jj] + V[ii][jj] * V[ii][jj];
mag2 = U.getDataValue(ii, jj) * U.getDataValue(ii, jj)
+ V.getDataValue(ii, jj) * V.getDataValue(ii, jj);
if ((mag2 >= minmag2) && (mag2 <= maxmag2)) {
continue;
}
@ -250,8 +305,8 @@ public final class StrmPak {
float rj0 = j1;
for (int i = i1; i <= i2 - 1; i += k) {
float ri0 = i + 0.5f;
StrmLin(U, V, Work, mnx, ri0, rj0, config.minspc,
mymax, rVal);
StrmLin(U, V, Work, ri0, rj0, config.minspc, mymax,
rVal);
}
j1 -= k;
again = true;
@ -261,8 +316,8 @@ public final class StrmPak {
float ri0 = i1;
for (int j = j1; j <= j2 - 1; j += k) {
float rj0 = j + 0.5f;
StrmLin(U, V, Work, mnx, ri0, rj0, config.minspc,
mymax, rVal);
StrmLin(U, V, Work, ri0, rj0, config.minspc, mymax,
rVal);
}
i1 -= k;
@ -273,8 +328,8 @@ public final class StrmPak {
float rj0 = j2;
for (int i = i1; i <= i2 - 1; i += k) {
float ri0 = i + 0.5f;
StrmLin(U, V, Work, mnx, ri0, rj0, config.minspc,
mymax, rVal);
StrmLin(U, V, Work, ri0, rj0, config.minspc, mymax,
rVal);
}
j2 += k;
again = true;
@ -284,8 +339,8 @@ public final class StrmPak {
float ri0 = i2;
for (int j = j1; j <= j2 - 1; j += k) {
float rj0 = j + 0.5f;
StrmLin(U, V, Work, mnx, ri0, rj0, config.minspc,
mymax, rVal);
StrmLin(U, V, Work, ri0, rj0, config.minspc, mymax,
rVal);
}
i2 += k;
again = true;
@ -311,8 +366,6 @@ public final class StrmPak {
* drawn in each cell. A value of -1 designates a cell as having
* bad or missing data. 1 is for previously drawn streamlines, 2
* includes the streamline currently being drawn.
* @param mnx
* First dimension of array to be countoured.
* @param ri0
* X-coordinate to draw the streamline through. Coordinates are
* in array index space.
@ -331,7 +384,7 @@ public final class StrmPak {
* <code>StreamLineContainer</code> object accumulating all line
* segments necessary to draw stream lines for U and V.
*/
private void StrmLin(float[][] U, float[][] V, byte[][][] Work, int mnx,
private void StrmLin(DataSource U, DataSource V, byte[][][] Work,
float ri0, float rj0, float minspc, float maxspc,
StreamLineContainer container) {
if ((ri0 < ill) || (ri0 > iur) || (rj0 < jll) || (rj0 > jur)) {
@ -463,15 +516,19 @@ public final class StrmPak {
// Determine whether we are working with or against the
// flow.
float dirflg;
float influx;
double influx;
if (side0 == 1) {
influx = V[i][j] * (1.0f - x) + V[ii][j] * x;
influx = V.getDataValue(i, j) * (1.0f - x)
+ V.getDataValue(ii, j) * x;
} else if (side0 == 2) {
influx = -(U[ii][j] * (1.0f - y) + U[ii][jj] * y);
influx = -(U.getDataValue(ii, j) * (1.0f - y) + U
.getDataValue(ii, jj) * y);
} else if (side0 == 3) {
influx = -(V[i][jj] * (1.0f - x) + V[ii][jj] * x);
influx = -(V.getDataValue(i, jj) * (1.0f - x) + V
.getDataValue(ii, jj) * x);
} else {
influx = U[i][j] * (1.0f - y) + U[i][jj] * y;
influx = U.getDataValue(i, j) * (1.0f - y)
+ U.getDataValue(i, jj) * y;
}
if (influx < 0.0f) {
dirflg = -1.0f;
@ -587,11 +644,15 @@ public final class StrmPak {
// Determine flux contributions from each component.
// FIXME? in fortran Flux was a size 8 array, indexed 1
// -> 8
float[] Flux = { Float.NaN, (-dirflg) * V[i][j],
(-dirflg) * V[ii][j], dirflg * U[ii][j],
dirflg * U[ii][jj], dirflg * V[ii][jj],
dirflg * V[i][jj], (-dirflg) * U[i][jj],
(-dirflg) * U[i][j] };
float[] Flux = { Float.NaN,
(-dirflg) * (float) V.getDataValue(i, j),
(-dirflg) * (float) V.getDataValue(ii, j),
dirflg * (float) U.getDataValue(ii, j),
dirflg * (float) U.getDataValue(ii, jj),
dirflg * (float) V.getDataValue(ii, jj),
dirflg * (float) V.getDataValue(i, jj),
(-dirflg) * (float) U.getDataValue(i, jj),
(-dirflg) * (float) U.getDataValue(i, j) };
// Count total number of in, out, and zero contributions
// to net flux.
@ -711,20 +772,22 @@ public final class StrmPak {
boolean forward;
if (side0 == 1) {
curloc = x;
forward = ((dirflg * (U[i][j] * (1.0f - x) + U[ii][j]
forward = ((dirflg * (U.getDataValue(i, j)
* (1.0f - x) + U.getDataValue(ii, j)
* x)) > 0.0f);
} else if (side0 == 2) {
curloc = 1.0f + y;
forward = ((dirflg * (V[ii][j] * (1.0f - y) + V[ii][jj]
forward = ((dirflg * (V.getDataValue(ii, j)
* (1.0f - y) + V.getDataValue(ii, jj)
* y)) > 0.0f);
} else if (side0 == 3) {
curloc = 3.0f - x;
forward = ((dirflg * (U[i][jj] * x + U[ii][jj]
* (1.0f - x))) < 0.0f);
forward = ((dirflg * (U.getDataValue(i, jj) * x + U
.getDataValue(ii, jj) * (1.0f - x))) < 0.0f);
} else {
curloc = 4.0f - y;
forward = ((dirflg * (V[i][j] * y + V[i][jj]
* (1.0f - y))) < 0.0f);
forward = ((dirflg * (V.getDataValue(i, j) * y + V
.getDataValue(i, jj) * (1.0f - y))) < 0.0f);
}
// Determine stream function value of entry

View file

@ -0,0 +1,52 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.geospatial.interpolation.data;
/**
* Wrapper source which swaps the X and Y axis when accessing data.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Feb 24, 2014 2791 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AxisSwapDataSource implements DataSource {
protected final DataSource wrappedSource;
public AxisSwapDataSource(DataSource wrappedSource) {
this.wrappedSource = wrappedSource;
}
@Override
public double getDataValue(int x, int y) {
return wrappedSource.getDataValue(y, x);
}
}

View file

@ -0,0 +1,51 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.geospatial.interpolation.data;
/**
* Provide utility method for copying data from a {@link DataSource} to a
* {@link DataDestination}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Feb 27, 2014 2791 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class DataCopy {
public static final <D extends DataDestination> D copy(DataSource source,
D destination, int nx, int ny) {
for (int i = 0; i < nx; i += 1) {
for (int j = 0; j < ny; j += 1) {
destination.setDataValue(source.getDataValue(i, j), i, j);
}
}
return destination;
}
}

View file

@ -0,0 +1,65 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.geospatial.interpolation.data;
/**
* Returns NaN for all data values that are within a range that can be
* considered invalid.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Feb 24, 2014 2791 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class InvalidRangeDataSource implements DataSource {
protected final DataSource wrappedSource;
protected final double badlo;
protected final double badhi;
public InvalidRangeDataSource(DataSource wrappedSource, double badlo,
double badhi) {
this.wrappedSource = wrappedSource;
this.badlo = badlo;
this.badhi = badhi;
}
@Override
public double getDataValue(int x, int y) {
double val = wrappedSource.getDataValue(y, x);
if (val > badlo && val < badhi) {
val = Double.NaN;
}
return val;
}
}

View file

@ -26,12 +26,13 @@ package com.raytheon.uf.common.wxmath;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 06, 2013 2043 bsteffen Ported from meteolib C
* Aug 13, 2013 2262 njensen Moved from deriv params
* Aug 13, 2013 2262 dgilling Adding additional constants from
* calcrh.f, hgt2pres.f, ztopsa.f, ptozsa.f
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jun 06, 2013 2043 bsteffen Ported from meteolib C
* Aug 13, 2013 2262 njensen Moved from deriv params
* Aug 13, 2013 2262 dgilling Adding additional constants from
* calcrh.f, hgt2pres.f, ztopsa.f, ptozsa.f
* Feb 27, 2014 2791 bsteffen Move commonly used legacy NaN here.
*
* </pre>
*
@ -95,6 +96,8 @@ public class Constants {
// from meteoLib hgt2pres.f, ztopsa.f, ptozsa.f
public static final double HGT_PRES_c2 = 14600.0;
public static final float LEGACY_NAN = 1e37f;
// Never allow this class to be directly instantiated
private Constants() {
throw new AssertionError();

View file

@ -28,10 +28,11 @@ import java.util.Arrays;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 10, 2011 rjpeter Initial creation
* Aug 13, 2013 2262 njensen Moved from deriv params
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Aug 10, 2011 rjpeter Initial creation
* Aug 13, 2013 2262 njensen Moved from deriv params
* Feb 27, 2014 2791 bsteffen Move legacy NaN to constants.
*
* </pre>
*
@ -144,7 +145,7 @@ public class DistFilter {
for (jj = dd; jj < ny; jj++, fpiMid += dnx, fpo += dnx) {
for (ii = dd; ii < nx; ii++, fpiMid++, fpo++) {
if (input[fpiMid] > 99998.0) {
output[fpo] = 1e37f;
output[fpo] = Constants.LEGACY_NAN;
continue;
}
@ -164,7 +165,7 @@ public class DistFilter {
}
if (tot < 0.95) {
output[fpo] = 1e37f;
output[fpo] = Constants.LEGACY_NAN;
} else {
output[fpo] /= tot;
}
@ -190,7 +191,7 @@ public class DistFilter {
}
if (input[fpiMid] > 99998.0) {
output[fpo] = 1e37f;
output[fpo] = Constants.LEGACY_NAN;
continue;
}
@ -211,7 +212,7 @@ public class DistFilter {
}
if (tot < 0.95) {
output[fpo] = 1e37f;
output[fpo] = Constants.LEGACY_NAN;
} else {
output[fpo] /= tot;
}

View file

@ -32,9 +32,10 @@ import java.util.Arrays;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 13, 2013 2262 njensen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Aug 13, 2013 2262 njensen Initial creation
* Feb 27, 2014 2791 bsteffen Move legacy NaN to constants.
*
* </pre>
*
@ -191,9 +192,9 @@ public class ScalelessAnalysis {
binidx[kk] = (short) (bb * 2 - 2);
double rat;
if (ii == 0) {
rat = (float) (jj) / 0.1;
rat = (jj) / 0.1;
} else if (jj == 0) {
rat = 0.1 / (float) (ii);
rat = 0.1 / (ii);
} else {
rat = (float) (jj) / (float) (ii);
}
@ -536,7 +537,7 @@ public class ScalelessAnalysis {
for (jj = sxy - 1; jj >= 0; jj--) {
int ii = 0;
for (int kk = jj * sxy; ii < sxy; ii++, kk++) {
System.err.printf("%d ", (int) (kswath0[kk]));
System.err.printf("%d ", (kswath0[kk]));
}
System.err.printf("\n");
}
@ -676,8 +677,8 @@ public class ScalelessAnalysis {
float[] grid = new float[nx * ny];
float[] raw = new float[nnd];
int[] counts = new int[nnd];
Arrays.fill(raw, 1e37f);
Arrays.fill(grid, 1e37f);
Arrays.fill(raw, Constants.LEGACY_NAN);
Arrays.fill(grid, Constants.LEGACY_NAN);
int raw0 = -ddd;
int counts0 = -ddd;
@ -743,7 +744,7 @@ public class ScalelessAnalysis {
/* work arrays with info about each grid resolved observation */
float[] dists = new float[nnd];
Arrays.fill(dists, 1e37f);
Arrays.fill(dists, Constants.LEGACY_NAN);
int dists0 = -ddd;
byte[] octant = new byte[nnd];
int[] nearest = new int[nnd];