Merge branch 'development_on_RHEL5' (GOES-R) into development
Conflicts: cave/com.raytheon.viz.satellite/src/com/raytheon/viz/satellite/rsc/SatBlendedResource.java nativeLib/edexBridge/edexBridge.cpp rpms/build/i386/build.sh rpms/build/x86_64/build.sh Former-commit-id:7969ef9648
[formerly760f215e8c
] [formerly f6787c0b9f2cb0cae1c07a2111e91ecfc12f31f5 [formerlyf5f75ec629
]] [formerlye82e1137f9
[formerlyf5f75ec629
[formerly 039d9ecb587338801cdab9cad11b06890517d6a4]]] Former-commit-id:e82e1137f9
Former-commit-id: cecc12c190bbaa908cbfe835a5a9a64a5ba96dba [formerly94994868fa
] Former-commit-id:ee03dcf505
This commit is contained in:
commit
2cafd3a81b
31 changed files with 1362 additions and 667 deletions
|
@ -76,10 +76,12 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 18, 2011 2190 mschenke Initial creation
|
||||
* Oct 2, 2013 2333 mschenke Converted to use IGridGeometryProvider
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Jul 18, 2011 2190 mschenke Initial creation
|
||||
* Oct 2, 2013 2333 mschenke Converted to use IGridGeometryProvider
|
||||
* Nov 20, 2013 2492 bsteffen Refactor deprecated references to
|
||||
* ColorMapParameters.getDataUnit
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -389,8 +391,8 @@ public class CloudHeightResource extends
|
|||
if (rsc != null && rsc.hasCapability(ColorMapCapability.class)) {
|
||||
ColorMapParameters params = rsc.getCapability(
|
||||
ColorMapCapability.class).getColorMapParameters();
|
||||
if (params != null && params.getDataUnit() != null
|
||||
&& TEMP_UNIT.isCompatible(params.getDataUnit())) {
|
||||
if (params != null && params.getColorMapUnit() != null
|
||||
&& TEMP_UNIT.isCompatible(params.getColorMapUnit())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import com.raytheon.uf.viz.core.maps.scales.MapScales.MapScale;
|
|||
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale;
|
||||
import com.raytheon.uf.viz.core.procedures.Bundle;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
|
||||
|
||||
/**
|
||||
* MapRenderableDisplay associated with a {@link MapScale}
|
||||
|
@ -47,10 +48,11 @@ import com.raytheon.uf.viz.core.rsc.ResourceList;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 22, 2013 mschenke Initial creation
|
||||
* Oct 10, 2013 2104 mschenke Switched to use MapScalesManager
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Mar 22, 2013 mschenke Initial creation
|
||||
* Oct 10, 2013 2104 mschenke Switched to use MapScalesManager
|
||||
* Nov 20, 2013 2492 bsteffen Recycle resources in clear.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -133,9 +135,13 @@ public class MapScaleRenderableDisplay extends PlainMapRenderableDisplay
|
|||
// non-map/system layers and reset display
|
||||
ResourceList list = descriptor.getResourceList();
|
||||
for (ResourcePair rp : list) {
|
||||
if (rp.getProperties().isMapLayer() == false
|
||||
&& rp.getProperties().isSystemResource() == false) {
|
||||
ResourceProperties props = rp.getProperties();
|
||||
if (props.isMapLayer() == false
|
||||
&& props.isSystemResource() == false) {
|
||||
list.remove(rp);
|
||||
} else {
|
||||
props.setVisible(true);
|
||||
rp.getResource().recycle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
|
@ -71,11 +70,13 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 19, 2013 2122 mschenke Initial creation.
|
||||
* Oct 16, 2013 2333 mschenke Added method for auto-unit conversion
|
||||
* interrogating
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Jun 19, 2013 2122 mschenke Initial creation.
|
||||
* Oct 16, 2013 2333 mschenke Added method for auto-unit conversion
|
||||
* interrogating
|
||||
* Nov 20, 2013 2492 bsteffen Move unit converting interrogate into
|
||||
* TileSetRenderable.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -369,61 +370,12 @@ public class RecordTileSetRenderable extends TileSetRenderable {
|
|||
return interrogate(coordinate, parameters.getNoDataValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate in units of desiredUnit
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @param desiredUnit
|
||||
* unit to convert data value to if not nanValue
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate, Unit<?> desiredUnit)
|
||||
@Override
|
||||
public double interrogate(Coordinate coordinate, Unit<?> resultUnit)
|
||||
throws VizException {
|
||||
ColorMapParameters parameters = colormapping.getColorMapParameters();
|
||||
return interrogate(coordinate, parameters.getNoDataValue(), desiredUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate in units of desiredUnit
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @param nanValue
|
||||
* if interrogated value is equal to nanValue, {@link Double#NaN}
|
||||
* will be returned
|
||||
* @param desiredUnit
|
||||
* unit to convert data value to if not nanValue
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate, double nanValue,
|
||||
Unit<?> desiredUnit) throws VizException {
|
||||
double dataValue = super.interrogate(coordinate, nanValue);
|
||||
if (Double.isNaN(dataValue) == false) {
|
||||
ColorMapParameters params = colormapping.getColorMapParameters();
|
||||
Unit<?> dataUnit = params.getDataUnit();
|
||||
if (dataUnit != null && desiredUnit != null
|
||||
&& dataUnit != desiredUnit) {
|
||||
if (dataUnit.isCompatible(desiredUnit)) {
|
||||
dataValue = dataUnit.getConverterTo(desiredUnit).convert(
|
||||
dataValue);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to interrogate tile set. "
|
||||
+ String.format(
|
||||
"Desired unit (%s) is not compatible with data unit (%s).",
|
||||
UnitFormat.getUCUMInstance()
|
||||
.format(desiredUnit),
|
||||
UnitFormat.getUCUMInstance()
|
||||
.format(dataUnit)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataValue;
|
||||
return super.interrogate(coordinate, resultUnit,
|
||||
parameters.getNoDataValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
|
@ -67,6 +70,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made
|
||||
* canceling jobs safer
|
||||
* Oct 16, 2013 2333 mschenke Added auto NaN checking for interrogation
|
||||
* Nov 14, 2013 2492 mschenke Added more interrogate methods that take units
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -475,12 +479,33 @@ public class TileSetRenderable implements IRenderable {
|
|||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate) throws VizException {
|
||||
return interrogate(coordinate, Double.NaN);
|
||||
return interrogate(coordinate, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate. Any values matching nanValue will return {@link Double#NaN}
|
||||
* coordinate
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @param resultUnit
|
||||
* unit result from interrogate will be returned is. If unit is
|
||||
* not compatible with data unit, {@link Double#NaN} will be
|
||||
* returned. Null indicates data will not be converted
|
||||
* @param nanValue
|
||||
* if interrogated value is equal to nanValue, {@link Double#NaN}
|
||||
* will be returned
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate, Unit<?> resultUnit)
|
||||
throws VizException {
|
||||
return interrogate(coordinate, resultUnit, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
|
@ -492,6 +517,27 @@ public class TileSetRenderable implements IRenderable {
|
|||
*/
|
||||
public double interrogate(Coordinate coordinate, double nanValue)
|
||||
throws VizException {
|
||||
return interrogate(coordinate, null, nanValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate. Any values matching nanValue will return {@link Double#NaN}
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @param resultUnit
|
||||
* unit result from interrogate will be returned is. If unit is
|
||||
* not compatible with data unit, {@link Double#NaN} will be
|
||||
* returned. Null indicates data will not be converted
|
||||
* @param nanValue
|
||||
* if interrogated value is equal to nanValue, {@link Double#NaN}
|
||||
* will be returned
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate, Unit<?> resultUnit,
|
||||
double nanValue) throws VizException {
|
||||
double dataValue = Double.NaN;
|
||||
try {
|
||||
double[] local = new double[2];
|
||||
|
@ -515,8 +561,27 @@ public class TileSetRenderable implements IRenderable {
|
|||
% tileSize);
|
||||
if (dataValue == nanValue) {
|
||||
dataValue = Double.NaN;
|
||||
} else {
|
||||
Unit<?> dataUnit = cmapImage.getDataUnit();
|
||||
if (resultUnit != null && dataUnit != null
|
||||
&& dataUnit.equals(resultUnit) == false) {
|
||||
if (resultUnit.isCompatible(dataUnit)) {
|
||||
dataValue = dataUnit.getConverterTo(
|
||||
resultUnit).convert(dataValue);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to interrogate tile set. "
|
||||
+ String.format(
|
||||
"Desired unit (%s) is not compatible with data unit (%s).",
|
||||
UnitFormat
|
||||
.getUCUMInstance()
|
||||
.format(resultUnit),
|
||||
UnitFormat
|
||||
.getUCUMInstance()
|
||||
.format(dataUnit)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ vec4 applyColorBand(int colorband) {
|
|||
vec2((xy.x / width), (xy.y / height)));
|
||||
|
||||
// Lookup raw data value
|
||||
float dataValue = getDataValue(rawData, gl_TexCoord[0].st);
|
||||
float dataValue = textureToDataValue(rawData, gl_TexCoord[0].st);
|
||||
|
||||
float r = curVal.r;
|
||||
float g = curVal.g;
|
||||
|
|
|
@ -232,8 +232,7 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
|||
parameters.put(colorMapParameters, null);
|
||||
|
||||
GLSLStructFactory.createDataTexture(program, "rawData", 0,
|
||||
cmapImage.getDataFormat(),
|
||||
colorMapParameters.getNoDataValue());
|
||||
cmapImage);
|
||||
|
||||
int numMappingValues = 0;
|
||||
GLDataMapping mapping = cmapImage.getDataMapping();
|
||||
|
|
|
@ -7,7 +7,7 @@ uniform ColorMapping colorMapping;
|
|||
uniform ColorModifiers modifiers;
|
||||
|
||||
void main(void) {
|
||||
float dataValue = getDataValue(rawData, gl_TexCoord[0].st);
|
||||
float dataValue = textureToDataValue(rawData, gl_TexCoord[0].st);
|
||||
|
||||
// No data check/special NaN check
|
||||
if (dataValue == rawData.noDataValue || dataValue != dataValue) {
|
||||
|
|
|
@ -14,6 +14,8 @@ struct DataTexture {
|
|||
int isScaled;
|
||||
float scaleMin;
|
||||
float scaleMax;
|
||||
float width;
|
||||
float height;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -51,7 +53,7 @@ struct ColorMapping {
|
|||
/**
|
||||
* Returns the data value for the DataTexture at location.
|
||||
*/
|
||||
float getDataValue(DataTexture texture, vec2 location) {
|
||||
float textureToDataValue(DataTexture texture, vec2 location) {
|
||||
vec4 textureValue = texture2D(texture.rawTex, location);
|
||||
float dataValue = textureValue.r;
|
||||
|
||||
|
@ -63,6 +65,18 @@ float getDataValue(DataTexture texture, vec2 location) {
|
|||
return dataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data value for the DataTexture at location.
|
||||
*/
|
||||
float dataToTextureValue(DataTexture texture, float dataValue) {
|
||||
float textureValue = dataValue;
|
||||
if (texture.isScaled == 1) {
|
||||
textureValue = (dataValue - texture.scaleMin)
|
||||
/ (texture.scaleMax - texture.scaleMin);
|
||||
}
|
||||
return textureValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a value in a mapping texture given an index [0-numMappingValues).
|
||||
*/
|
||||
|
@ -103,8 +117,8 @@ float dataToColorMapValue(float dataValue, DataMapping mapping) {
|
|||
int nextIndex = lowIndex + ((highIndex - lowIndex) / 2);
|
||||
if (nextIndex > lowIndex && nextIndex < highIndex) {
|
||||
// Look up next value and determine if it is a high or low
|
||||
float nextValue = lookupMappingValue(mapping.dataMappingValues, nextIndex,
|
||||
numMappingValues);
|
||||
float nextValue = lookupMappingValue(mapping.dataMappingValues,
|
||||
nextIndex, numMappingValues);
|
||||
if (nextValue < dataValue) {
|
||||
if (reversed == 0) {
|
||||
lowIndex = nextIndex;
|
||||
|
@ -132,10 +146,10 @@ float dataToColorMapValue(float dataValue, DataMapping mapping) {
|
|||
factor = 1.0 - factor;
|
||||
}
|
||||
|
||||
float lowCmapValue = lookupMappingValue(mapping.colorMappingValues, lowIndex,
|
||||
numMappingValues);
|
||||
float highCmapValue = lookupMappingValue(mapping.colorMappingValues, highIndex,
|
||||
numMappingValues);
|
||||
float lowCmapValue = lookupMappingValue(mapping.colorMappingValues,
|
||||
lowIndex, numMappingValues);
|
||||
float highCmapValue = lookupMappingValue(mapping.colorMappingValues,
|
||||
highIndex, numMappingValues);
|
||||
|
||||
return lowCmapValue + (highCmapValue - lowCmapValue) * factor;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
// this shader program sets values into a mosaic texture
|
||||
// which is the same size as the screen (frame buffer)
|
||||
|
||||
uniform sampler2D imageData;
|
||||
uniform sampler2D mosaicTexture;
|
||||
uniform int height;
|
||||
uniform int width;
|
||||
#include <mapping>
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 xy = gl_FragCoord.xy;
|
||||
vec4 imageVal = texture2D(imageData,gl_TexCoord[0].st);
|
||||
vec4 curVal = texture2D(mosaicTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
|
||||
if ( imageVal.r > curVal.r ) {
|
||||
gl_FragColor = vec4(imageVal.r,0.0,0.0,1.0);
|
||||
} else {
|
||||
gl_FragColor = vec4(curVal.r,0.0,0.0,1.0);
|
||||
uniform DataTexture imageData;
|
||||
uniform DataMapping imageToMosaic;
|
||||
uniform DataTexture mosaicData;
|
||||
|
||||
void main(void) {
|
||||
float imageValue = textureToDataValue(imageData, gl_TexCoord[0].st);
|
||||
vec2 frag_xy = gl_FragCoord.xy;
|
||||
float mosaicValue = textureToDataValue(mosaicData,
|
||||
vec2(frag_xy.x / mosaicData.width, frag_xy.y / mosaicData.height));
|
||||
|
||||
float newValue = mosaicValue;
|
||||
// No data check/special NaN check
|
||||
if (imageValue != imageData.noDataValue && imageValue == imageValue) {
|
||||
// Convert image value to mosaic value
|
||||
imageValue = dataToColorMapValue(imageValue, imageToMosaic);
|
||||
if (imageValue > mosaicValue) {
|
||||
newValue = imageValue;
|
||||
}
|
||||
}
|
||||
gl_FragColor = vec4(dataToTextureValue(mosaicData, newValue), 0.0, 0.0,
|
||||
1.0);
|
||||
}
|
|
@ -1,20 +1,26 @@
|
|||
// this shader program sets values into a mosaic texture
|
||||
// which is the same size as the screen (frame buffer)
|
||||
|
||||
uniform sampler2D imageData;
|
||||
uniform sampler2D mosaicTexture;
|
||||
uniform int height;
|
||||
uniform int width;
|
||||
#include <mapping>
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 xy = gl_FragCoord.xy;
|
||||
vec4 imageVal = texture2D(imageData,gl_TexCoord[0].st);
|
||||
vec4 curVal = texture2D(mosaicTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
|
||||
// assume 0 or NaN is No Data and should be replaced if another image has better values.
|
||||
if ( imageVal.r != 0.0 && imageVal.r == imageVal.r) {
|
||||
gl_FragColor = vec4(imageVal.r,0.0,0.0,1.0);
|
||||
uniform DataTexture imageData;
|
||||
uniform DataMapping imageToMosaic;
|
||||
uniform DataTexture mosaicData;
|
||||
|
||||
void main(void) {
|
||||
float imageValue = textureToDataValue(imageData, gl_TexCoord[0].st);
|
||||
vec2 frag_xy = gl_FragCoord.xy;
|
||||
float mosaicValue = textureToDataValue(mosaicData,
|
||||
vec2(frag_xy.x / mosaicData.width, frag_xy.y / mosaicData.height));
|
||||
|
||||
float newValue;
|
||||
// No data check/special NaN check
|
||||
if (imageValue == imageData.noDataValue || imageValue != imageValue) {
|
||||
// Use existing value
|
||||
newValue = mosaicValue;
|
||||
} else {
|
||||
gl_FragColor = vec4(curVal.r,0.0,0.0,1.0);
|
||||
newValue = dataToColorMapValue(imageValue, imageToMosaic);
|
||||
}
|
||||
gl_FragColor = vec4(dataToTextureValue(mosaicData, newValue), 0.0, 0.0,
|
||||
1.0);
|
||||
}
|
|
@ -53,9 +53,6 @@
|
|||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicMaxValImageExtension">
|
||||
</graphicsExtension>
|
||||
|
|
|
@ -54,14 +54,16 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Nov 18, 2011 mschenke Initial creation
|
||||
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
|
||||
* parameters, disable colormap interpolation
|
||||
* by default.
|
||||
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled.
|
||||
* Added support for colormapping in non-data unit.
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Nov 18, 2011 mschenke Initial creation
|
||||
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
|
||||
* parameters, disable colormap interpolation
|
||||
* by default.
|
||||
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled.
|
||||
* Added support for colormapping in non-data unit.
|
||||
* Nov 20, 2013 2492 bsteffen Mosaic in image units.
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -174,7 +176,8 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets up a {@link GLDataMapping} for use in image rendering
|
||||
* Sets up a {@link GLDataMapping} for use in image rendering. Data will be
|
||||
* mapped to the image's {@link ColorMapParameters#getColorMapUnit()}
|
||||
*
|
||||
* @param gl
|
||||
* @param glImage
|
||||
|
@ -185,14 +188,32 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
|||
public static void setupDataMapping(GL gl,
|
||||
AbstractGLColormappedImage glImage, int dataMappedTexBinding,
|
||||
int colorMappedTexBinding) throws VizException {
|
||||
setupDataMapping(gl, glImage, glImage.getColorMapParameters()
|
||||
.getColorMapUnit(), dataMappedTexBinding, colorMappedTexBinding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a {@link GLDataMapping} for use in image renderingData will be
|
||||
* mapped to the unit provided
|
||||
*
|
||||
* @param gl
|
||||
* @param glImage
|
||||
* @param colorMapUnit
|
||||
* @param dataMappedTexBinding
|
||||
* @param colorMappedTexBinding
|
||||
* @throws VizException
|
||||
*/
|
||||
public static void setupDataMapping(GL gl,
|
||||
AbstractGLColormappedImage glImage, Unit<?> colorMapUnit,
|
||||
int dataMappedTexBinding, int colorMappedTexBinding)
|
||||
throws VizException {
|
||||
ColorMapParameters colorMapParameters = glImage.getColorMapParameters();
|
||||
// Get GLDataMapping and generate if datamapping is not set. If
|
||||
// datamapping is not set, the data has already been mapped to
|
||||
// colorMapUnits and we need not do anything
|
||||
GLDataMapping dataMapping = glImage.getDataMapping();
|
||||
if (dataMapping == null && colorMapParameters.getDataMapping() == null) {
|
||||
Unit<?> colorMapUnit = colorMapParameters.getColorMapUnit();
|
||||
Unit<?> dataUnit = colorMapParameters.getDataUnit();
|
||||
Unit<?> dataUnit = glImage.getDataUnit();
|
||||
int colorMapSize = colorMapParameters.getColorMap().getSize();
|
||||
float colorMapMin = colorMapParameters.getColorMapMin();
|
||||
float colorMapMax = colorMapParameters.getColorMapMax();
|
||||
|
@ -290,8 +311,7 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
|||
|
||||
ColorMapParameters colorMapParameters = image.getColorMapParameters();
|
||||
|
||||
GLSLStructFactory.createDataTexture(program, "rawData", 0,
|
||||
image.getDataFormat(), colorMapParameters.getNoDataValue());
|
||||
GLSLStructFactory.createDataTexture(program, "rawData", 0, image);
|
||||
|
||||
int numMappingValues = 0;
|
||||
GLDataMapping mapping = image.getDataMapping();
|
||||
|
|
|
@ -21,6 +21,7 @@ package com.raytheon.viz.core.gl.glsl;
|
|||
|
||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
|
||||
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
|
||||
|
||||
/**
|
||||
* Factory for creating API defined GLSL structs in a {@link GLShaderProgram}.
|
||||
|
@ -49,14 +50,15 @@ public class GLSLStructFactory {
|
|||
* @param program
|
||||
* @param name
|
||||
* @param texBinding
|
||||
* @param dataFormat
|
||||
* @param noDataValue
|
||||
* @param image
|
||||
*/
|
||||
public static void createDataTexture(GLShaderProgram program, String name,
|
||||
int texBinding, AbstractGLColorMapDataFormat dataFormat,
|
||||
double noDataValue) {
|
||||
int texBinding, AbstractGLColormappedImage image) {
|
||||
ColorMapParameters parameters = image.getColorMapParameters();
|
||||
AbstractGLColorMapDataFormat dataFormat = image.getDataFormat();
|
||||
setFieldUniform(program, name, "rawTex", texBinding);
|
||||
setFieldUniform(program, name, "noDataValue", noDataValue);
|
||||
setFieldUniform(program, name, "noDataValue",
|
||||
parameters.getNoDataValue());
|
||||
setFieldUniform(program, name, "isScaled", dataFormat.isScaled());
|
||||
if (dataFormat.isScaled()) {
|
||||
setFieldUniform(program, name, "scaleMin",
|
||||
|
@ -64,6 +66,8 @@ public class GLSLStructFactory {
|
|||
setFieldUniform(program, name, "scaleMax",
|
||||
dataFormat.getDataFormatMax());
|
||||
}
|
||||
setFieldUniform(program, name, "width", (float) image.getWidth());
|
||||
setFieldUniform(program, name, "height", (float) image.getHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,8 +33,12 @@ import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
|||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
|
||||
import com.raytheon.viz.core.gl.ext.imaging.GLColormappedImageExtension;
|
||||
import com.raytheon.viz.core.gl.ext.imaging.GLDataMappingFactory.GLDataMapping;
|
||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
|
||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
||||
import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
|
||||
|
@ -46,13 +50,14 @@ import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 16, 2011 mschenke Initial creation
|
||||
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
|
||||
* format for offscreen textures.
|
||||
* Oct 16, 2013 2333 mschenke Cleaned up render logic, switched to
|
||||
* use GLOffscreenColormappedImage
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Dec 16, 2011 mschenke Initial creation
|
||||
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
|
||||
* format for offscreen textures.
|
||||
* Oct 16, 2013 2333 mschenke Cleaned up render logic, switched to use
|
||||
* GLOffscreenColormappedImage
|
||||
* Nov 20, 2013 2492 bsteffen Mosaic in image units.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -60,8 +65,8 @@ import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
|
||||
implements IMosaicImageExtension {
|
||||
public abstract class GLMosaicImageExtension extends
|
||||
AbstractGLSLImagingExtension implements IMosaicImageExtension {
|
||||
|
||||
private GLOffscreenColormappedImage writeToImage;
|
||||
|
||||
|
@ -75,19 +80,6 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
|
|||
imageExtent, this.getClass());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#getShaderProgramName
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public String getShaderProgramName() {
|
||||
// Default mosaicing algorithm glsl program
|
||||
return "mosaicOrdered";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -142,16 +134,20 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
|
|||
new DrawableImage(mosaicImage.getWrappedImage(),
|
||||
coverage));
|
||||
}
|
||||
// Don't actually render this image now since we just did it
|
||||
return null;
|
||||
} else {
|
||||
} else if (image instanceof AbstractGLColormappedImage) {
|
||||
GL gl = target.getGl();
|
||||
// activate on texture2 as 0 is radar image and 1 is colormap
|
||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||
gl.glBindTexture(writeToImage.getTextureStorageType(),
|
||||
writeToImage.getTextureid());
|
||||
|
||||
GLColormappedImageExtension.setupDataMapping(gl,
|
||||
(AbstractGLColormappedImage) image,
|
||||
writeToImage.getDataUnit(), 2, 3);
|
||||
return image;
|
||||
}
|
||||
// Fall through here, no actual rendering will occur
|
||||
return null;
|
||||
}
|
||||
|
||||
private GLOffscreenColormappedImage getWriteToImage(
|
||||
|
@ -208,6 +204,12 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
|
|||
// activate on texture2 as 0 is radar image
|
||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
|
||||
|
||||
gl.glActiveTexture(GL.GL_TEXTURE2);
|
||||
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||
|
||||
gl.glActiveTexture(GL.GL_TEXTURE3);
|
||||
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -220,14 +222,27 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
|
|||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void loadShaderData(GLShaderProgram program, IImage image,
|
||||
public void loadShaderData(GLShaderProgram program, IImage iimage,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
program.setUniform("imageData", 0);
|
||||
program.setUniform("mosaicTexture", 1);
|
||||
AbstractGLColormappedImage image = null;
|
||||
if (iimage instanceof AbstractGLColormappedImage == false) {
|
||||
throw new VizException(
|
||||
"Cannot apply glsl mosaicing shader to non gl colormap image");
|
||||
}
|
||||
image = (AbstractGLColormappedImage) iimage;
|
||||
|
||||
// pass in width and height
|
||||
program.setUniform("height", writeToImage.getHeight());
|
||||
program.setUniform("width", writeToImage.getWidth());
|
||||
GLSLStructFactory.createDataTexture(program, "imageData", 0, image);
|
||||
|
||||
int numMappingValues = 0;
|
||||
GLDataMapping mapping = image.getDataMapping();
|
||||
if (mapping != null && mapping.isValid()) {
|
||||
numMappingValues = mapping.getNumMappingValues();
|
||||
}
|
||||
GLSLStructFactory.createDataMapping(program, "imageToMosaic", 2, 3,
|
||||
numMappingValues);
|
||||
|
||||
GLSLStructFactory.createDataTexture(program, "mosaicData", 1,
|
||||
writeToImage);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.measure.Measure;
|
||||
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||
|
@ -64,6 +66,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* only check for NaN. SatResource handles fill
|
||||
* values and returns NaN now
|
||||
* Nov 18, 2013 2544 bsteffen Override recycleInternal
|
||||
* Nov 20, 2013 2492 bsteffen Update inspect to use Measure objects
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -291,10 +294,12 @@ public class SatBlendedResource extends
|
|||
for (int i = list.size() - 1; i >= 0; --i) {
|
||||
AbstractVizResource<?, ?> rsc = list.get(i).getResource();
|
||||
Map<String, Object> dataMap = rsc.interrogate(coord);
|
||||
if (dataMap.get(SatResource.RAW_VALUE) instanceof Number) {
|
||||
double value = ((Number) dataMap.get(SatResource.RAW_VALUE))
|
||||
Measure<?, ?> value = (Measure<?, ?>) dataMap
|
||||
.get(SatResource.SATELLITE_DATA_INTERROGATE_ID);
|
||||
if (value != null && value.getValue() instanceof Number) {
|
||||
double measuredValue = ((Number) value.getValue())
|
||||
.doubleValue();
|
||||
if (Double.isNaN(value) == false) {
|
||||
if (Double.isNaN(measuredValue) == false) {
|
||||
// use this resource
|
||||
inspectString = rsc.inspect(coord);
|
||||
break;
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
|
||||
import javax.measure.Measure;
|
||||
import javax.measure.converter.UnitConverter;
|
||||
import javax.measure.quantity.Temperature;
|
||||
import javax.measure.unit.Unit;
|
||||
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
@ -41,18 +42,14 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
|||
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
|
||||
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
|
||||
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits;
|
||||
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
|
||||
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
|
||||
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
|
||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||
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.ParamLevelMatchCriteria;
|
||||
import com.raytheon.uf.common.style.StyleException;
|
||||
import com.raytheon.uf.common.style.StyleManager;
|
||||
import com.raytheon.uf.common.style.StyleRule;
|
||||
import com.raytheon.uf.common.style.image.ColorMapParameterFactory;
|
||||
import com.raytheon.uf.common.style.image.DataScale;
|
||||
import com.raytheon.uf.common.style.image.ImagePreferences;
|
||||
import com.raytheon.uf.common.style.image.SamplePreferences;
|
||||
import com.raytheon.uf.common.style.level.Level;
|
||||
|
@ -82,19 +79,25 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 1, 2007 chammack Initial Creation.
|
||||
* 02/17/2009 njensen Refactored to new rsc architecture.
|
||||
* 03/02/2009 2032 jsanchez Added check for displayedDate if no data.
|
||||
* 03/25/2009 2086 jsanchez Mapped correct converter to parameter type.
|
||||
* Updated the call to ColormapParametersFactory.build
|
||||
* 03/30/2009 2169 jsanchez Updated numLevels handling.
|
||||
* - AWIPS2 Baseline Repository --------
|
||||
* 07/17/2012 798 jkorman Use decimationLevels from SatelliteRecord. Removed hard-coded
|
||||
* data set names.
|
||||
* 06/20/2013 2122 mschenke Modified to use SatTileSetRenderable
|
||||
* 07/31/2013 2190 mschenke Switched to use Measure objects for interrogation
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Mar 01, 2007 chammack Initial Creation.
|
||||
* Feb 17, 2009 njensen Refactored to new rsc architecture.
|
||||
* Mar 02, 2009 2032 jsanchez Added check for displayedDate if no
|
||||
* data.
|
||||
* Mar 25, 2009 2086 jsanchez Mapped correct converter to parameter
|
||||
* type. Updated the call to
|
||||
* ColormapParametersFactory.build
|
||||
* Mar 30, 2009 2169 jsanchez Updated numLevels handling.
|
||||
* Jul 17, 2012 798 jkorman Use decimationLevels from
|
||||
* SatelliteRecord. Removed hard-coded
|
||||
* data set names.
|
||||
* Jun 20, 2013 2122 mschenke Modified to use SatTileSetRenderable
|
||||
* Jul 31, 2013 2190 mschenke Switched to use Measure objects for
|
||||
* interrogation
|
||||
* Nov 20, 2013 2492 bsteffen Always get min/max values from style
|
||||
* rules.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author chammack
|
||||
|
@ -103,11 +106,6 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
public class SatResource extends
|
||||
AbstractPluginDataObjectResource<SatResourceData, IMapDescriptor> {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(SatResource.class);
|
||||
|
||||
public static String RAW_VALUE = "rawValue";
|
||||
|
||||
/** String id to look for satellite-provided data values */
|
||||
public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue";
|
||||
|
||||
|
@ -215,12 +213,12 @@ public class SatResource extends
|
|||
}
|
||||
}
|
||||
|
||||
public InterrogationResult interrogate(Coordinate latLon)
|
||||
throws VizException {
|
||||
public InterrogationResult interrogate(Coordinate latLon,
|
||||
Unit<?> requestUnit) throws VizException {
|
||||
InterrogationResult result = null;
|
||||
synchronized (tileMap) {
|
||||
for (SatTileSetRenderable renderable : tileMap.values()) {
|
||||
double rValue = renderable.interrogate(latLon, fillValue);
|
||||
double rValue = renderable.interrogate(latLon, requestUnit);
|
||||
if (Double.isNaN(rValue) == false) {
|
||||
result = new InterrogationResult(
|
||||
renderable.getSatelliteRecord(), rValue);
|
||||
|
@ -235,7 +233,8 @@ public class SatResource extends
|
|||
|
||||
protected SamplePreferences sampleRange;
|
||||
|
||||
protected double fillValue = 0;
|
||||
/** Flag to avoid reinitializing ColorMapParameters from style rules */
|
||||
private boolean initialized = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -249,21 +248,19 @@ public class SatResource extends
|
|||
|
||||
@Override
|
||||
protected DataTime getDataObjectTime(PluginDataObject pdo) {
|
||||
SatelliteRecord record = (SatelliteRecord) pdo;
|
||||
if (dataTimes.isEmpty()) {
|
||||
if (initialized == false) {
|
||||
try {
|
||||
initializeFirstFrame(record);
|
||||
initializeFirstFrame((SatelliteRecord) pdo);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
throw new IllegalStateException(
|
||||
"Unable to initialize the satellite resource");
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
DataTime pdoTime = pdo.getDataTime();
|
||||
if (resourceData.getBinOffset() != null) {
|
||||
pdoTime = resourceData.getBinOffset().getNormalizedTime(pdoTime);
|
||||
}
|
||||
|
||||
return pdoTime;
|
||||
}
|
||||
|
||||
|
@ -286,7 +283,6 @@ public class SatResource extends
|
|||
}
|
||||
|
||||
SingleLevel level = new SingleLevel(Level.LevelType.SURFACE);
|
||||
Unit<?> unit = SatDataRetriever.getRecordUnit(record);
|
||||
String physicalElement = null;
|
||||
DerivedParameterRequest request = (DerivedParameterRequest) record
|
||||
.getMessageData();
|
||||
|
@ -301,25 +297,42 @@ public class SatResource extends
|
|||
match.setParameterName(Arrays.asList(physicalElement));
|
||||
match.setLevels(Arrays.asList((Level) level));
|
||||
match.setCreatingEntityNames(Arrays.asList(record.getCreatingEntity()));
|
||||
StyleRule sr;
|
||||
Unit<?> unit = SatDataRetriever.getRecordUnit(record);
|
||||
try {
|
||||
sr = StyleManager.getInstance().getStyleRule(
|
||||
StyleRule sr = StyleManager.getInstance().getStyleRule(
|
||||
StyleManager.StyleType.IMAGERY, match);
|
||||
} catch (StyleException e) {
|
||||
throw new VizException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
if (sr != null && sr.getPreferences() instanceof ImagePreferences) {
|
||||
sampleRange = ((ImagePreferences) sr.getPreferences())
|
||||
.getSamplePrefs();
|
||||
String lg = ((ImagePreferences) sr.getPreferences()).getLegend();
|
||||
|
||||
ImagePreferences preferences = null;
|
||||
if (sr == null
|
||||
|| sr.getPreferences() instanceof ImagePreferences == false) {
|
||||
// No style rule, this is a best guess at what might look good.
|
||||
preferences = new ImagePreferences();
|
||||
if (unit != null && unit.isCompatible(Temperature.UNIT)) {
|
||||
preferences.setDefaultColormap("Sat/IR/CIRA (IR Default)");
|
||||
} else {
|
||||
preferences.setDefaultColormap("Sat/VIS/ZA (Vis Default)");
|
||||
}
|
||||
DataScale range = new DataScale();
|
||||
range.setScaleType(DataScale.Type.LINEAR);
|
||||
range.setMinValue(0.0);
|
||||
range.setMaxValue(255.0);
|
||||
preferences.setDataScale(range);
|
||||
} else {
|
||||
preferences = (ImagePreferences) sr.getPreferences();
|
||||
}
|
||||
colorMapParameters = ColorMapParameterFactory.build(preferences,
|
||||
unit);
|
||||
|
||||
sampleRange = preferences.getSamplePrefs();
|
||||
String lg = preferences.getLegend();
|
||||
// test, so legend is not over written with empty string
|
||||
if (lg != null && !lg.trim().isEmpty()) {
|
||||
legend = lg;
|
||||
}
|
||||
} catch (StyleException e) {
|
||||
throw new VizException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
colorMapParameters = ColorMapParameterFactory.build(sr, null, level,
|
||||
unit);
|
||||
// If null, set from style rules
|
||||
if (cmName == null) {
|
||||
cmName = colorMapParameters.getColorMapName();
|
||||
|
@ -343,26 +356,7 @@ public class SatResource extends
|
|||
if (persisted != null) {
|
||||
colorMapParameters.applyPersistedParameters(persisted);
|
||||
}
|
||||
|
||||
// TODO: Figure out data/color map min/max values better
|
||||
if (unit == null) {
|
||||
colorMapParameters.setColorMapMin(0.0f);
|
||||
colorMapParameters.setColorMapMax(255.0f);
|
||||
}
|
||||
if (unit instanceof GenericPixel) {
|
||||
// Derived parameter data will be signed
|
||||
colorMapParameters.setDataMin(-128.0f);
|
||||
colorMapParameters.setDataMax(127.0f);
|
||||
} else if (unit instanceof BlendedTPWPixel) {
|
||||
colorMapParameters.setDataMin(0.0f);
|
||||
colorMapParameters.setDataMax(252.0f);
|
||||
|
||||
colorMapParameters.setColorMapMin(0.0f);
|
||||
colorMapParameters.setColorMapMax(252.0f);
|
||||
} else {
|
||||
colorMapParameters.setDataMin(0.0f);
|
||||
colorMapParameters.setDataMax(255.0f);
|
||||
}
|
||||
colorMapParameters.setNoDataValue(0);
|
||||
|
||||
getCapability(ColorMapCapability.class).setColorMapParameters(
|
||||
colorMapParameters);
|
||||
|
@ -389,10 +383,11 @@ public class SatResource extends
|
|||
ColorMapParameters parameters = getCapability(ColorMapCapability.class)
|
||||
.getColorMapParameters();
|
||||
double dataValue = Double.NaN;
|
||||
Unit<?> dataUnit = parameters.getColorMapUnit();
|
||||
if (renderable != null) {
|
||||
try {
|
||||
InterrogationResult result = renderable.interrogate(coord
|
||||
.asLatLon());
|
||||
InterrogationResult result = renderable.interrogate(
|
||||
coord.asLatLon(), dataUnit);
|
||||
if (result != null) {
|
||||
dataValue = result.getValue();
|
||||
dataMap.put(IGridGeometryProvider.class.toString(), result
|
||||
|
@ -403,9 +398,8 @@ public class SatResource extends
|
|||
}
|
||||
}
|
||||
|
||||
dataMap.put(RAW_VALUE, dataValue);
|
||||
dataMap.put(SATELLITE_DATA_INTERROGATE_ID,
|
||||
Measure.valueOf(dataValue, parameters.getDataUnit()));
|
||||
Measure.valueOf(dataValue, dataUnit));
|
||||
|
||||
return dataMap;
|
||||
}
|
||||
|
@ -413,8 +407,14 @@ public class SatResource extends
|
|||
@Override
|
||||
public String inspect(ReferencedCoordinate coord) throws VizException {
|
||||
Map<String, Object> dataMap = interrogate(coord);
|
||||
Double value = (Double) dataMap.get(RAW_VALUE);
|
||||
if (value == null || value.isNaN()) {
|
||||
|
||||
Measure<?, ?> value = (Measure<?, ?>) dataMap
|
||||
.get(SATELLITE_DATA_INTERROGATE_ID);
|
||||
double measuredValue = Double.NaN;
|
||||
if (value != null && value.getValue() instanceof Double) {
|
||||
measuredValue = (Double) value.getValue();
|
||||
}
|
||||
if (Double.isNaN(measuredValue)) {
|
||||
return "NO DATA";
|
||||
}
|
||||
ColorMapParameters cmp = getCapability(ColorMapCapability.class)
|
||||
|
@ -425,18 +425,21 @@ public class SatResource extends
|
|||
if (dataMapping != null) {
|
||||
// if the pixel value matches the data mapping entry use that
|
||||
// label instead
|
||||
String label = dataMapping.getLabelValueForDataValue(value);
|
||||
String label = dataMapping.getLabelValueForDataValue(measuredValue);
|
||||
if (label != null) {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
UnitConverter dataToDisplay = cmp.getDataToDisplayConverter();
|
||||
if (dataToDisplay != null) {
|
||||
value = dataToDisplay.convert(value);
|
||||
Unit<?> unit = cmp.getDisplayUnit();
|
||||
Unit<?> measuredUnit = value.getUnit();
|
||||
if (unit != null && measuredUnit != null) {
|
||||
UnitConverter dataToDisplay = measuredUnit.getConverterTo(unit);
|
||||
if (dataToDisplay != null) {
|
||||
measuredValue = dataToDisplay.convert(measuredValue);
|
||||
}
|
||||
}
|
||||
|
||||
Unit<?> unit = cmp.getDisplayUnit();
|
||||
// Had to use 'bit' as the display unit because
|
||||
// counts was not an acceptable unit.
|
||||
String unitString = unit == null ? ""
|
||||
|
@ -447,13 +450,13 @@ public class SatResource extends
|
|||
f1 = sampleRange.getMaxValue();
|
||||
f2 = sampleRange.getMinValue();
|
||||
}
|
||||
if (value > f1 && value > f2) {
|
||||
if (measuredValue > f1 && measuredValue > f2) {
|
||||
return String.format(">%.1f%s", Math.max(f1, f2), unitString);
|
||||
}
|
||||
if (value < f1 && value < f2) {
|
||||
if (measuredValue < f1 && measuredValue < f2) {
|
||||
return String.format("<%.1f%s", Math.min(f1, f2), unitString);
|
||||
}
|
||||
return String.format("%.1f%s", value, unitString);
|
||||
return String.format("%.1f%s", measuredValue, unitString);
|
||||
}
|
||||
|
||||
private String getLegend(PluginDataObject record) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
|
|||
import java.nio.ShortBuffer;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
|
@ -60,7 +61,9 @@ import com.raytheon.viz.satellite.SatelliteConstants;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 20, 2013 2122 mschenke Initial creation
|
||||
* Jun 20, 2013 2122 mschenke Initial creation
|
||||
* Nov 13, 2013 2492 mschenke Added extraction of scale/offset from
|
||||
* data record attributes for unit
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -92,8 +95,8 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
|
|||
*/
|
||||
@Override
|
||||
public ColorMapData getColorMapData() {
|
||||
// TODO: Read scale/offset out of attributes?
|
||||
Buffer data = null;
|
||||
Unit<?> dataUnit = Unit.ONE;
|
||||
boolean signed = false;
|
||||
Request req = Request.buildSlab(new int[] { this.datasetBounds.x,
|
||||
this.datasetBounds.y }, new int[] {
|
||||
|
@ -112,6 +115,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
|
|||
}
|
||||
Unit<?> recordUnit = getRecordUnit(this.record);
|
||||
signed = recordUnit instanceof GenericPixel;
|
||||
dataUnit = getDataUnit(recordUnit, record);
|
||||
}
|
||||
} catch (VizDataCubeException e) {
|
||||
statusHandler.handle(Priority.SIGNIFICANT,
|
||||
|
@ -134,7 +138,7 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
|
|||
}
|
||||
|
||||
return new ColorMapData(data, new int[] { datasetBounds.width,
|
||||
datasetBounds.height }, dataType);
|
||||
datasetBounds.height }, dataType, dataUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,7 +154,8 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
|
|||
physicalElement = request.getParameterAbbreviation();
|
||||
}
|
||||
|
||||
if (record.getUnits() != null && record.getUnits().isEmpty() == false && request == null) {
|
||||
if (record.getUnits() != null && record.getUnits().isEmpty() == false
|
||||
&& request == null) {
|
||||
try {
|
||||
recordUnit = UnitFormat.getUCUMInstance().parseProductUnit(
|
||||
record.getUnits(), new ParsePosition(0));
|
||||
|
@ -181,6 +186,37 @@ public class SatDataRetriever implements IColorMapDataRetrievalCallback {
|
|||
return recordUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the data units for the data record given the PDO's base unit
|
||||
*
|
||||
* @param recordUnit
|
||||
* @param dataRecord
|
||||
* @return
|
||||
*/
|
||||
private static Unit<?> getDataUnit(Unit<?> recordUnit,
|
||||
IDataRecord dataRecord) {
|
||||
Unit<?> units = recordUnit != null ? recordUnit : Unit.ONE;
|
||||
Map<String, Object> attrs = dataRecord.getDataAttributes();
|
||||
if (attrs != null) {
|
||||
Number offset = (Number) attrs.get(SatelliteRecord.SAT_ADD_OFFSET);
|
||||
Number scale = (Number) attrs.get(SatelliteRecord.SAT_SCALE_FACTOR);
|
||||
|
||||
if (offset != null) {
|
||||
double offsetVal = offset.doubleValue();
|
||||
if (offsetVal != 0.0) {
|
||||
units = units.plus(offsetVal);
|
||||
}
|
||||
}
|
||||
if (scale != null) {
|
||||
double scaleVal = scale.doubleValue();
|
||||
if (scaleVal != 0.0) {
|
||||
units = units.times(scaleVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return units;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -65,7 +65,7 @@ public class ColorMapSliderComp extends Composite {
|
|||
|
||||
private static final int SLIDER_MIN = 0;
|
||||
|
||||
private static final int SLIDER_MAX = 255;
|
||||
private static final int SLIDER_MAX = 250;
|
||||
|
||||
private static final int SLIDER_INC = 1;
|
||||
|
||||
|
@ -79,9 +79,9 @@ public class ColorMapSliderComp extends Composite {
|
|||
|
||||
private Text maxValueText;
|
||||
|
||||
private final float cmapAbsoluteMin;
|
||||
private float cmapAbsoluteMin;
|
||||
|
||||
private final float cmapAbsoluteMax;
|
||||
private float cmapAbsoluteMax;
|
||||
|
||||
private final float origCmapMin;
|
||||
|
||||
|
@ -93,8 +93,6 @@ public class ColorMapSliderComp extends Composite {
|
|||
|
||||
private final DecimalFormat format;
|
||||
|
||||
private final boolean dataInverted;
|
||||
|
||||
private UnitConverter displayToColorMap;
|
||||
|
||||
private UnitConverter colorMapToDisplay;
|
||||
|
@ -106,8 +104,10 @@ public class ColorMapSliderComp extends Composite {
|
|||
public ColorMapSliderComp(Composite parent, ColorMapParameters cmap) {
|
||||
super(parent, SWT.NONE);
|
||||
this.cmap = cmap;
|
||||
this.currentCmapMin = this.origCmapMin = cmap.getColorMapMin();
|
||||
this.currentCmapMax = this.origCmapMax = cmap.getColorMapMax();
|
||||
this.cmapAbsoluteMin = this.currentCmapMin = this.origCmapMin = cmap
|
||||
.getColorMapMin();
|
||||
this.cmapAbsoluteMax = this.currentCmapMax = this.origCmapMax = cmap
|
||||
.getColorMapMax();
|
||||
this.displayToColorMap = cmap.getDisplayToColorMapConverter();
|
||||
this.colorMapToDisplay = cmap.getColorMapToDisplayConverter();
|
||||
if (displayToColorMap == null) {
|
||||
|
@ -116,34 +116,9 @@ public class ColorMapSliderComp extends Composite {
|
|||
if (colorMapToDisplay == null) {
|
||||
colorMapToDisplay = Unit.ONE.getConverterTo(Unit.ONE);
|
||||
}
|
||||
float cmapAbsoluteMin, cmapAbsoluteMax;
|
||||
if (cmap.getDataMapping() != null) {
|
||||
cmapAbsoluteMin = cmap.getColorMapMin();
|
||||
cmapAbsoluteMax = cmap.getColorMapMax();
|
||||
} else {
|
||||
UnitConverter dataToColorMap = cmap.getDataToColorMapConverter();
|
||||
cmapAbsoluteMin = cmap.getDataMin();
|
||||
cmapAbsoluteMax = cmap.getDataMax();
|
||||
if (dataToColorMap != null) {
|
||||
cmapAbsoluteMin = (float) dataToColorMap.convert(cmap
|
||||
.getDataMin());
|
||||
cmapAbsoluteMax = (float) dataToColorMap.convert(cmap
|
||||
.getDataMax());
|
||||
}
|
||||
}
|
||||
|
||||
this.cmapAbsoluteMin = cmapAbsoluteMin;
|
||||
this.cmapAbsoluteMax = cmapAbsoluteMax;
|
||||
updateAbsolutes(cmapAbsoluteMin, cmapAbsoluteMax);
|
||||
|
||||
boolean dataInverted = false;
|
||||
if ((cmapAbsoluteMin > cmapAbsoluteMax && cmap.getDataMin() < cmap
|
||||
.getDataMax())
|
||||
|| (cmapAbsoluteMin < cmapAbsoluteMax && cmap.getDataMin() > cmap
|
||||
.getDataMax())) {
|
||||
dataInverted = true;
|
||||
}
|
||||
|
||||
this.dataInverted = dataInverted;
|
||||
this.format = getTextFormat();
|
||||
|
||||
initializeComponents();
|
||||
|
@ -205,6 +180,7 @@ public class ColorMapSliderComp extends Composite {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
minSlider.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
|
@ -217,8 +193,7 @@ public class ColorMapSliderComp extends Composite {
|
|||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.character == SWT.CR) {
|
||||
setColorMapMax(textToColorMapValue(maxValueText.getText()
|
||||
.trim()));
|
||||
updateMinMaxFromText(maxValueText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -227,8 +202,7 @@ public class ColorMapSliderComp extends Composite {
|
|||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.character == SWT.CR) {
|
||||
setColorMapMin(textToColorMapValue(minValueText.getText()
|
||||
.trim()));
|
||||
updateMinMaxFromText(minValueText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -237,6 +211,48 @@ public class ColorMapSliderComp extends Composite {
|
|||
setColorMapMax(currentCmapMax);
|
||||
}
|
||||
|
||||
private void updateMinMaxFromText(Text text) {
|
||||
float newCmapValue = textToColorMapValue(text);
|
||||
if (Float.isNaN(newCmapValue)) {
|
||||
// Change nothing
|
||||
if (text == minValueText) {
|
||||
newCmapValue = currentCmapMin;
|
||||
} else {
|
||||
newCmapValue = currentCmapMax;
|
||||
}
|
||||
} else {
|
||||
// Update colormap range
|
||||
if (text == minValueText) {
|
||||
currentCmapMin = newCmapValue;
|
||||
} else {
|
||||
currentCmapMax = newCmapValue;
|
||||
}
|
||||
}
|
||||
|
||||
updateAbsolutes(currentCmapMin, currentCmapMax);
|
||||
|
||||
setColorMapMin(currentCmapMin);
|
||||
setColorMapMax(currentCmapMax);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void updateAbsolutes(float cmapAbsoluteMin, float cmapAbsoluteMax) {
|
||||
double displayAbsMax = colorMapToDisplay.convert(cmapAbsoluteMax);
|
||||
double displayAbsMin = colorMapToDisplay.convert(cmapAbsoluteMin);
|
||||
if (displayAbsMax < displayAbsMin) {
|
||||
float tmp = cmapAbsoluteMax;
|
||||
cmapAbsoluteMax = cmapAbsoluteMin;
|
||||
cmapAbsoluteMin = tmp;
|
||||
}
|
||||
|
||||
// Add a 1/16 buffer on either side for fine tuning
|
||||
float buffer = (cmapAbsoluteMax - cmapAbsoluteMin) * .0625f;
|
||||
this.cmapAbsoluteMin = cmapAbsoluteMin - buffer;
|
||||
this.cmapAbsoluteMax = cmapAbsoluteMax + buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a slider selection index to a colormap value
|
||||
*
|
||||
|
@ -246,9 +262,6 @@ public class ColorMapSliderComp extends Composite {
|
|||
private float selectionToColorMapValue(int selection) {
|
||||
double indexValue = Colormapper.getLinearIndex(selection, SLIDER_MIN,
|
||||
SLIDER_MAX);
|
||||
if (dataInverted) {
|
||||
indexValue = 1 - indexValue;
|
||||
}
|
||||
double colorMapValue = cmapAbsoluteMin
|
||||
+ (cmapAbsoluteMax - cmapAbsoluteMin) * indexValue;
|
||||
return (float) colorMapValue;
|
||||
|
@ -263,9 +276,6 @@ public class ColorMapSliderComp extends Composite {
|
|||
private int colorMapValueToSelection(float colorMapValue) {
|
||||
double indexValue = Colormapper.getLinearIndex(colorMapValue,
|
||||
cmapAbsoluteMin, cmapAbsoluteMax);
|
||||
if (dataInverted) {
|
||||
indexValue = 1 - indexValue;
|
||||
}
|
||||
return (int) (SLIDER_MIN + (SLIDER_MAX - SLIDER_MIN) * indexValue);
|
||||
}
|
||||
|
||||
|
@ -275,7 +285,8 @@ public class ColorMapSliderComp extends Composite {
|
|||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private float textToColorMapValue(String text) {
|
||||
private float textToColorMapValue(Text textControl) {
|
||||
String text = textControl.getText().trim();
|
||||
if (cmap.getDataMapping() != null && text.isEmpty() == false) {
|
||||
// First check for data mapping entries
|
||||
for (DataMappingEntry entry : cmap.getDataMapping().getEntries()) {
|
||||
|
@ -285,13 +296,28 @@ public class ColorMapSliderComp extends Composite {
|
|||
}
|
||||
}
|
||||
if (NaN_STRING.equals(text)) {
|
||||
// If special NaN String, try to find first NaN value
|
||||
// If special NaN String, try to find closest NaN value
|
||||
float currentColorMapValue = textControl == maxValueText ? currentCmapMax
|
||||
: currentCmapMin;
|
||||
int currentSliderValue = colorMapValueToSelection(currentColorMapValue);
|
||||
int minDist = Integer.MAX_VALUE;
|
||||
float bestNanValue = currentColorMapValue;
|
||||
for (int i = SLIDER_MIN; i < SLIDER_MAX; i += SLIDER_INC) {
|
||||
float colorMapValue = selectionToColorMapValue(i);
|
||||
if (Double.isNaN(colorMapToDisplay.convert(colorMapValue))) {
|
||||
return colorMapValue;
|
||||
int dist = Math.abs(i - currentSliderValue);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
bestNanValue = colorMapValue;
|
||||
} else if (i > currentSliderValue) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// For now, assume NaN will live on low end of slider
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bestNanValue;
|
||||
} else {
|
||||
// Attempt to parse and convert
|
||||
try {
|
||||
|
|
|
@ -26,13 +26,14 @@ import javax.measure.converter.UnitConverter;
|
|||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
/**
|
||||
* Converts a temperature value in Kelvin to a pixel value from 0 to 255
|
||||
* Converts a temperature value in Kelvin to a pixel value.
|
||||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 29, 2007 njensen Initial creation
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Aug 29, 2007 njensen Initial creation
|
||||
* Nov 20, 2013 2492 bsteffen Make conversion unbounded.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -40,45 +41,39 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
|
|||
*/
|
||||
public class IRTempToPixelConverter extends UnitConverter {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public double convert(double aTemperature) throws ConversionException {
|
||||
double result = 0.0;
|
||||
@Override
|
||||
public double convert(double aTemperature) throws ConversionException {
|
||||
double result = 0.0;
|
||||
|
||||
if (aTemperature < 238.15) {
|
||||
result = 418.15 - aTemperature;
|
||||
} else {
|
||||
result = 656.3 - (2.0 * aTemperature);
|
||||
}
|
||||
if (aTemperature < 238.15) {
|
||||
result = 418.15 - aTemperature;
|
||||
} else {
|
||||
result = 656.3 - (2.0 * aTemperature);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
result = 0.0;
|
||||
} else if (result > 255) {
|
||||
result = 255.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object aConverter) {
|
||||
return (aConverter instanceof IRTempToPixelConverter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object aConverter) {
|
||||
return (aConverter instanceof IRTempToPixelConverter);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
@Override
|
||||
public UnitConverter inverse() {
|
||||
return new IRPixelToTempConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitConverter inverse() {
|
||||
return new IRPixelToTempConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLinear() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isLinear() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,118 +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.uf.common.dataplugin.satellite.units.water;
|
||||
|
||||
import javax.measure.converter.ConversionException;
|
||||
import javax.measure.converter.UnitConverter;
|
||||
import javax.measure.unit.SI;
|
||||
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2010 jsanchez Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author jsanchez
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class BlendedTPWLengthToPixelConverter extends UnitConverter {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static UnitConverter meterToMillimeter = SI.METRE.getConverterTo(SI
|
||||
.MILLI(SI.METRE));
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#convert( double)
|
||||
*/
|
||||
@Override
|
||||
public double convert(double aLength) throws ConversionException {
|
||||
|
||||
double result = 0.0;
|
||||
|
||||
aLength = meterToMillimeter.convert(aLength);
|
||||
|
||||
if (aLength < 1) {
|
||||
result = 176;
|
||||
} else {
|
||||
result = aLength + 176;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
result = 0;
|
||||
} else if (result > 255) {
|
||||
result = 255;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object aConverter) {
|
||||
return (aConverter instanceof BlendedTPWLengthToPixelConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#inverse()
|
||||
*/
|
||||
@Override
|
||||
public UnitConverter inverse() {
|
||||
return new BlendedTPWPixelToLengthConverter();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#isLinear()
|
||||
*/
|
||||
@Override
|
||||
public boolean isLinear() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.dataplugin.satellite.units.water;
|
||||
|
||||
import javax.measure.converter.AddConverter;
|
||||
import javax.measure.converter.UnitConverter;
|
||||
import javax.measure.quantity.Length;
|
||||
import javax.measure.unit.DerivedUnit;
|
||||
|
@ -28,15 +29,17 @@ import javax.measure.unit.Unit;
|
|||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* Represents a pixel value on a satellite blended total precipitable water(TPW)
|
||||
* image.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2010 jsanchez Initial creation
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Mar 18, 2010 jsanchez Initial creation
|
||||
* Nov 20, 2013 2492 bsteffen Make conversion unbounded.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -66,6 +69,7 @@ public class BlendedTPWPixel extends DerivedUnit<Length> {
|
|||
|
||||
@Override
|
||||
public UnitConverter toStandardUnit() {
|
||||
return new BlendedTPWPixelToLengthConverter();
|
||||
return SI.MILLI(SI.METRE).getConverterTo(SI.METRE)
|
||||
.concatenate(new AddConverter(-176));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,111 +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.uf.common.dataplugin.satellite.units.water;
|
||||
|
||||
import javax.measure.converter.ConversionException;
|
||||
import javax.measure.converter.UnitConverter;
|
||||
import javax.measure.unit.SI;
|
||||
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 18, 2010 jsanchez Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author jsanchez
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class BlendedTPWPixelToLengthConverter extends UnitConverter {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static UnitConverter millimeterToMeter = (SI.MILLI(SI.METRE))
|
||||
.getConverterTo(SI.METRE);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#convert(double)
|
||||
*/
|
||||
@Override
|
||||
public double convert(double aPixel) throws ConversionException {
|
||||
double result = 0.0;
|
||||
|
||||
if (aPixel <= 176) {
|
||||
result = 0.0;
|
||||
} else {
|
||||
result = aPixel - 176;
|
||||
}
|
||||
|
||||
result = millimeterToMeter.convert(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object aConverter) {
|
||||
return (aConverter instanceof BlendedTPWPixelToLengthConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#inverse()
|
||||
*/
|
||||
@Override
|
||||
public UnitConverter inverse() {
|
||||
return new BlendedTPWLengthToPixelConverter();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.measure.converter.UnitConverter#isLinear()
|
||||
*/
|
||||
@Override
|
||||
public boolean isLinear() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -43,8 +43,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -75,8 +75,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -199,8 +199,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -211,8 +211,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -223,8 +223,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/WV/Gray Scale Water Vapor</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -235,10 +235,10 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
|
||||
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
|
||||
</imageStyle>
|
||||
</styleRule>
|
||||
<styleRule>
|
||||
|
@ -248,8 +248,8 @@
|
|||
<imageStyle>
|
||||
<displayUnits>C</displayUnits>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap>
|
||||
<colorbarLabeling>
|
||||
|
@ -264,8 +264,8 @@
|
|||
<imageStyle>
|
||||
<displayUnits>C</displayUnits>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/IR/CIRA (IR Default)</defaultColormap>
|
||||
<colorbarLabeling>
|
||||
|
@ -436,7 +436,7 @@
|
|||
<imageStyle>
|
||||
<displayUnits>mm</displayUnits>
|
||||
<range scale="LINEAR">
|
||||
<minValue>0</minValue>
|
||||
<minValue>-176</minValue>
|
||||
<maxValue>76</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/Precip Water/Blended Total Precip Water</defaultColormap>
|
||||
|
@ -492,8 +492,8 @@
|
|||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<range scale="LINEAR">
|
||||
<minValue>1</minValue>
|
||||
<maxValue>254</maxValue>
|
||||
<minValue>0</minValue>
|
||||
<maxValue>255</maxValue>
|
||||
</range>
|
||||
<defaultColormap>Sat/VIS/ZA (Vis Default)</defaultColormap>
|
||||
</imageStyle>
|
||||
|
@ -530,5 +530,4 @@
|
|||
</colorbarLabeling>
|
||||
</imageStyle>
|
||||
</styleRule>
|
||||
|
||||
</styleRuleset>
|
|
@ -49,10 +49,11 @@ import org.opengis.referencing.operation.MathTransform;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 27, 2013 mschenke Initial creation
|
||||
* Oct 02, 2013 2333 mschenke Converted from libproj to CGMS algorithm
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Jun 27, 2013 mschenke Initial creation
|
||||
* Oct 02, 2013 2333 mschenke Converted from libproj to CGMS algorithm
|
||||
* Nov 18, 2013 2528 bsteffen Add hashCode/equals.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -212,6 +213,34 @@ public class Geostationary extends MapProjection {
|
|||
return ptDst;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(orbitalHeight);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
result = prime * result + (swapAxis ? 1231 : 1237);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!super.equals(obj))
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Geostationary other = (Geostationary) obj;
|
||||
if (Double.doubleToLongBits(orbitalHeight) != Double
|
||||
.doubleToLongBits(other.orbitalHeight))
|
||||
return false;
|
||||
if (swapAxis != other.swapAxis)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Provider extends AbstractProvider {
|
||||
|
||||
private static final long serialVersionUID = 3868187206568280453L;
|
||||
|
|
|
@ -0,0 +1,416 @@
|
|||
/**
|
||||
* 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.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.geometry.jts.JTS;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.geometry.MismatchedDimensionException;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence;
|
||||
|
||||
/**
|
||||
* Solves the problem of intersecting two envelopes in different coordinate
|
||||
* systems by reprojecting a grid of points and building polygons out of
|
||||
* adjacent grid cells. This can be significantly slower than other algorithms
|
||||
* but will always produce the best result possible for a given width and
|
||||
* height. Increasing the width/height will slow the algorithm but give better
|
||||
* results.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Nov 14, 2013 2528 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
class BruteForceEnvelopeIntersection {
|
||||
|
||||
private final ReferencedEnvelope sourceEnvelope;
|
||||
|
||||
private final ReferencedEnvelope targetEnvelope;
|
||||
|
||||
private final WorldWrapChecker wwc;
|
||||
|
||||
private final int width;
|
||||
|
||||
private final int height;
|
||||
|
||||
private final MathTransform latLonToTargetCRS;
|
||||
|
||||
private final CoordinateSequence latLonCoords;
|
||||
|
||||
private final CoordinateSequence targetCoords;
|
||||
|
||||
/**
|
||||
* Construct a new intersection. This will calculate all fields including
|
||||
* reprojecting all points in the grid.
|
||||
*/
|
||||
private BruteForceEnvelopeIntersection(Envelope sourceEnvelope,
|
||||
Envelope targetEnvelope, int width, int height)
|
||||
throws FactoryException, TransformException {
|
||||
if (sourceEnvelope instanceof ReferencedEnvelope) {
|
||||
this.sourceEnvelope = (ReferencedEnvelope) sourceEnvelope;
|
||||
} else {
|
||||
this.sourceEnvelope = new ReferencedEnvelope(sourceEnvelope);
|
||||
}
|
||||
if (targetEnvelope instanceof ReferencedEnvelope) {
|
||||
this.targetEnvelope = (ReferencedEnvelope) targetEnvelope;
|
||||
} else {
|
||||
this.targetEnvelope = new ReferencedEnvelope(targetEnvelope);
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
wwc = new WorldWrapChecker(this.targetEnvelope);
|
||||
|
||||
double[] latLonCoords = buildLatLonCoords();
|
||||
this.latLonCoords = new PackedCoordinateSequence.Double(latLonCoords, 2);
|
||||
|
||||
latLonToTargetCRS = MapUtil
|
||||
.getTransformFromLatLon(targetEnvelope
|
||||
.getCoordinateReferenceSystem());
|
||||
double[] targetCoords = new double[latLonCoords.length];
|
||||
latLonToTargetCRS.transform(latLonCoords, 0, targetCoords, 0, width
|
||||
* height);
|
||||
this.targetCoords = new PackedCoordinateSequence.Double(targetCoords, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a grid of coordinates and reproject to lat/lon CRS.
|
||||
*/
|
||||
private double[] buildLatLonCoords() throws FactoryException,
|
||||
TransformException {
|
||||
MathTransform sourceCRSToLatLon = MapUtil
|
||||
.getTransformToLatLon(sourceEnvelope
|
||||
.getCoordinateReferenceSystem());
|
||||
double worldMinX = this.sourceEnvelope.getMinX();
|
||||
double worldMinY = this.sourceEnvelope.getMinY();
|
||||
double dXWorld = this.sourceEnvelope.getWidth() / (width - 1);
|
||||
double dYWorld = this.sourceEnvelope.getHeight() / (height - 1);
|
||||
|
||||
int index = 0;
|
||||
double[] coordinates = new double[width * height * 2];
|
||||
|
||||
for (int j = 0; j < height; ++j) {
|
||||
double y = worldMinY + j * dYWorld;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
coordinates[index++] = worldMinX + i * dXWorld;
|
||||
coordinates[index++] = y;
|
||||
}
|
||||
}
|
||||
sourceCRSToLatLon.transform(coordinates, 0, coordinates, 0, width
|
||||
* height);
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual intersection operation by merging all {@link Cell}s
|
||||
* into {@link SimplePolygon} and finally converting those into Polygons.
|
||||
*/
|
||||
public Geometry reproject() throws MismatchedDimensionException,
|
||||
TransformException {
|
||||
/*
|
||||
* Loop over each cell and split into two groups. First group is the
|
||||
* "simple" cases that do not world wrap and can all be merged into one
|
||||
* or more polygons. Second group contains the cells that need to be
|
||||
* world wrap corrected.
|
||||
*/
|
||||
List<SimplePolygon> simpleCases = new ArrayList<SimplePolygon>();
|
||||
List<Cell> worldWrappCells = new ArrayList<Cell>();
|
||||
for (int j = 1; j < height; ++j) {
|
||||
for (int i = 1; i < width; ++i) {
|
||||
Cell cell = new Cell(i, j);
|
||||
if (!cell.isValid()) {
|
||||
// skip it
|
||||
} else if (cell.worldWrapCheck(wwc)) {
|
||||
worldWrappCells.add(cell);
|
||||
} else {
|
||||
for (SimplePolygon poly : simpleCases) {
|
||||
if (poly.merge(cell)) {
|
||||
cell = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell != null) {
|
||||
simpleCases.add(new SimplePolygon(cell));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Convert all simple case polygons into JTS polygons */
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
List<Geometry> geoms = new ArrayList<Geometry>(simpleCases.size() + worldWrappCells.size() *2);
|
||||
for (SimplePolygon poly : simpleCases) {
|
||||
geoms.add(poly.asGeometry(gf));
|
||||
}
|
||||
if(!worldWrappCells.isEmpty()){
|
||||
/*
|
||||
* World wrap correct the cells that need it and transform the
|
||||
* corrected geometries.
|
||||
*/
|
||||
WorldWrapCorrector corrector = new WorldWrapCorrector(
|
||||
targetEnvelope);
|
||||
for (Cell cell : worldWrappCells) {
|
||||
Geometry geom = cell.asLatLonGeometry(gf);
|
||||
geom = corrector.correct(geom);
|
||||
geom = JTS.transform(geom, latLonToTargetCRS);
|
||||
if (geom.isValid() && !geom.isEmpty()) {
|
||||
geoms.add(geom);
|
||||
}
|
||||
}
|
||||
}
|
||||
return gf.createGeometryCollection(geoms.toArray(new Geometry[0]))
|
||||
.buffer(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A cell represents four connected grid points that form a continous piece
|
||||
* of an intersecting polygons. Most of the time a cell represents a
|
||||
* quadrilateral but for cases where one of the corners is invalid in the
|
||||
* target CRS a cell may represent a triangle. If any more points are
|
||||
* invalid then the cell is invalid.
|
||||
*/
|
||||
private final class Cell {
|
||||
|
||||
private final int[] indices;
|
||||
|
||||
public Cell(int x, int y) {
|
||||
int[] indices = new int[] { y * width + x - 1,
|
||||
(y - 1) * width + x - 1,
|
||||
(y - 1) * width + x, y * width + x};
|
||||
int nanCount = 0;
|
||||
for (int index : indices) {
|
||||
if (isNaN(index)) {
|
||||
nanCount += 1;
|
||||
}
|
||||
}
|
||||
if (nanCount == 0) {
|
||||
this.indices = indices;
|
||||
} else if (nanCount == 1) {
|
||||
this.indices = new int[3];
|
||||
int i = 0;
|
||||
for (int index : indices) {
|
||||
if (!isNaN(index)) {
|
||||
this.indices[i++] = index;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.indices = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNaN(int index){
|
||||
return Double.isNaN(targetCoords.getOrdinate(index, 0))
|
||||
|| Double.isNaN(targetCoords.getOrdinate(index, 1));
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return indices != null;
|
||||
}
|
||||
|
||||
public boolean worldWrapCheck(WorldWrapChecker wwc) {
|
||||
double prevLon = latLonCoords.getOrdinate(
|
||||
indices[indices.length - 1], 0);
|
||||
for (int index : indices) {
|
||||
double lon = latLonCoords.getOrdinate(index, 0);
|
||||
if (wwc.check(prevLon, lon)) {
|
||||
return true;
|
||||
}
|
||||
prevLon = lon;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public List<Coordinate> getTargetCoords() {
|
||||
List<Coordinate> result = new ArrayList<Coordinate>(4);
|
||||
for (int index : indices) {
|
||||
result.add(targetCoords.getCoordinate(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Polygon asLatLonGeometry(GeometryFactory gf) {
|
||||
Coordinate[] coordinates = new Coordinate[indices.length + 1];
|
||||
for (int i = 0; i < indices.length; i += 1) {
|
||||
coordinates[i] = latLonCoords.getCoordinate(indices[i]);
|
||||
}
|
||||
coordinates[coordinates.length - 1] = coordinates[0];
|
||||
return gf.createPolygon(gf.createLinearRing(coordinates), null);
|
||||
}
|
||||
|
||||
public Coordinate getTargetCoord(int index) {
|
||||
return targetCoords.getCoordinate(indices[index % indices.length]);
|
||||
}
|
||||
|
||||
public int indexOfTarget(Coordinate c) {
|
||||
for (int i = 0; i < targetCoords.size(); i += 1) {
|
||||
if (targetCoords.getOrdinate(indices[i], 0) == c.x
|
||||
&& targetCoords.getOrdinate(indices[i], 1) == c.y) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return indices.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to represent a Polygon with no holes. Additionally it
|
||||
* provides fast method for merging a cell because it can safely assume that
|
||||
* any points it shares with the cell are identical.
|
||||
*/
|
||||
private static final class SimplePolygon {
|
||||
|
||||
private List<Coordinate> coords;
|
||||
|
||||
public SimplePolygon(Cell cell) {
|
||||
this.coords = cell.getTargetCoords();
|
||||
}
|
||||
|
||||
public boolean merge(Cell cell) {
|
||||
List<Coordinate> toCheck = cell.getTargetCoords();
|
||||
/*
|
||||
* Walk coords in order, if any identical coords are found we can
|
||||
* ceck nearby points to eliminate the duplicates
|
||||
*/
|
||||
for (int i = 0; i < coords.size() - 1; i += 1) {
|
||||
if (toCheck.remove(coords.get(i))) {
|
||||
int lastFoundIndex = -1;
|
||||
if (i == 0 && toCheck.remove(coords.get(coords.size() - 1))) {
|
||||
/*
|
||||
* For the 0 index the end of coords must be checked,
|
||||
* all other indices do not need to check previous
|
||||
* coords.
|
||||
*/
|
||||
while (toCheck.remove(coords.get(coords.size() - 2))) {
|
||||
coords.remove(coords.size() - 1);
|
||||
}
|
||||
lastFoundIndex = 0;
|
||||
} else if (i + 1 < coords.size()
|
||||
&& toCheck.remove(coords.get(i + 1))) {
|
||||
/* This check ensures 2 points match. */
|
||||
lastFoundIndex = i + 1;
|
||||
}
|
||||
if (lastFoundIndex != -1) {
|
||||
while (lastFoundIndex + 1 < coords.size()
|
||||
&& toCheck.remove(coords
|
||||
.get(lastFoundIndex + 1))) {
|
||||
/*
|
||||
* If more than two points match, remove the common
|
||||
* interior points.
|
||||
*/
|
||||
coords.remove(lastFoundIndex);
|
||||
}
|
||||
if (!toCheck.isEmpty()) {
|
||||
/*
|
||||
* Add any exterior remaining points from the cell
|
||||
* into this.
|
||||
*/
|
||||
int cellLastFoundIndex = cell.indexOfTarget(coords
|
||||
.get(lastFoundIndex));
|
||||
int prevIndex = cellLastFoundIndex + cell.size() - 1;
|
||||
int nextIndex = cellLastFoundIndex + 1;
|
||||
if (toCheck
|
||||
.contains(cell.getTargetCoord(nextIndex))) {
|
||||
coords.add(lastFoundIndex,
|
||||
cell.getTargetCoord(nextIndex));
|
||||
for (int j = nextIndex + 1; j < prevIndex; j += 1) {
|
||||
Coordinate c = cell.getTargetCoord(j);
|
||||
if (toCheck.contains(c)) {
|
||||
coords.add(lastFoundIndex, c);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (toCheck.contains(cell
|
||||
.getTargetCoord(prevIndex))) {
|
||||
coords.add(lastFoundIndex,
|
||||
cell.getTargetCoord(prevIndex));
|
||||
for (int j = prevIndex - 1; j > nextIndex; j -= 1) {
|
||||
Coordinate c = cell.getTargetCoord(j);
|
||||
if (toCheck.contains(c)) {
|
||||
coords.add(lastFoundIndex, c);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Polygon asGeometry(GeometryFactory gf) {
|
||||
Coordinate[] coordinates = new Coordinate[this.coords.size() + 1];
|
||||
this.coords.toArray(coordinates);
|
||||
coordinates[coordinates.length - 1] = coordinates[0];
|
||||
return gf.createPolygon(gf.createLinearRing(coordinates), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes an intersection {@link Geometry} between sourceEnvelope and
|
||||
* targetEnvelope in targetEnvelope's CRS space. The resulting
|
||||
* {@link Geometry} may contain multiple Geometries within it. But all
|
||||
* geometries will be {@link Polygon}s
|
||||
*
|
||||
* @param sourceEnvelope
|
||||
* @param targetEnvelope
|
||||
* @param maxHorDivisions
|
||||
* @param maxVertDivisions
|
||||
* @return
|
||||
* @throws FactoryException
|
||||
* @throws TransformException
|
||||
*/
|
||||
public static Geometry createEnvelopeIntersection(Envelope sourceEnvelope,
|
||||
Envelope targetEnvelope, int maxHorDivisions, int maxVertDivisions)
|
||||
throws FactoryException, TransformException {
|
||||
return new BruteForceEnvelopeIntersection(sourceEnvelope, targetEnvelope,
|
||||
maxHorDivisions, maxVertDivisions).reproject();
|
||||
}
|
||||
}
|
|
@ -55,8 +55,10 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Sep 13, 2013 2309 bsteffen Corrected Lines that are extrapolated to
|
||||
* intersect the border will use projection
|
||||
* factor from all 4 corners instead of 3.
|
||||
* Oct 8, 2013 2104 mschenke Added case for where actual border is
|
||||
* Oct 08, 2013 2104 mschenke Added case for where actual border is
|
||||
* inside out by checking interior point
|
||||
* Nov 18, 2013 2528 bsteffen Fall back to brute force when corner
|
||||
* points are not found.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -86,11 +88,30 @@ public class EnvelopeIntersection {
|
|||
int maxVertDivisions) throws TransformException, FactoryException {
|
||||
ReferencedEnvelope sourceREnvelope = reference(sourceEnvelope);
|
||||
ReferencedEnvelope targetREnvelope = reference(targetEnvelope);
|
||||
Geometry border = null;
|
||||
WorldWrapCorrector corrector = new WorldWrapCorrector(targetREnvelope);
|
||||
MathTransform sourceCRSToTargetCRS = CRS.findMathTransform(
|
||||
sourceREnvelope.getCoordinateReferenceSystem(),
|
||||
targetREnvelope.getCoordinateReferenceSystem());
|
||||
if (sourceCRSToTargetCRS.isIdentity()) {
|
||||
com.vividsolutions.jts.geom.Envelope intersection = sourceREnvelope
|
||||
.intersection(targetREnvelope);
|
||||
if (intersection == null) {
|
||||
return gf.createGeometryCollection(new Geometry[0]);
|
||||
} else {
|
||||
Coordinate[] border = new Coordinate[5];
|
||||
border[0] = new Coordinate(intersection.getMinX(),
|
||||
intersection.getMinY());
|
||||
border[1] = new Coordinate(intersection.getMinX(),
|
||||
intersection.getMaxY());
|
||||
border[2] = new Coordinate(intersection.getMaxX(),
|
||||
intersection.getMaxY());
|
||||
border[3] = new Coordinate(intersection.getMaxX(),
|
||||
intersection.getMinY());
|
||||
border[4] = border[0];
|
||||
return gf.createPolygon(gf.createLinearRing(border), null);
|
||||
}
|
||||
}
|
||||
Geometry border = null;
|
||||
WorldWrapCorrector corrector = new WorldWrapCorrector(targetREnvelope);
|
||||
MathTransform targetCRSToSourceCRS = sourceCRSToTargetCRS.inverse();
|
||||
MathTransform targetCRSToLatLon = MapUtil
|
||||
.getTransformToLatLon(targetREnvelope
|
||||
|
@ -136,6 +157,19 @@ public class EnvelopeIntersection {
|
|||
new double[] { sourceREnvelope.getMinimum(0), midY }, null,
|
||||
sourceCRSToTargetCRS, true);
|
||||
|
||||
if (UL == null || UR == null || LR == null || LL == null) {
|
||||
/*
|
||||
* If entire edges of the tile are invalid in target space then the
|
||||
* algorithms below are not that good. For most cases they produce
|
||||
* overly large polygons but there are cases where they completely
|
||||
* miss intersections. For these cases the BruteForce method is
|
||||
* worth the extra time to get a really accurate envelope.
|
||||
*/
|
||||
return BruteForceEnvelopeIntersection.createEnvelopeIntersection(
|
||||
sourceEnvelope, targetEnvelope, maxHorDivisions,
|
||||
maxVertDivisions);
|
||||
}
|
||||
|
||||
List<Coordinate> borderPoints = new ArrayList<Coordinate>(
|
||||
maxVertDivisions * 2 + maxHorDivisions * 2);
|
||||
double[] out = new double[2];
|
||||
|
@ -544,7 +578,9 @@ public class EnvelopeIntersection {
|
|||
try {
|
||||
double[] tmp = new double[maxPoint.length];
|
||||
mt.transform(maxPoint, 0, tmp, 0, 1);
|
||||
return maxPoint;
|
||||
if (!Double.isNaN(tmp[0]) && !Double.isNaN(tmp[1])) {
|
||||
return maxPoint;
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
@ -553,13 +589,15 @@ public class EnvelopeIntersection {
|
|||
try {
|
||||
double[] tmp = new double[point.length];
|
||||
mt.transform(point, 0, tmp, 0, 1);
|
||||
// point is valid, keep looking
|
||||
double deltaX = (maxPoint[0] - point[0]) / 2.0;
|
||||
double deltaY = (maxPoint[1] - point[1]) / 2.0;
|
||||
double[] newPoint = new double[] { point[0] + deltaX,
|
||||
point[1] + deltaY };
|
||||
return findNearestValidPoint(maxPoint, newPoint, point, mt,
|
||||
checkMax);
|
||||
if (!Double.isNaN(tmp[0]) && !Double.isNaN(tmp[1])) {
|
||||
// point is valid, keep looking
|
||||
double deltaX = (maxPoint[0] - point[0]) / 2.0;
|
||||
double deltaY = (maxPoint[1] - point[1]) / 2.0;
|
||||
double[] newPoint = new double[] { point[0] + deltaX,
|
||||
point[1] + deltaY };
|
||||
return findNearestValidPoint(maxPoint, newPoint, point, mt,
|
||||
checkMax);
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import javax.measure.unit.Unit;
|
|||
import org.apache.commons.lang.ArrayUtils;
|
||||
|
||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences;
|
||||
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences.DataMappingEntry;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -42,7 +44,6 @@ import com.raytheon.uf.common.style.level.RangeLevel;
|
|||
import com.raytheon.uf.common.style.level.SingleLevel;
|
||||
import com.raytheon.uf.common.util.GridUtil;
|
||||
|
||||
|
||||
/**
|
||||
* ColorMapParameterFactory
|
||||
*
|
||||
|
@ -53,10 +54,11 @@ import com.raytheon.uf.common.util.GridUtil;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 25, 2007 chammack Initial Creation.
|
||||
* Mar 26, 2009 2086 jsanchez Added a entityList to the match criteria.
|
||||
* Mar 26, 2009 2086 jsanchez Added a entityList to the match criteria.
|
||||
* Feb 15, 2013 1638 mschenke Moved GRID_FILL_VALUE from edex.common Util into GridUtil
|
||||
* Jun 24, 2013 2122 mschenke Added method for constructing {@link ColorMapParameters} from {@link StyleRule}
|
||||
* Sep 24, 2013 2404 bclement moved to common.style from viz.core, added build method that takes ParamLevelMatchCriteria, removed unused methods
|
||||
* Nov 13, 2013 2492 mschenke Create build that does not take data for adaptive building
|
||||
* </pre>
|
||||
*
|
||||
* @author chammack
|
||||
|
@ -129,7 +131,17 @@ public class ColorMapParameterFactory {
|
|||
}
|
||||
|
||||
// If a record to convert units exists, use it
|
||||
params.setDataUnit(parameterUnits);
|
||||
Unit<?> colorMapUnit = null;
|
||||
try {
|
||||
colorMapUnit = preferences.getColorMapUnitsObject();
|
||||
} catch (StyleException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
if (colorMapUnit == null) {
|
||||
params.setColorMapUnit(parameterUnits);
|
||||
} else {
|
||||
params.setColorMapUnit(colorMapUnit);
|
||||
}
|
||||
params.setDisplayUnit(preferences.getDisplayUnits());
|
||||
params.setDataMapping(preferences.getDataMapping());
|
||||
|
||||
|
@ -237,9 +249,10 @@ public class ColorMapParameterFactory {
|
|||
.convert(colormapMax) : colormapMax;
|
||||
|
||||
if (preferences.getColorbarLabeling() != null) {
|
||||
extractLabelValues(sr, displayMax, displayMin, params);
|
||||
extractLabelValues(preferences, displayMax, displayMin, params);
|
||||
} else if (preferences.getDataMapping() == null) {
|
||||
calculateLabelValues(sr, displayMax, displayMin, params);
|
||||
calculateLabelValues(preferences, displayMax, displayMin,
|
||||
params);
|
||||
if (scale != null) {
|
||||
params.setMirror(scale.isMirror());
|
||||
}
|
||||
|
@ -325,8 +338,8 @@ public class ColorMapParameterFactory {
|
|||
params.setColorMapMin((float) dataMin);
|
||||
params.setDataMin((float) dataMin);
|
||||
|
||||
extractLabelValues(sr, (float) displayMax, (float) displayMin,
|
||||
params);
|
||||
extractLabelValues(preferences, (float) displayMax,
|
||||
(float) displayMin, params);
|
||||
params.setColorMapName(preferences.getDefaultColormap());
|
||||
}
|
||||
if (preferences.getDataScale() != null) {
|
||||
|
@ -338,6 +351,154 @@ public class ColorMapParameterFactory {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the same thing as {@link #build(ImagePreferences, Unit)} but first
|
||||
* unpacks the ImagePreference from a {@link StyleRule}.
|
||||
*
|
||||
* @param sr
|
||||
* @param defaultColorMapUnit
|
||||
* @return
|
||||
* @throws StyleException
|
||||
*/
|
||||
public static ColorMapParameters build(StyleRule sr,
|
||||
Unit<?> defaultColorMapUnit) throws StyleException {
|
||||
if (sr == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"StyleRule must not be null when building ColorMapParameters");
|
||||
}
|
||||
if (sr.getPreferences() instanceof ImagePreferences == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"ImagePreferences are only supported for building ColorMapParameters");
|
||||
}
|
||||
return build((ImagePreferences) sr.getPreferences(),
|
||||
defaultColorMapUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ColorMapParameters} given {@link ImagePreferences} and a
|
||||
* unit to colormap in. This method provides for the simplest color mapping
|
||||
* case. No data or level information is input so the
|
||||
* {@link ImagePreferences} must specify an exact range or data mapping and
|
||||
* also no lableing is added unless the colorbar labeling is specifically
|
||||
* set in the style rule.
|
||||
*
|
||||
* @param preferences
|
||||
* @param defaultColorMapUnit
|
||||
* @return
|
||||
* @throws StyleException
|
||||
*/
|
||||
public static ColorMapParameters build(ImagePreferences preferences,
|
||||
Unit<?> defaultColorMapUnit) throws StyleException {
|
||||
ColorMapParameters params = new ColorMapParameters();
|
||||
|
||||
Unit<?> colorMapUnit = preferences.getColorMapUnitsObject();
|
||||
if (colorMapUnit == null) {
|
||||
colorMapUnit = defaultColorMapUnit;
|
||||
}
|
||||
|
||||
Unit<?> displayUnit = preferences.getDisplayUnits();
|
||||
if (displayUnit == null) {
|
||||
displayUnit = colorMapUnit;
|
||||
} else if (colorMapUnit == null) {
|
||||
colorMapUnit = displayUnit;
|
||||
}
|
||||
|
||||
params.setColorMapUnit(colorMapUnit);
|
||||
params.setDisplayUnit(displayUnit);
|
||||
params.setDataMapping(preferences.getDataMapping());
|
||||
params.setColorMapName(preferences.getDefaultColormap());
|
||||
|
||||
Float displayMin = null, displayMax = null;
|
||||
DataScale scale = preferences.getDataScale();
|
||||
boolean mirrored = false;
|
||||
Type scaleType = Type.LINEAR;
|
||||
if (scale != null) {
|
||||
if (scale.getMinValue() != null) {
|
||||
displayMin = scale.getMinValue().floatValue();
|
||||
}
|
||||
if (scale.getMaxValue() != null) {
|
||||
displayMax = scale.getMaxValue().floatValue();
|
||||
}
|
||||
|
||||
mirrored = scale.isMirror();
|
||||
scaleType = scale.getScaleType();
|
||||
|
||||
}
|
||||
|
||||
if (displayMin == null || displayMax == null) {
|
||||
// Could not find min/max in DataScale, attempt to get from
|
||||
// DataMappingPreferences if set
|
||||
if (params.getDataMapping() != null) {
|
||||
DataMappingPreferences mapping = params.getDataMapping();
|
||||
List<DataMappingEntry> entries = mapping.getEntries();
|
||||
if (entries != null && entries.isEmpty() == false) {
|
||||
if (displayMin == null) {
|
||||
DataMappingEntry min = entries.get(0);
|
||||
if (min.getPixelValue() != null
|
||||
&& min.getDisplayValue() != null) {
|
||||
displayMin = min.getDisplayValue().floatValue();
|
||||
}
|
||||
}
|
||||
if (displayMax == null) {
|
||||
DataMappingEntry max = entries.get(entries.size() - 1);
|
||||
if (max.getPixelValue() != null
|
||||
&& max.getDisplayValue() != null) {
|
||||
displayMax = max.getDisplayValue().floatValue();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (mirrored && (displayMin != null || displayMax != null)) {
|
||||
// Mirror value set
|
||||
if (displayMin == null) {
|
||||
displayMin = -displayMax;
|
||||
} else {
|
||||
displayMax = -displayMin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayMin == null || displayMax == null) {
|
||||
throw new StyleException("Unable to determine colormap min/max.");
|
||||
}
|
||||
|
||||
params.setMirror(mirrored);
|
||||
params.setLogarithmic(scaleType == Type.LOG);
|
||||
|
||||
// Convert to colormap min/max
|
||||
float colorMapMin = displayMin;
|
||||
float colorMapMax = displayMax;
|
||||
|
||||
UnitConverter displayToColorMap = params
|
||||
.getDisplayToColorMapConverter();
|
||||
if (displayToColorMap != null) {
|
||||
colorMapMin = (float) displayToColorMap.convert(displayMin);
|
||||
colorMapMax = (float) displayToColorMap.convert(displayMax);
|
||||
}
|
||||
|
||||
params.setColorMapMin(colorMapMin);
|
||||
params.setColorMapMax(colorMapMax);
|
||||
|
||||
LabelingPreferences labeling = preferences.getColorbarLabeling();
|
||||
if (labeling != null) {
|
||||
if (labeling.getValues() != null) {
|
||||
params.setColorBarIntervals(labeling.getValues());
|
||||
} else if (labeling.getIncrement() != 0) {
|
||||
float increment = labeling.getIncrement();
|
||||
float initialPoint = (float) (Math
|
||||
.ceil(colorMapMin / increment) * increment);
|
||||
float finalPoint = (float) (Math.floor(colorMapMin / increment) * increment);
|
||||
int count = (int) ((finalPoint - initialPoint) / increment) + 1;
|
||||
float[] vals = new float[count];
|
||||
for (int i = 0; i < count; i += 1) {
|
||||
vals[i] = initialPoint + increment * i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
private static Number[] repackData(Object data) {
|
||||
Number[] numArray = null;
|
||||
if (data instanceof byte[]) {
|
||||
|
@ -375,33 +536,27 @@ public class ColorMapParameterFactory {
|
|||
return build(data, parameter, parameterUnits, level, null);
|
||||
}
|
||||
|
||||
private static void extractLabelValues(StyleRule sr, float max, float min,
|
||||
ColorMapParameters parameters) {
|
||||
if (sr != null) {
|
||||
ImagePreferences preferences = (ImagePreferences) sr
|
||||
.getPreferences();
|
||||
if (preferences.getColorbarLabeling() != null) {
|
||||
DataScale dataScale = preferences.getDataScale();
|
||||
if (dataScale != null
|
||||
&& dataScale.isMirror()
|
||||
&& !dataScale.isAdaptive()
|
||||
&& preferences.getColorbarLabeling().getValues() != null) {
|
||||
// if its mirror and not adaptive and the upper half labels
|
||||
// have been provided.
|
||||
createMirror(preferences, parameters);
|
||||
parameters.setMirror(dataScale.isMirror());
|
||||
} else if (preferences.getColorbarLabeling().getValues() != null) {
|
||||
// If a list is provided, use it
|
||||
float[] vals = preferences.getColorbarLabeling()
|
||||
.getValues();
|
||||
private static void extractLabelValues(ImagePreferences preferences,
|
||||
float max, float min, ColorMapParameters parameters) {
|
||||
if (preferences.getColorbarLabeling() != null) {
|
||||
DataScale dataScale = preferences.getDataScale();
|
||||
if (dataScale != null && dataScale.isMirror()
|
||||
&& !dataScale.isAdaptive()
|
||||
&& preferences.getColorbarLabeling().getValues() != null) {
|
||||
// if its mirror and not adaptive and the upper half labels
|
||||
// have been provided.
|
||||
createMirror(preferences, parameters);
|
||||
parameters.setMirror(dataScale.isMirror());
|
||||
} else if (preferences.getColorbarLabeling().getValues() != null) {
|
||||
// If a list is provided, use it
|
||||
float[] vals = preferences.getColorbarLabeling().getValues();
|
||||
|
||||
parameters.setColorBarIntervals(vals);
|
||||
} else {
|
||||
// Populate the list using min and max
|
||||
calculateLabelValues(sr, max, min, parameters);
|
||||
if (dataScale != null) {
|
||||
parameters.setMirror(dataScale.isMirror());
|
||||
}
|
||||
parameters.setColorBarIntervals(vals);
|
||||
} else {
|
||||
// Populate the list using min and max
|
||||
calculateLabelValues(preferences, max, min, parameters);
|
||||
if (dataScale != null) {
|
||||
parameters.setMirror(dataScale.isMirror());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,29 +587,23 @@ public class ColorMapParameterFactory {
|
|||
/**
|
||||
* Derived from ImageDepictable.C::adaptGridImageStyle
|
||||
*/
|
||||
private static void calculateLabelValues(StyleRule sr, float max,
|
||||
float min, ColorMapParameters parameters) {
|
||||
private static void calculateLabelValues(ImagePreferences preferences,
|
||||
float max, float min, ColorMapParameters parameters) {
|
||||
|
||||
boolean haveIncrement = false;
|
||||
float increment = 0.1f;
|
||||
Type dataScaleType = Type.LINEAR;
|
||||
boolean isMirror = false;
|
||||
if (sr != null) {
|
||||
ImagePreferences preferences = (ImagePreferences) sr
|
||||
.getPreferences();
|
||||
if (preferences != null) {
|
||||
LabelingPreferences prefs = preferences.getColorbarLabeling();
|
||||
if (prefs != null) {
|
||||
increment = prefs.getIncrement();
|
||||
haveIncrement = true;
|
||||
}
|
||||
LabelingPreferences prefs = preferences.getColorbarLabeling();
|
||||
if (prefs != null) {
|
||||
increment = prefs.getIncrement();
|
||||
haveIncrement = true;
|
||||
}
|
||||
|
||||
DataScale dataScale = preferences.getDataScale();
|
||||
if (dataScale != null) {
|
||||
dataScaleType = dataScale.getScaleType();
|
||||
isMirror = dataScale.isMirror();
|
||||
}
|
||||
}
|
||||
DataScale dataScale = preferences.getDataScale();
|
||||
if (dataScale != null) {
|
||||
dataScaleType = dataScale.getScaleType();
|
||||
isMirror = dataScale.isMirror();
|
||||
}
|
||||
if (Math.abs(max - min) / increment > 16) {
|
||||
increment *= 2;
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
package com.raytheon.uf.common.style.image;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
@ -28,6 +33,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences;
|
||||
import com.raytheon.uf.common.style.AbstractStylePreferences;
|
||||
import com.raytheon.uf.common.style.LabelingPreferences;
|
||||
import com.raytheon.uf.common.style.StyleException;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -40,6 +46,7 @@ import com.raytheon.uf.common.style.LabelingPreferences;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 27, 2007 chammack Initial Creation.
|
||||
* Nov 25, 2013 2492 bsteffen Add colorMapUnits
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -62,15 +69,18 @@ public class ImagePreferences extends AbstractStylePreferences {
|
|||
@XmlElement
|
||||
private SamplePreferences samplePrefs;
|
||||
|
||||
@XmlElement(name = "dataMapping")
|
||||
@XmlElement
|
||||
private DataMappingPreferences dataMapping;
|
||||
|
||||
@XmlElement(name = "colorbarLabeling")
|
||||
@XmlElement
|
||||
private LabelingPreferences colorbarLabeling;
|
||||
|
||||
@XmlElement(name = "interpolate")
|
||||
@XmlElement
|
||||
private boolean interpolate = true;
|
||||
|
||||
@XmlElement
|
||||
private String colorMapUnits;
|
||||
|
||||
public boolean isInterpolate() {
|
||||
return interpolate;
|
||||
}
|
||||
|
@ -154,4 +164,37 @@ public class ImagePreferences extends AbstractStylePreferences {
|
|||
return legend;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return String representation of colorMapUnits for serialization.
|
||||
* @see ImagePreferences#getColorMapUnitsObject()
|
||||
*/
|
||||
public String getColorMapUnits() {
|
||||
return colorMapUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param colorMapUnits
|
||||
* String representation of colorMapUnits for serialization.
|
||||
* @see ImagePreferences#getColorMapUnitsObject()
|
||||
*/
|
||||
public void setColorMapUnits(String colorMapUnits) {
|
||||
this.colorMapUnits = colorMapUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Units that should be used when color mapping. Mostly useful for cases
|
||||
* where the colormap should be applied non linearly.
|
||||
*/
|
||||
public Unit<?> getColorMapUnitsObject() throws StyleException {
|
||||
if (colorMapUnits != null && !colorMapUnits.isEmpty()) {
|
||||
try {
|
||||
return UnitFormat.getUCUMInstance().parseProductUnit(
|
||||
colorMapUnits, new ParsePosition(0));
|
||||
} catch (ParseException e) {
|
||||
throw new StyleException("Unable to parse colorMap Units.");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,7 +266,7 @@ if [ "${1}" = "-full" ]; then
|
|||
buildRPM "awips2-httpd-pypies"
|
||||
buildJava
|
||||
buildRPM "awips2-groovy"
|
||||
#buildRPM "awips2-ldm"
|
||||
buildRPM "awips2-ldm"
|
||||
buildRPM "awips2-postgres"
|
||||
buildRPM "awips2-pgadmin3"
|
||||
buildRPM "awips2-tools"
|
||||
|
|
|
@ -256,7 +256,7 @@ if [ "${1}" = "-delta" ]; then
|
|||
fi
|
||||
|
||||
if [ "${1}" = "-full" ]; then
|
||||
# buildRPM "awips2-common-base"
|
||||
buildRPM "awips2-common-base"
|
||||
buildCAVE
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
|
@ -277,7 +277,7 @@ if [ "${1}" = "-full" ]; then
|
|||
buildRPM "awips2-python-pil"
|
||||
buildRPM "awips2-python-pmw"
|
||||
buildRPM "awips2-python-pupynere"
|
||||
# buildRPM "awips2-python-qpid"
|
||||
buildRPM "awips2-python-qpid"
|
||||
buildRPM "awips2-python-scientific"
|
||||
buildRPM "awips2-python-scipy"
|
||||
buildRPM "awips2-python-tables"
|
||||
|
|
|
@ -19,17 +19,27 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.geospatial.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.factory.FactoryIteratorProvider;
|
||||
import org.geotools.factory.GeoTools;
|
||||
import org.geotools.geometry.jts.JTS;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.geotools.referencing.crs.DefaultProjectedCRS;
|
||||
import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.parameter.ParameterValueGroup;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.crs.ProjectedCRS;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.projection.Geostationary;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
@ -49,6 +59,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Sep 13, 2013 2309 bsteffen Initial creation
|
||||
* Nov 18, 2013 2528 bsteffen Add test for geostationary.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -94,6 +105,49 @@ public class EnvelopeIntersectionTest {
|
|||
1.0324516833231976E7,
|
||||
MapUtil.AWIPS_POLARSTEREO_NORTHAMERICA);
|
||||
}
|
||||
},
|
||||
|
||||
GEOSTATIONARY {
|
||||
public Envelope getEnvelope() {
|
||||
try {
|
||||
// Must manually register geostation
|
||||
GeoTools.addFactoryIteratorProvider(new FactoryIteratorProvider() {
|
||||
|
||||
@Override
|
||||
public <T> Iterator<T> iterator(Class<T> category) {
|
||||
if (category
|
||||
.isAssignableFrom(Geostationary.Provider.class)) {
|
||||
List<T> tmp = new ArrayList<T>(1);
|
||||
tmp.add(category
|
||||
.cast(new Geostationary.Provider()));
|
||||
return tmp.iterator();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ParameterValueGroup parameters = new DefaultMathTransformFactory()
|
||||
.getDefaultParameters(Geostationary.PROJECTION_NAME);
|
||||
|
||||
parameters.parameter("semi_major").setValue(6378137.0);
|
||||
parameters.parameter("semi_minor").setValue(6356732.31414);
|
||||
parameters.parameter("latitude_of_origin").setValue(0.0);
|
||||
parameters.parameter("central_meridian").setValue(-137);
|
||||
parameters.parameter("false_easting").setValue(0);
|
||||
parameters.parameter("false_northing").setValue(0);
|
||||
parameters.parameter(Geostationary.ORBITAL_HEIGHT)
|
||||
.setValue(35785863.0);
|
||||
parameters.parameter(Geostationary.SWEEP_AXIS)
|
||||
.setValue(0.0);
|
||||
DefaultProjectedCRS crs = MapUtil.constructProjection(
|
||||
Geostationary.PROJECTION_NAME, parameters);
|
||||
return new ReferencedEnvelope(-5434870.792806381,
|
||||
-2356713.972039082, -3799599.721331195,
|
||||
-721442.9005638957, crs);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Unable to create geostationary projection", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public abstract Envelope getEnvelope();
|
||||
|
@ -107,6 +161,7 @@ public class EnvelopeIntersectionTest {
|
|||
double threshold, int maxHorDivisions, int maxVertDivisions,
|
||||
float[] expectedPolygonCoords) throws TransformException,
|
||||
FactoryException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Geometry testGeom = EnvelopeIntersection.createEnvelopeIntersection(
|
||||
source.getEnvelope(), target.getEnvelope(), threshold,
|
||||
maxHorDivisions, maxVertDivisions);
|
||||
|
@ -141,6 +196,10 @@ public class EnvelopeIntersectionTest {
|
|||
// toKML(target.getEnvelope(), (Polygon) testGeom, expectedPolygon,
|
||||
// maxError);
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
System.out.println(source + " intersected with " + target + " took: "
|
||||
+ (endTime - startTime) + "ms");
|
||||
|
||||
Assert.assertTrue(source + " intersected with " + target
|
||||
+ " is too large.",
|
||||
expectedPolygon.buffer(maxError).contains(testGeom));
|
||||
|
@ -237,6 +296,40 @@ public class EnvelopeIntersectionTest {
|
|||
288, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testGeostationaryToUkmet() throws TransformException,
|
||||
FactoryException {
|
||||
/* This was created using printSimplePolygon. */
|
||||
float[] expected = { -803884, -836926, 5717769, -737647, 5605322,
|
||||
-1820270, 5412823, -2767932, 5122653, -3661810, 4764378,
|
||||
-4405659, 2533964, -4570863, -74925, -4826265, 141761,
|
||||
-4699883, 265720, -4585495, 398396, -4374090, -401980,
|
||||
-4451987, -214394, -4335532, -140376, -4231895, -111147,
|
||||
-4039970, -191289, -3862333, -279094, -3778945, -431268,
|
||||
-3701630, 203526, -3560640, 5468, -3401972, -348043, -3256781,
|
||||
130869, -3136911, -224309, -2994515, -678028, -2942195, -31273,
|
||||
-2816425, -277475, -2750530, 73248, -2647495, -149634,
|
||||
-2580518, -547236, -2523641, -92802, -2417432, -447576,
|
||||
-2357760, -82722, -2259030, -453907, -2199805, -112694,
|
||||
-2104320, -555394, -2047966, -184709, -1952826, 22519,
|
||||
-1866703, -312976, -1804583, -88257, -1718835, -567370,
|
||||
-1661644, -78052, -1491513, -585469, -1433545, -305862,
|
||||
-1348754, -19066, -1190667, -484493, -1128908, -299531,
|
||||
-1049446, -76719, -896167, -803884, -836926, };
|
||||
test(KNOWN_ENVELOPES.GEOSTATIONARY, KNOWN_ENVELOPES.UKMET,
|
||||
19097.596365784917, 64, 49, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testGeostationaryToGeostationary()
|
||||
throws TransformException, FactoryException {
|
||||
/* This was created using printSimplePolygon. */
|
||||
float[] expected = { -5434871, -3799600, -5434871, -721443, -2356714,
|
||||
-721443, -2356714, -3799600, -5434871, -3799600 };
|
||||
test(KNOWN_ENVELOPES.GEOSTATIONARY, KNOWN_ENVELOPES.GEOSTATIONARY,
|
||||
19097.596365784917, 64, 49, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can be used to assist in generating test cases. It starts
|
||||
* with a known good result and minimizes the amount of text to put in the
|
||||
|
|
Loading…
Add table
Reference in a new issue