Issue #2122 Refactored satellite to use tile set renderable. Deleted old code

Amend: Added fix for issue 2103
Amend: Added software history

Change-Id: I1e09bcbf28aaffbf602431a09af50da447e4cf2b

Former-commit-id: 78c0e1684e [formerly b4c0d1f715] [formerly 47b55981c8] [formerly 78c0e1684e [formerly b4c0d1f715] [formerly 47b55981c8] [formerly 2f03c38ca0 [formerly 47b55981c8 [formerly e98002c1d18eefe039f0bfc9f1b90ef577d42547]]]]
Former-commit-id: 2f03c38ca0
Former-commit-id: 6b4982e8a3 [formerly c912e8e6c5] [formerly 81f10786b9755a530e3615de10b091e1f0022d78 [formerly bc4ebb4f08]]
Former-commit-id: d7196e32710e3cc8969f238de14a54ee542ee1fa [formerly 20caab72f9]
Former-commit-id: 539bbe2cb5
This commit is contained in:
Max Schenkelberg 2013-06-24 09:21:43 -05:00
parent fd6ecf1273
commit 815ab796b9
16 changed files with 1066 additions and 700 deletions

View file

@ -1,50 +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.viz.core;
import com.raytheon.uf.viz.core.rsc.hdf5.ImageTile;
/**
* Interface for notification when a mesh calculation has completed
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 19, 2010 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public interface IMeshCallback {
/**
* Notification of when the calculation for the mesh of the tile has been
* completed
*
* @param tile
*/
public void meshCalculated(ImageTile tile);
}

View file

@ -35,7 +35,9 @@ import java.nio.ShortBuffer;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 22, 2011 mschenke Initial creation
* Nov 22, 2011 mschenke Initial creation
* Jun 20, 2013 2122 mschenke Made work with slicing from data with
* bounds not starting at 0,0
*
* </pre>
*
@ -61,7 +63,7 @@ public class BufferSlicer {
|| dataBounds.getMinY() < totalBounds.getMinY()
|| dataBounds.getMaxX() > totalBounds.getMaxX()
|| dataBounds.getMaxY() > totalBounds.getMaxY()) {
throw new RuntimeException(
throw new IndexOutOfBoundsException(
"Data bounds defines region outside of buffer's total bounds");
}
@ -111,10 +113,12 @@ public class BufferSlicer {
newData = ByteBuffer.allocate(dataSize);
}
int xOffset = (dataBounds.x - totalBounds.x);
int yOffset = (dataBounds.y - totalBounds.y);
newData.position(0);
byte[] bytes = new byte[dataBounds.width];
for (int i = 0; i < dataBounds.height; ++i) {
data.position((dataBounds.y * totalBounds.width + dataBounds.x) + i
data.position((yOffset * totalBounds.width + xOffset) + i
* totalBounds.width);
data.get(bytes);
newData.put(bytes);
@ -134,10 +138,12 @@ public class BufferSlicer {
newData = ShortBuffer.allocate(dataSize);
}
int xOffset = (dataBounds.x - totalBounds.x);
int yOffset = (dataBounds.y - totalBounds.y);
newData.position(0);
short[] shorts = new short[dataBounds.width];
for (int i = 0; i < dataBounds.height; ++i) {
data.position((dataBounds.y * totalBounds.width + dataBounds.x) + i
data.position((yOffset * totalBounds.width + xOffset) + i
* totalBounds.width);
data.get(shorts);
newData.put(shorts);
@ -157,10 +163,12 @@ public class BufferSlicer {
newData = IntBuffer.allocate(dataSize);
}
int xOffset = (dataBounds.x - totalBounds.x);
int yOffset = (dataBounds.y - totalBounds.y);
newData.position(0);
int[] ints = new int[dataBounds.width];
for (int i = 0; i < dataBounds.height; ++i) {
data.position((dataBounds.y * totalBounds.width + dataBounds.x) + i
data.position((yOffset * totalBounds.width + xOffset) + i
* totalBounds.width);
data.get(ints);
newData.put(ints);
@ -180,10 +188,12 @@ public class BufferSlicer {
newData = FloatBuffer.allocate(dataSize);
}
int xOffset = (dataBounds.x - totalBounds.x);
int yOffset = (dataBounds.y - totalBounds.y);
newData.position(0);
float[] floats = new float[dataBounds.width];
for (int i = 0; i < dataBounds.height; ++i) {
data.position((dataBounds.y * totalBounds.width + dataBounds.x) + i
data.position((yOffset * totalBounds.width + xOffset) + i
* totalBounds.width);
data.get(floats);
newData.put(floats);

View file

@ -20,6 +20,7 @@
package com.raytheon.uf.viz.core.rsc;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -34,6 +35,7 @@ import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IRenderable;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType;
import com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability;
/**
@ -45,7 +47,9 @@ import com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 21, 2011 mschenke Initial creation
* Dec 21, 2011 mschenke Initial creation
* Jun 24, 2013 2122 mschenke Made use built in resource data changed listener
* updates will not be lost from construction to initInternal
*
* </pre>
*
@ -66,38 +70,6 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
IRenderable renderable;
}
private IResourceDataChanged dataChangedListener = new IResourceDataChanged() {
@Override
public void resourceChanged(ChangeType type, Object object) {
if (type == ChangeType.DATA_UPDATE) {
if (object instanceof PluginDataObject) {
addDataObject((PluginDataObject) object);
} else if (object instanceof PluginDataObject[]) {
addDataObject((PluginDataObject[]) object);
} else if (object instanceof Object[]) {
List<PluginDataObject> pdos = new ArrayList<PluginDataObject>();
for (Object obj : (Object[]) object) {
if (obj instanceof PluginDataObject) {
pdos.add((PluginDataObject) obj);
}
}
if (pdos.size() > 0) {
addDataObject(pdos.toArray(new PluginDataObject[0]));
}
}
} else if (type == ChangeType.CAPABILITY) {
if (object instanceof AbstractCapability) {
AbstractCapability capability = (AbstractCapability) object;
for (Frame frame : frames.values()) {
if (frame.renderable != null) {
capabilityChanged(frame.renderable, capability);
}
}
}
}
}
};
private Map<DataTime, Frame> frames = new HashMap<DataTime, Frame>();
/**
@ -110,6 +82,37 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
dataTimes = new ArrayList<DataTime>();
}
@Override
protected void resourceDataChanged(ChangeType type, Object object) {
if (type == ChangeType.DATA_UPDATE) {
if (object instanceof PluginDataObject) {
addDataObject((PluginDataObject) object);
} else if (object instanceof PluginDataObject[]) {
addDataObject((PluginDataObject[]) object);
} else if (object instanceof Object[]) {
List<PluginDataObject> pdos = new ArrayList<PluginDataObject>();
for (Object obj : (Object[]) object) {
if (obj instanceof PluginDataObject) {
pdos.add((PluginDataObject) obj);
}
}
if (pdos.isEmpty() == false) {
addDataObject(pdos.toArray(new PluginDataObject[0]));
}
}
} else if (type == ChangeType.CAPABILITY) {
if (object instanceof AbstractCapability) {
AbstractCapability capability = (AbstractCapability) object;
for (Frame frame : frames.values()) {
if (frame.renderable != null) {
capabilityChanged(frame.renderable, capability);
}
}
}
}
issueRefresh();
}
/**
* Adds the pdo to the appropriate time and removes any renderable or data
* cached for that time.
@ -153,12 +156,14 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
if (updateRenderable(frame.renderable,
pdoList.toArray(new PluginDataObject[0])) == false) {
dispose(frame.renderable);
frame.renderable = null;
}
}
}
if (!dataTimes.contains(dataTimes)) {
dataTimes.add(time);
Collections.sort(dataTimes);
}
}
}
@ -205,6 +210,54 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
return descriptor.getTimeForResource(this);
}
/**
* Gets the renderable for the frame and creates it if it doesn't exist
*
* @param dataTime
* @return
*/
protected IRenderable getOrCreateRenderable(DataTime time)
throws VizException {
Frame frame = null;
IRenderable renderable = null;
synchronized (this) {
frame = frames.get(time);
}
if (frame != null) {
synchronized (frame.lock) {
if (!frame.disposed) {
renderable = frame.renderable;
if (renderable == null) {
frame.renderable = renderable = constructRenderable(
time, new ArrayList<PluginDataObject>(
frame.records));
}
}
}
}
return renderable;
}
/**
* Gets the IRenderable for the given time or null if none exists yet
*
* @param time
* @return
*/
protected IRenderable getRenderable(DataTime time) {
Frame frame = null;
synchronized (this) {
frame = frames.get(time);
}
if (frame != null) {
synchronized (frame.lock) {
return frame.renderable;
}
}
return null;
}
/*
* (non-Javadoc)
*
@ -260,18 +313,8 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
}
@Override
protected final void initInternal(IGraphicsTarget target)
throws VizException {
resourceData.addChangeListener(dataChangedListener);
initResource(target);
}
/**
* Init method for the resource to initialize any data needed for rendering
* which is not tied to a renderable.
*/
protected void initResource(IGraphicsTarget target) throws VizException {
protected void initInternal(IGraphicsTarget target) throws VizException {
// Default no-op
}
/*
@ -292,25 +335,10 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
return;
}
}
Frame currFrame = null;
synchronized (this) {
currFrame = frames.get(time);
}
if (currFrame != null) {
synchronized (currFrame.lock) {
if (currFrame.disposed == false) {
IRenderable renderable = currFrame.renderable;
if (renderable == null) {
currFrame.renderable = renderable = constructRenderable(
time, new ArrayList<PluginDataObject>(
currFrame.records));
}
if (renderable != null) {
renderable.paint(target, paintProps);
}
}
}
IRenderable renderable = getOrCreateRenderable(time);
if (renderable != null) {
renderable.paint(target, paintProps);
}
}
@ -333,7 +361,6 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
disposeFrame(frame);
}
resourceData.removeChangeListener(dataChangedListener);
disposeResource();
}
@ -345,12 +372,14 @@ public abstract class AbstractPluginDataObjectResource<T extends AbstractResourc
*/
private void disposeFrame(Frame frame) {
synchronized (frame.lock) {
if (frame.renderable != null) {
disposeRenderable(frame.renderable);
frame.renderable = null;
if (!frame.disposed) {
if (frame.renderable != null) {
dispose(frame.renderable);
frame.renderable = null;
}
frame.records.clear();
frame.disposed = true;
}
frame.records.clear();
frame.disposed = true;
}
}

View file

@ -170,6 +170,10 @@ public abstract class AbstractVizResource<T extends AbstractResourceData, D exte
paintListeners = new CopyOnWriteArraySet<IPaintListener>();
paintStatusListeners = new CopyOnWriteArraySet<IPaintStatusChangedListener>();
disposeListeners = new CopyOnWriteArraySet<IDisposeListener>();
if (resourceData != null) {
resourceData.addChangeListener(changeListener);
}
}
/**
@ -344,10 +348,6 @@ public abstract class AbstractVizResource<T extends AbstractResourceData, D exte
initInternal(target);
status = ResourceStatus.INITIALIZED;
if (resourceData != null) {
resourceData.addChangeListener(changeListener);
}
for (IInitListener listener : initListeners) {
listener.inited(this);
}

View file

@ -0,0 +1,381 @@
/**
* 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.viz.core.tile;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.opengis.coverage.grid.GridEnvelope;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.HDF5Util;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.RasterMode;
import com.raytheon.uf.viz.core.IMesh;
import com.raytheon.uf.viz.core.PixelCoverage;
import com.raytheon.uf.viz.core.data.BufferSlicer;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.data.prep.HDF5DataRetriever;
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
import com.raytheon.uf.viz.core.drawables.IImage.Status;
import com.raytheon.uf.viz.core.drawables.ext.colormap.IColormappedImageExtension;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapMeshExtension;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
/**
* {@link TileSetRenderable} for 2D {@link PluginDataObject}s. Groups adjacent
* tiles when retrieving data. Default retrieval mechanism uses
* {@link HDF5DataRetriever}. If other mechanism desired, extend class and
* override {@link #retrieveRecordData(Tile)}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 19, 2013 2122 mschenke Initial creation.
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class RecordTileSetRenderable extends TileSetRenderable {
private class RecordTileDataCallback implements
IColorMapDataRetrievalCallback {
private final Tile tile;
private ColorMapData data;
private RecordTileDataCallback(Tile tile) {
this.tile = tile;
}
private void setRetrievedData(ColorMapData data) {
this.data = data;
}
@Override
public ColorMapData getColorMapData() throws VizException {
ColorMapData rval = data;
if (rval != null) {
// Once retrieved, null out
data = null;
} else {
rval = data = retrieveRecordData(tile);
}
return rval;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((tile == null) ? 0 : tile.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RecordTileDataCallback other = (RecordTileDataCallback) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (tile == null) {
if (other.tile != null)
return false;
} else if (!tile.equals(other.tile))
return false;
return true;
}
private RecordTileSetRenderable getOuterType() {
// Only compares outer type class to ensure calls to
// retrieveRecordData will be the same
return RecordTileSetRenderable.this;
}
}
private class RecordTileImageCreatorTask implements Runnable {
private final IGraphicsTarget target;
private final Tile bigTile;
private final List<Tile> subTiles;
public RecordTileImageCreatorTask(IGraphicsTarget target, Tile bigTile,
List<Tile> subTiles) {
this.target = target;
this.bigTile = bigTile;
this.subTiles = subTiles;
}
@Override
public void run() {
int numTiles = subTiles.size();
int numNeedStaging = 0;
List<RecordTileDataCallback> callbacks = new ArrayList<RecordTileDataCallback>(
numTiles);
List<DrawableImage> images = new ArrayList<DrawableImage>(numTiles);
for (Tile tile : subTiles) {
RecordTileDataCallback callback = new RecordTileDataCallback(
tile);
callbacks.add(callback);
DrawableImage image = null;
try {
image = createTileImage(target, tile, callback);
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
images.add(image);
if (image != null
&& image.getImage().getStatus() == Status.UNLOADED) {
numNeedStaging += 1;
}
}
if (numNeedStaging == numTiles) {
// All the images need staging, do bulk request
ColorMapData data = retrieveRecordData(bigTile);
Rectangle bigTileRect = bigTile.getRectangle();
for (int i = 0; i < numTiles; i += 1) {
Tile tile = subTiles.get(i);
DrawableImage image = images.get(i);
if (image != null) {
if (image.getImage().getStatus() == Status.UNLOADED) {
Rectangle tileRect = tile.getRectangle();
ColorMapData subData = new ColorMapData(
BufferSlicer.slice(data.getBuffer(),
tileRect, bigTileRect), new int[] {
tileRect.width, tileRect.height },
data.getDataType());
callbacks.get(i).setRetrievedData(subData);
try {
image.getImage().stage();
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
}
}
}
for (int i = 0; i < numTiles; i += 1) {
Tile tile = subTiles.get(i);
DrawableImage image = images.get(i);
addTileImage(tile, image);
}
target.setNeedsRefresh(true);
}
public DrawableImage createTileImage(IGraphicsTarget target, Tile tile,
RecordTileDataCallback callback) throws VizException {
IColormappedImage image = target.getExtension(
IColormappedImageExtension.class).initializeRaster(
callback, colormapping.getColorMapParameters());
IMesh mesh = target.getExtension(IMapMeshExtension.class)
.constructMesh(tile.tileGeometry,
tileSet.getTargetGeometry());
return new DrawableImage(image, new PixelCoverage(mesh),
RasterMode.ASYNCHRONOUS);
}
}
protected final ColorMapCapability colormapping;
protected final PluginDataObject record;
public RecordTileSetRenderable(AbstractVizResource<?, ?> resource,
PluginDataObject record, ISpatialObject spatialObject,
int tileLevels) {
this(resource, record, MapUtil.getGridGeometry(spatialObject),
tileLevels);
}
public RecordTileSetRenderable(AbstractVizResource<?, ?> resource,
PluginDataObject record, GridGeometry2D tileSetGeometry,
int tileLevels) {
this(resource, record, tileSetGeometry, tileLevels, 512);
}
public RecordTileSetRenderable(AbstractVizResource<?, ?> resource,
PluginDataObject record, GridGeometry2D tileSetGeometry,
int tileLevels, int tileSize) {
super(resource.getCapability(ImagingCapability.class), tileSetGeometry,
null, tileLevels, tileSize);
this.record = record;
this.colormapping = resource.getCapability(ColorMapCapability.class);
}
@Override
protected void createTileImages(IGraphicsTarget target,
Collection<Tile> tilesToCreate) {
Map<Integer, List<Tile>> mapped = new HashMap<Integer, List<Tile>>();
for (Tile tile : tilesToCreate) {
// Ensure no job already scheduled for tile
if (jobMap.get(tile) == null) {
List<Tile> tiles = mapped.get(tile.tileLevel);
if (tiles == null) {
tiles = new ArrayList<Tile>();
mapped.put(tile.tileLevel, tiles);
}
tiles.add(tile);
}
}
for (Integer tileLevel : mapped.keySet()) {
List<Tile> tiles = mapped.get(tileLevel);
List<GridEnvelope2D> rectangles = new ArrayList<GridEnvelope2D>();
List<Envelope2D> envelopes = new ArrayList<Envelope2D>();
for (Tile tile : tiles) {
rectangles.add(tile.tileGeometry.getGridRange2D());
envelopes.add(tile.tileGeometry.getEnvelope2D());
}
// Join together any adjacent rectangles
for (int i = 0; i < rectangles.size(); i++) {
Rectangle r1 = rectangles.get(i);
Envelope2D e1 = envelopes.get(i);
for (int j = i + 1; j < rectangles.size(); j++) {
Rectangle r2 = rectangles.get(j);
Envelope2D e2 = envelopes.get(j);
boolean joinable = true;
if (r1.x == r2.x && r1.width == r2.width) {
if (r1.getMaxY() == r2.getMinY()
|| r1.getMinY() == r2.getMaxY()) {
joinable = true;
}
} else if (r1.y == r2.y && r1.height == r2.height) {
if (r1.getMaxX() == r2.getMinX()
|| r1.getMinX() == r2.getMaxX()) {
joinable = true;
}
}
if (joinable) {
// Join the rectangles
rectangles.remove(r1);
rectangles.remove(r2);
Rectangle2D joined = new GridEnvelope2D();
Rectangle2D.union(r1, r2, joined);
rectangles.add((GridEnvelope2D) joined);
// Join the envelopes
envelopes.remove(e1);
envelopes.remove(e2);
joined = new Envelope2D();
Rectangle2D.union(e1, e2, joined);
envelopes.add((Envelope2D) joined);
// start all over.
i = -1;
break;
}
}
}
// start a separate job for every big rectangle
for (int i = 0; i < rectangles.size(); i++) {
Tile joinedTile = new Tile(tileLevel, new GridGeometry2D(
(GridEnvelope) rectangles.get(i), envelopes.get(i)));
RecordTileImageCreatorTask task = new RecordTileImageCreatorTask(
target, joinedTile, tiles);
for (Tile tile : tiles) {
jobMap.put(tile, task);
}
tileCreationPool.schedule(task);
}
}
}
/**
* @param tile
* @return
*/
protected ColorMapData retrieveRecordData(Tile tile) {
return new HDF5DataRetriever(HDF5Util.findHDF5Location(record),
DataStoreFactory.createDataSetName(record.getDataURI(),
DataStoreFactory.DEF_DATASET_NAME, tile.tileLevel),
tile.getRectangle()).getColorMapData();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((record == null) ? 0 : record.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RecordTileSetRenderable other = (RecordTileSetRenderable) obj;
if (record == null) {
if (other.record != null)
return false;
} else if (!record.equals(other.record))
return false;
return true;
}
}

View file

@ -22,6 +22,7 @@ package com.raytheon.uf.viz.core.tile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -63,7 +64,9 @@ import com.vividsolutions.jts.geom.Coordinate;
* ------------ ---------- ----------- --------------------------
* Aug 8, 2012 mschenke Initial creation
* May 28, 2013 2037 njensen Made imageMap concurrent to fix leak
*
* Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made
* canceling jobs safer
*
* </pre>
*
* @author mschenke
@ -297,7 +300,21 @@ public class TileSetRenderable implements IRenderable {
lastPaintedLevel = usedTileLevel;
return getImagesWithinExtent(target, paintProps.getView().getExtent(),
usedTileLevel, 0);
usedTileLevel);
}
/**
* Gets the images to render within the extent in target grid space
*
* @param target
* @param extent
* @param level
* @return
* @throws VizException
*/
protected List<DrawableImage> getImagesWithinExtent(IGraphicsTarget target,
IExtent extent, int level) {
return getImagesWithinExtent(target, extent, level, 0);
}
/**
@ -309,8 +326,8 @@ public class TileSetRenderable implements IRenderable {
* @return
* @throws VizException
*/
protected List<DrawableImage> getImagesWithinExtent(IGraphicsTarget target,
IExtent extent, int level, int depth) throws VizException {
private List<DrawableImage> getImagesWithinExtent(IGraphicsTarget target,
IExtent extent, int level, int depth) {
if (tileSet == null) {
// Early exit condition, disposed or haven't projected yet
return Collections.emptyList();
@ -366,10 +383,13 @@ public class TileSetRenderable implements IRenderable {
// All intersecting tiles are loaded for this level, cancel any
// jobs running for tiles we don't need anymore (may be case if
// zooming or panning)
for (Runnable job : jobMap.values()) {
tileCreationPool.cancel(job);
Iterator<Runnable> iterator = jobMap.values().iterator();
while (iterator.hasNext()) {
Runnable job = iterator.next();
if (tileCreationPool.cancel(job)) {
iterator.remove();
}
}
jobMap.clear();
} else {
target.setNeedsRefresh(true);
// Create tiles needing images
@ -446,12 +466,15 @@ public class TileSetRenderable implements IRenderable {
TileLevel level = tileSet.getTileLevel(lastPaintedLevel);
double[] grid = level.crsToGrid(localX, localY);
Tile tile = level.getTile(grid[0], grid[1]);
DrawableImage di = imageMap.get(tile);
if (di != null) {
IImage image = di.getImage();
if (image instanceof IColormappedImage) {
return ((IColormappedImage) image).getValue((int) grid[0]
% tileSize, (int) grid[1] % tileSize);
if (tile != null) {
DrawableImage di = imageMap.get(tile);
if (di != null) {
IImage image = di.getImage();
if (image instanceof IColormappedImage) {
return ((IColormappedImage) image).getValue(
(int) grid[0] % tileSize, (int) grid[1]
% tileSize);
}
}
}
} catch (TransformException e) {

View file

@ -24,10 +24,8 @@ import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.collections.keyvalue.MultiKey;
@ -53,7 +51,6 @@ import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.RasterMode;
import com.raytheon.uf.viz.core.IMeshCallback;
import com.raytheon.uf.viz.core.PixelCoverage;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
@ -83,13 +80,14 @@ import com.vividsolutions.jts.geom.Coordinate;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 15, 2007 chammack Initial Creation.
* Jun 24, 2013 2122 mschenke Removed unused IMeshCallback listeners
*
* </pre>
*
* @author chammack
* @version 1
*/
public abstract class AbstractTileSet implements IRenderable, IMeshCallback {
public abstract class AbstractTileSet implements IRenderable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(AbstractTileSet.class);
@ -147,8 +145,6 @@ public abstract class AbstractTileSet implements IRenderable, IMeshCallback {
private boolean disposed = true;
private Set<IMeshCallback> meshCallbacks = new HashSet<IMeshCallback>();
public AbstractTileSet(int levels, int tileSize,
GridGeometry2D gridGeometry, AbstractVizResource<?, ?> rsc,
PixelInCell pixelOrientation, String viewType) throws VizException {
@ -905,18 +901,4 @@ public abstract class AbstractTileSet implements IRenderable, IMeshCallback {
return jobMap.isEmpty();
}
public void addMeshCallback(IMeshCallback meshCallback) {
this.meshCallbacks.add(meshCallback);
}
public void removeMeshCallback(IMeshCallback meshCallback) {
this.meshCallbacks.remove(meshCallback);
}
public void meshCalculated(ImageTile tile) {
for (IMeshCallback meshCallback : meshCallbacks) {
meshCallback.meshCalculated(tile);
}
}
}

View file

@ -1,254 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.rsc.hdf5;
import java.io.File;
import java.io.FileNotFoundException;
import javax.measure.converter.UnitConverter;
import org.geotools.coverage.grid.GridGeometry2D;
import org.opengis.referencing.datum.PixelInCell;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.StorageException;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.data.IDataPreparer;
import com.raytheon.uf.viz.core.data.prep.CMDataPreparerManager;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
/**
* Memory based tileset.
*
* This memory-based tileset pulls a small raster from an hdf5 file and
* interpolates it to a larger size. The raster is then split once it is already
* loaded in memory.git pull
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 15, 2007 chammack Initial Creation.
*
* </pre>
*
* @author chammack
* @version 1
*/
public class MemoryBasedTileSet extends AbstractTileSet {
protected Object[] loadedData;
protected int[][] dims;
protected boolean[] isLoaded;
protected UnitConverter converter;
protected PluginDataObject pdo;
protected String hdf5File;
protected String group;
protected String dataset;
public MemoryBasedTileSet(String hdf5File, String group, String dataset,
AbstractTileSet sharedGeometryTileset, UnitConverter converter,
PluginDataObject pdo) throws VizException {
super(sharedGeometryTileset);
this.converter = converter;
this.isLoaded = new boolean[sharedGeometryTileset.levels];
this.pdo = pdo;
this.hdf5File = hdf5File;
this.group = group;
this.dataset = dataset;
}
public MemoryBasedTileSet(String hdf5File, String group, String dataset,
int levels, int tileSize, GridGeometry2D gridGeometry,
AbstractVizResource<?, ?> rsc, UnitConverter converter,
PixelInCell orientation, PluginDataObject pdo, String viewType)
throws VizException {
super(levels, tileSize, gridGeometry, rsc, orientation, viewType);
this.converter = converter;
this.isLoaded = new boolean[levels];
this.pdo = pdo;
this.hdf5File = hdf5File;
this.group = group;
this.dataset = dataset;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.rsc.tiling.AbstractTileSet#preloadDataObject(int)
*/
@Override
protected void preloadDataObject(int level) throws StorageException {
synchronized (isLoaded) {
if (isLoaded[level]) {
return;
}
IDataRecord rec = getDataRecord();
if (loadedData == null) {
loadedData = new Object[levels];
dims = new int[levels][];
}
if (rec != null) {
loadedData[level] = rec.getDataObject();
long[] d = rec.getSizes();
dims[level] = new int[] { (int) d[0], (int) d[1] };
}
isLoaded[level] = true;
}
}
protected IDataRecord getDataRecord() throws StorageException {
if (pdo != null) {
try {
IDataRecord[] records = DataCubeContainer.getDataRecord(pdo);
if (records != null && records.length > 0) {
return records[0];
}
} catch (VizDataCubeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
IDataStore ds = DataStoreFactory
.getDataStore(new File(hdf5File));
return ds.retrieve("", group + "/" + dataset, Request.ALL);
// (float) this.interpolationFactorOnLoad
// * (float) (Math.pow(2, this.levels
// - level - 1)));
} catch (FileNotFoundException e) {
throw new StorageException("Unable to open file", null, e);
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.rsc.tiling.AbstractTileSet#createTile(com.raytheon
* .viz.core.IGraphicsTarget, int, int, int)
*/
@Override
protected IImage createTile(IGraphicsTarget target, int level, int i, int j)
throws VizException {
IDataPreparer preparer = CMDataPreparerManager.getDataPreparer(
loadedData[level], this.tileSet.getTile(level, i, j)
.getRectangle(), dims[level]);
return target.initializeRaster(preparer,
rsc.getCapability(ColorMapCapability.class)
.getColorMapParameters());
}
public float getDataMin() {
float dataMin = Float.POSITIVE_INFINITY;
if (loadedData[0] instanceof float[]) {
float[] floatData = (float[]) loadedData[0];
for (int i = 0; i < floatData.length; i++) {
if (!Float.isNaN(floatData[i]) && floatData[i] != -999999) {
dataMin = Math.min(dataMin, floatData[i]);
}
}
}
return dataMin;
}
public float getDataMax() {
float dataMax = Float.NEGATIVE_INFINITY;
if (loadedData[0] instanceof float[]) {
float[] floatData = (float[]) loadedData[0];
for (int i = 0; i < floatData.length; i++) {
if (!Float.isNaN(floatData[i]) && floatData[i] != -999999) {
dataMax = Math.max(dataMax, floatData[i]);
}
}
}
return dataMax;
}
protected IDataRecord getFullDataSet() throws StorageException,
FileNotFoundException {
IDataStore ds = DataStoreFactory.getDataStore(new File(hdf5File));
IDataRecord dr = ds.retrieve(group, dataset, Request.ALL);
if (converter == null) {
return dr;
}
if (dr instanceof FloatDataRecord) {
float[] fd = ((FloatDataRecord) dr).getFloatData();
for (int i = 0; i < fd.length; i++) {
fd[i] = (float) converter.convert(fd[i]);
}
}
return dr;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.rsc.tiling.AbstractTileSet#hasDataPreloaded(int)
*/
@Override
public boolean hasDataPreloaded(int level) {
return this.isLoaded[level];
}
@Override
public void cancelRequest(int level, int i, int j) {
// TODO Auto-generated method stub
}
}

View file

@ -53,7 +53,7 @@ import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
* @author mschenke
* @version 1.0
*/
@Deprecated
public class SatDataRetriever implements IColorMapDataRetrievalCallback {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SatDataRetriever.class);

View file

@ -50,7 +50,10 @@ import com.raytheon.viz.core.rsc.hdf5.AbstractTileSet;
import com.raytheon.viz.core.rsc.hdf5.CreateTileJob;
import com.raytheon.viz.core.rsc.hdf5.FileBasedTileSet;
import com.raytheon.viz.satellite.data.prep.SatDataRetriever;
import com.raytheon.viz.satellite.tileset.SatTileSetRenderable;
/** Use {@link SatTileSetRenderable} instead */
@Deprecated
public class SatFileBasedTileSet extends FileBasedTileSet {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SatFileBasedTileSet.class);

View file

@ -23,8 +23,8 @@ import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -33,9 +33,7 @@ import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import org.opengis.coverage.grid.GridGeometry;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import com.raytheon.uf.common.colormap.IColorMap;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
@ -47,26 +45,23 @@ import com.raytheon.uf.common.dataplugin.satellite.units.counts.DerivedWVPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.goes.PolarPrecipWaterPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
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.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IMeshCallback;
import com.raytheon.uf.viz.core.drawables.ColorMapLoader;
import com.raytheon.uf.viz.core.drawables.IRenderable;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.core.rsc.hdf5.ImageTile;
import com.raytheon.uf.viz.core.style.ParamLevelMatchCriteria;
import com.raytheon.uf.viz.core.style.StyleManager;
import com.raytheon.uf.viz.core.style.StyleRule;
@ -74,11 +69,11 @@ import com.raytheon.uf.viz.core.style.level.Level;
import com.raytheon.uf.viz.core.style.level.SingleLevel;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterRequest;
import com.raytheon.viz.core.drawables.ColorMapParameterFactory;
import com.raytheon.viz.core.rsc.hdf5.AbstractTileSet;
import com.raytheon.viz.core.rsc.hdf5.FileBasedTileSet;
import com.raytheon.viz.core.style.image.ImagePreferences;
import com.raytheon.viz.core.style.image.SamplePreferences;
import com.raytheon.viz.satellite.SatelliteConstants;
import com.raytheon.viz.satellite.tileset.SatTileSetRenderable;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Provides satellite raster rendering support
@ -93,49 +88,151 @@ import com.raytheon.viz.satellite.SatelliteConstants;
* 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
* 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.
* 07/17/2012 798 jkorman Use decimationLevels from SatelliteRecord. Removed hard-coded
* data set names.
* 06/20/2013 2122 mschenke Modified to use SatTileSetRenderable
* </pre>
*
* @author chammack
* @version 1
*/
public class SatResource extends
AbstractVizResource<SatResourceData, MapDescriptor> implements
IResourceDataChanged, IMeshCallback {
public static String RAW_VALUE = "rawValue";
AbstractPluginDataObjectResource<SatResourceData, IMapDescriptor> {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SatResource.class);
protected Map<DataTime, SatFileBasedTileSet> tileSet;
public static String RAW_VALUE = "rawValue";
private Map<DataTime, SatelliteRecord> recordMap = new HashMap<DataTime, SatelliteRecord>();
private static class InterrogationResult {
protected DataTime displayedDate;
private final SatelliteRecord record;
protected SatFileBasedTileSet baseTile;
private final double value;
public InterrogationResult(SatelliteRecord record, double value) {
this.record = record;
this.value = value;
}
public SatelliteRecord getRecord() {
return record;
}
public double getValue() {
return value;
}
}
private class SatRenderable implements IRenderable {
private Map<ISpatialObject, SatTileSetRenderable> tileMap = new HashMap<ISpatialObject, SatTileSetRenderable>();
private DataTime renderableTime;
public SatRenderable(DataTime renderableTime) {
this.renderableTime = renderableTime;
}
@Override
public void paint(IGraphicsTarget target, PaintProperties paintProps)
throws VizException {
Collection<DrawableImage> images = getImagesToRender(target,
paintProps);
if (images.isEmpty() == false) {
target.drawRasters(paintProps,
images.toArray(new DrawableImage[0]));
}
}
public Collection<DrawableImage> getImagesToRender(
IGraphicsTarget target, PaintProperties paintProps)
throws VizException {
List<DrawableImage> images = new ArrayList<DrawableImage>();
synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) {
images.addAll(renderable.getImagesToRender(target,
paintProps));
}
}
return images;
}
public void addRecord(SatelliteRecord record) {
synchronized (tileMap) {
SatTileSetRenderable tileSet = tileMap.get(record
.getSpatialObject());
if (tileSet != null) {
SatelliteRecord existingRecord = tileSet
.getSatelliteRecord();
if (existingRecord.equals(record) == false) {
// Different record, same spatial area for same frame
// Determine if new one is better than existing
long existingTimeMillis = existingRecord.getDataTime()
.getMatchRef();
long newRecordTimeMillis = record.getDataTime()
.getMatchRef();
long normalTimeMillis = renderableTime.getMatchRef();
if (Math.abs(normalTimeMillis - newRecordTimeMillis) < Math
.abs(normalTimeMillis - existingTimeMillis)) {
// New is better since it's data time is closer to
// the normal time than the existing record's time!
tileSet.dispose();
tileSet = null;
}
}
}
if (tileSet == null) {
tileSet = new SatTileSetRenderable(SatResource.this, record);
tileSet.project(descriptor.getGridGeometry());
tileMap.put(record.getSpatialObject(), tileSet);
}
}
}
public void project() {
synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) {
renderable.project(descriptor.getGridGeometry());
}
}
}
public void dispose() {
synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) {
renderable.dispose();
}
tileMap.clear();
}
}
public InterrogationResult interrogate(Coordinate latLon)
throws VizException {
InterrogationResult result = null;
synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) {
double rValue = renderable.interrogate(latLon);
if (Double.isNaN(rValue) == false && rValue != fillValue) {
result = new InterrogationResult(
renderable.getSatelliteRecord(), rValue);
}
}
}
return result;
}
}
protected String legend;
protected IGraphicsTarget target;
protected boolean hasBeenInited;
protected int numLevels;
protected String viewType;
protected SatFileBasedTileSet currentTile;
protected GridGeometry recordGeometry;
protected SamplePreferences sampleRange;
protected double fillValue = 0;
/**
* Constructor
*
@ -143,28 +240,27 @@ public class SatResource extends
*/
public SatResource(SatResourceData data, LoadProperties props) {
super(data, props);
data.addChangeListener(this);
this.tileSet = new HashMap<DataTime, SatFileBasedTileSet>();
this.dataTimes = new ArrayList<DataTime>();
this.legend = null;
SatelliteRecord[] records = data.getRecords();
Arrays.sort(records, new SatelliteRecordComparator());
addDataObject(data.getRecords());
}
for (SatelliteRecord record : records) {
@Override
protected DataTime getDataObjectTime(PluginDataObject pdo) {
SatelliteRecord record = (SatelliteRecord) pdo;
if (dataTimes.isEmpty()) {
try {
addRecord(record);
initializeFirstFrame(record);
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM,
"Error adding satellite record", e);
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
}
/*
* This handles if there is no data for East & West CONUS simultaneously
*/
if (dataTimes.size() > 1) {
displayedDate = dataTimes.get(dataTimes.size() - 1);
DataTime pdoTime = pdo.getDataTime();
if (resourceData.getBinOffset() != null) {
pdoTime = resourceData.getBinOffset().getNormalizedTime(pdoTime);
}
return pdoTime;
}
private void initializeFirstFrame(SatelliteRecord record)
@ -219,6 +315,7 @@ public class SatResource extends
cmName = colorMapParameters.getColorMapName();
}
}
// Grab the sampleRange from the preferences
ParamLevelMatchCriteria match = new ParamLevelMatchCriteria();
match.setParameterName(Arrays.asList(physicalElement));
@ -229,17 +326,16 @@ public class SatResource extends
if (sr != null && sr.getPreferences() instanceof ImagePreferences) {
sampleRange = ((ImagePreferences) sr.getPreferences())
.getSamplePrefs();
String lg = ((ImagePreferences) sr.getPreferences())
.getLegend();
String lg = ((ImagePreferences) sr.getPreferences()).getLegend();
// test, so legend is not over written with empty string
if (lg != null && !lg.trim().isEmpty()) {
legend = lg;
}
}
colorMapParameters = ColorMapParameterFactory.build(null,
record.getDataURI() + "/Data", physicalElement, unit, level,
creatingEntity);
colorMapParameters = ColorMapParameterFactory.build((Object) null,
physicalElement, unit, level, creatingEntity);
// TODO: Figure out data/color map min/max values better
if (unit == null) {
colorMapParameters.setColorMapMin(0.0f);
colorMapParameters.setColorMapMax(255.0f);
@ -259,18 +355,21 @@ public class SatResource extends
colorMapParameters.setDataMax(255.0f);
}
if (colorMap == null) {
if (cmName == null) {
cmName = "Sat/VIS/ZA (Vis Default)";
}
colorMap = ColorMapLoader.loadColorMap(cmName);
}
if (colorMap != null) {
colorMapParameters.setColorMap(colorMap);
}
if (cmName != null) {
colorMapParameters.setColorMapName(cmName);
}
getCapability(ColorMapCapability.class).setColorMapParameters(
colorMapParameters);
// number of interpolation levels plus the base level!
numLevels = record.getInterpolationLevels() + 1;
this.legend = getLegend(record);
}
@Override
@ -281,110 +380,32 @@ public class SatResource extends
return "";
}
@Override
protected void disposeInternal() {
if (baseTile != null)
baseTile.dispose();
for (AbstractTileSet tile : this.tileSet.values())
if (tile != baseTile)
tile.dispose();
}
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
synchronized (this) {
this.viewType = target.getViewType();
this.hasBeenInited = true;
this.target = target;
if (this.baseTile != null) {
this.baseTile.init(target);
}
for (AbstractTileSet tile : this.tileSet.values()) {
if (tile != baseTile) {
tile.init(target);
}
}
}
ColorMapParameters params = getCapability(ColorMapCapability.class)
.getColorMapParameters();
if (params.getColorMap() == null) {
String colorMapName = params.getColorMapName();
if (colorMapName == null)
colorMapName = "Sat/VIS/ZA (Vis Default)";
params.setColorMap(target.buildColorMap(colorMapName));
}
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.viz.core.rsc.IVizResource#paint(com.raytheon.viz.core.
* IGraphicsTarget, com.raytheon.viz.core.PixelExtent, double, float)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
this.target = target;
this.displayedDate = paintProps.getDataTime();
if (this.displayedDate == null)
return;
currentTile = this.tileSet.get(this.displayedDate);
if (currentTile != null) {
currentTile.paint(target, paintProps);
}
// System.out.println("Time to paint: "
// + (System.currentTimeMillis() - t0));
}
@Override
public void setDescriptor(MapDescriptor descriptor) {
if (this.baseTile != null) {
this.baseTile.setMapDescriptor(descriptor);
}
for (AbstractTileSet tile : this.tileSet.values())
tile.setMapDescriptor(descriptor);
this.descriptor = descriptor;
}
@Override
public void project(CoordinateReferenceSystem mapData) throws VizException {
if (this.baseTile != null)
this.baseTile.reproject();
for (AbstractTileSet tile : tileSet.values())
tile.reproject();
}
@Override
public Map<String, Object> interrogate(ReferencedCoordinate coord)
throws VizException {
DataTime displayedDate = descriptor.getFramesInfo().getTimeForResource(
this);
Map<String, Object> dataMap = new HashMap<String, Object>();
SatelliteRecord record = recordMap.get(displayedDate);
if (record != null) {
dataMap.put(ISpatialObject.class.toString(),
record.getSpatialObject());
AbstractTileSet tile = tileSet.get(displayedDate);
if (tile != null) {
try {
Double raw = tile.interrogate(coord.asLatLon(), true);
if (raw != 0 && raw.isNaN() == false) {
UnitConverter dataToDisplay = getCapability(
ColorMapCapability.class)
.getColorMapParameters()
.getDataToDisplayConverter();
if (dataToDisplay != null) {
raw = dataToDisplay.convert(raw);
}
dataMap.put(RAW_VALUE, raw);
SatRenderable renderable = (SatRenderable) getRenderable(displayedDate);
if (renderable != null) {
try {
InterrogationResult result = renderable.interrogate(coord
.asLatLon());
if (result != null) {
double dataValue = result.getValue();
UnitConverter dataToDisplay = getCapability(
ColorMapCapability.class).getColorMapParameters()
.getDataToDisplayConverter();
if (dataToDisplay != null) {
dataValue = dataToDisplay.convert(dataValue);
}
} catch (Exception e) {
throw new VizException("Error interrogating raw data", e);
dataMap.put(RAW_VALUE, dataValue);
dataMap.put(ISpatialObject.class.toString(), result
.getRecord().getSpatialObject());
}
} catch (Exception e) {
throw new VizException("Error interrogating raw data", e);
}
}
return dataMap;
@ -434,116 +455,7 @@ public class SatResource extends
return String.format("%.1f%s", value, unitString);
}
public class SatelliteRecordComparator implements
Comparator<SatelliteRecord> {
public int compare(SatelliteRecord o1, SatelliteRecord o2) {
return o1.getDataTime().getRefTime()
.compareTo(o2.getDataTime().getRefTime());
}
}
public void addRecord(PluginDataObject record) throws VizException {
synchronized (this) {
SatFileBasedTileSet tile;
DataTime recordTime = null;
if (resourceData.getBinOffset() != null || resourceData.equals(0)) {
BinOffset binOffset = resourceData.getBinOffset();
DataTime recTime = record.getDataTime();
DataTime normTime = binOffset.getNormalizedTime(recTime);
if (recordMap.containsKey(normTime)) {
// a normalized time was found...
// if this record's time is closer than the existing
// record's
// then replace the existing record with the new record
SatelliteRecord satRec = recordMap.get(normTime);
DataTime existingTime = satRec.getDataTime();
long existingTimeMillis = existingTime
.getRefTimeAsCalendar().getTimeInMillis();
long recTimeMillies = recTime.getRefTimeAsCalendar()
.getTimeInMillis();
long normTimeMillies = normTime.getRefTimeAsCalendar()
.getTimeInMillis();
if (Math.abs(normTimeMillies - existingTimeMillis) > Math
.abs(normTimeMillies - recTimeMillies)) {
// System.out.println("For " + normTime +
// "\n\treplaced "
// + existingTime + "\n\twith " + recTime);
recordMap.remove(normTime);
FileBasedTileSet oldTile = tileSet.remove(normTime);
if (oldTile != null) {
oldTile.dispose();
}
}
}
recordTime = normTime;
} else {
recordTime = record.getDataTime();
}
recordMap.put(recordTime, (SatelliteRecord) record);
if (baseTile == null) {
initializeFirstFrame((SatelliteRecord) record);
}
if (baseTile == null) {
tile = baseTile = new SatFileBasedTileSet(record, DataStoreFactory.DEF_DATASET_NAME,
numLevels, 256,
MapUtil.getGridGeometry(((SatelliteRecord) record)
.getSpatialObject()), this,
PixelInCell.CELL_CORNER, viewType);
} else {
tile = new SatFileBasedTileSet(record, DataStoreFactory.DEF_DATASET_NAME, baseTile);
}
tile.addMeshCallback(this);
tile.setMapDescriptor(this.descriptor);
if (hasBeenInited)
tile.init(target);
if (this.legend == null) {
this.legend = getLegend(record);
}
FileBasedTileSet oldTile = tileSet.put(recordTime, tile);
if (oldTile != null) {
oldTile.dispose();
}
dataTimes.add(recordTime);
Collections.sort(this.dataTimes);
}
}
@Override
public void remove(DataTime dataTime) {
synchronized (this) {
if (!this.dataTimes.contains(dataTime))
return;
this.dataTimes.remove(dataTime);
FileBasedTileSet tile = tileSet.remove(dataTime);
if (tile != baseTile && tile != null)
tile.dispose();
}
}
@Override
public void resourceChanged(ChangeType type, Object object) {
if (type.equals(ChangeType.DATA_UPDATE)) {
PluginDataObject[] pdos = (PluginDataObject[]) object;
for (PluginDataObject pdo : pdos) {
try {
this.addRecord(pdo);
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM,
"Error updating satellite resource", e);
}
}
}
issueRefresh();
}
private String getLegend(PluginDataObject record) {
String productName = null;
DerivedParameterRequest request = (DerivedParameterRequest) record
.getMessageData();
@ -556,23 +468,87 @@ public class SatResource extends
((SatelliteRecord) record).getCreatingEntity());
}
@Override
public void meshCalculated(ImageTile tile) {
issueRefresh();
}
public List<DrawableImage> getImages(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
this.target = target;
this.displayedDate = paintProps.getDataTime();
if (this.displayedDate == null)
return Collections.emptyList();
currentTile = this.tileSet.get(this.displayedDate);
if (currentTile != null) {
return currentTile.getImages(target, paintProps);
SatRenderable renderable = (SatRenderable) getOrCreateRenderable(paintProps
.getDataTime());
if (renderable != null) {
return new ArrayList<DrawableImage>(renderable.getImagesToRender(
target, paintProps));
}
return Collections.emptyList();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource#
* capabilityChanged(com.raytheon.uf.viz.core.drawables.IRenderable,
* com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability)
*/
@Override
protected void capabilityChanged(IRenderable renderable,
AbstractCapability capability) {
issueRefresh();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource#
* disposeRenderable(com.raytheon.uf.viz.core.drawables.IRenderable)
*/
@Override
protected void disposeRenderable(IRenderable renderable) {
((SatRenderable) renderable).dispose();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource#
* projectRenderable(com.raytheon.uf.viz.core.drawables.IRenderable,
* org.opengis.referencing.crs.CoordinateReferenceSystem)
*/
@Override
protected boolean projectRenderable(IRenderable renderable,
CoordinateReferenceSystem crs) throws VizException {
((SatRenderable) renderable).project();
return true;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource#
* constructRenderable(com.raytheon.uf.common.time.DataTime, java.util.List)
*/
@Override
protected IRenderable constructRenderable(DataTime time,
List<PluginDataObject> records) throws VizException {
SatRenderable renderable = new SatRenderable(time);
updateRenderable(renderable, records.toArray(new PluginDataObject[0]));
renderable.project();
return renderable;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractPluginDataObjectResource#
* updateRenderable(com.raytheon.uf.viz.core.drawables.IRenderable,
* com.raytheon.uf.common.dataplugin.PluginDataObject[])
*/
@Override
protected boolean updateRenderable(IRenderable renderable,
PluginDataObject... pdos) {
SatRenderable sr = (SatRenderable) renderable;
for (PluginDataObject object : pdos) {
if (object instanceof SatelliteRecord) {
sr.addRecord((SatelliteRecord) object);
}
}
return true;
}
}

View file

@ -0,0 +1,181 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.satellite.tileset;
import java.awt.Rectangle;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
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.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
/**
* {@link IColorMapDataRetrievalCallback} for satellite imagery data. Supports
* signed and unsigned byte and short data
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 20, 2013 2122 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class SatDataRetriever implements IColorMapDataRetrievalCallback {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SatDataRetriever.class);
protected Rectangle datasetBounds;
protected PluginDataObject pdo;
protected String dataset;
protected boolean signed = false;
public SatDataRetriever(PluginDataObject pdo, int level,
Rectangle dataSetBounds, boolean signed) {
this.pdo = pdo;
this.datasetBounds = dataSetBounds;
dataset = DataStoreFactory.createDataSetName(null,
SatelliteRecord.SAT_DATASET_NAME, level);
this.signed = signed;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.data.IDataRetrievalCallback#getData()
*/
@Override
public ColorMapData getColorMapData() {
// TODO: Read scale/offset out of attributes?
Buffer data = null;
Request req = Request.buildSlab(new int[] { this.datasetBounds.x,
this.datasetBounds.y }, new int[] {
this.datasetBounds.x + this.datasetBounds.width,
this.datasetBounds.y + this.datasetBounds.height });
IDataRecord[] dataRecord = null;
try {
dataRecord = DataCubeContainer
.getDataRecord(pdo, req, this.dataset);
if (dataRecord != null && dataRecord.length == 1) {
IDataRecord record = dataRecord[0];
if (record instanceof ByteDataRecord) {
data = ByteBuffer.wrap((byte[]) record.getDataObject());
} else if (record instanceof ShortDataRecord) {
data = ShortBuffer.wrap((short[]) record.getDataObject());
}
}
} catch (VizDataCubeException e) {
statusHandler.handle(Priority.SIGNIFICANT,
"Error retrieving satellite data", e);
}
if (data == null) {
return null;
}
ColorMapDataType dataType = null;
if (data instanceof ByteBuffer) {
dataType = signed ? ColorMapDataType.SIGNED_BYTE
: ColorMapDataType.BYTE;
} else if (data instanceof ShortBuffer) {
dataType = signed ? ColorMapDataType.SHORT
: ColorMapDataType.UNSIGNED_SHORT;
} else {
dataType = ColorMapData.getDataType(data);
}
return new ColorMapData(data, new int[] { datasetBounds.width,
datasetBounds.height }, dataType);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dataset == null) ? 0 : dataset.hashCode());
result = prime * result
+ ((datasetBounds == null) ? 0 : datasetBounds.hashCode());
result = prime * result + ((pdo == null) ? 0 : pdo.hashCode());
result = prime * result + (signed ? 1231 : 1237);
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SatDataRetriever other = (SatDataRetriever) obj;
if (dataset == null) {
if (other.dataset != null)
return false;
} else if (!dataset.equals(other.dataset))
return false;
if (datasetBounds == null) {
if (other.datasetBounds != null)
return false;
} else if (!datasetBounds.equals(other.datasetBounds))
return false;
if (pdo == null) {
if (other.pdo != null)
return false;
} else if (!pdo.equals(other.pdo))
return false;
if (signed != other.signed)
return false;
return true;
}
}

View file

@ -0,0 +1,82 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.satellite.tileset;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.core.tile.RecordTileSetRenderable;
import com.raytheon.uf.viz.core.tile.Tile;
/**
* Satellite tile set renderable, uses {@link SatDataRetriever} for {@link Tile}
* data retrieval
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 19, 2013 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class SatTileSetRenderable extends RecordTileSetRenderable {
private final boolean signed;
private final AbstractVizResource<?,?> resource;
/**
* Create satellite tile set renderable
*
* @param resource
* @param record
* @param signed
*/
public SatTileSetRenderable(AbstractVizResource<?,?> resource, SatelliteRecord record) {
// Total levels = Number of interpolation levels + base level
super(resource, record, record.getSpatialObject(), record
.getInterpolationLevels() + 1);
this.resource = resource;
// TODO: Better way of determining this (taken from SatFileBasedTileSet)
this.signed = resource.getCapability(ColorMapCapability.class)
.getColorMapParameters().getDataUnit() instanceof GenericPixel;
}
@Override
protected ColorMapData retrieveRecordData(Tile tile) {
ColorMapData data = new SatDataRetriever(record, tile.tileLevel,
tile.getRectangle(), signed).getColorMapData();
resource.issueRefresh();
return data;
}
public SatelliteRecord getSatelliteRecord() {
return (SatelliteRecord) record;
}
}

View file

@ -29,5 +29,6 @@ insert into awips.satellite_units values (27,'SounderCloudTopHeightPixel');
insert into awips.satellite_units values (28,'SounderCloudAmountPixel');
insert into awips.satellite_units values (29,'RainfallRatePixel');
insert into awips.satellite_units values (43,'IRPixel');
insert into awips.satellite_units values (48,'IRPixel');
insert into awips.satellite_units values (60,'PercentOfNormalTPWPixel');
insert into awips.satellite_units values (64,'IRPixel');

View file

@ -97,7 +97,7 @@ public class ColorMapData {
return dataType;
}
private static ColorMapData.ColorMapDataType getDataType(Buffer buffer) {
public static ColorMapData.ColorMapDataType getDataType(Buffer buffer) {
if (buffer instanceof FloatBuffer) {
return ColorMapData.ColorMapDataType.FLOAT;
} else if (buffer instanceof IntBuffer) {

View file

@ -24,6 +24,7 @@ import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Length;
import javax.measure.quantity.Temperature;
import javax.measure.quantity.Velocity;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
@ -49,6 +50,7 @@ import com.raytheon.uf.common.dataplugin.satellite.units.water.RainfallRatePixel
* Sep 4, 2007 njensen Initial creation
* Mar 23, 2009 2086 jsanchez Updated RainfallRatePixel to be velocity.
* Added PolarPrecipWaterPixel.
* Jun 20, 2013 2122 mschenke Added alias for degrees celsius to "C"
*
* </pre>
*
@ -83,8 +85,8 @@ public class SatelliteUnits {
public static final Unit<Dimensionless> GENERIC_PIXEL = new GenericPixel();
public static void register() {
UnitFormat.getUCUMInstance().alias(SI.CELSIUS, "C");
UnitFormat.getUCUMInstance().label(SatelliteUnits.IR_PIXEL, "IRPixel");
UnitFormat.getUCUMInstance().label(SatelliteUnits.PRECIP_PIXEL,
"PrecipPixel");
UnitFormat.getUCUMInstance().label(SatelliteUnits.RAINFALL_RATE_PIXEL,