Issue #28 Implemented generic true color resource with new extension. Wrote new, more efficient, accurate, and scalable TileSet rendering/managing code to replace AbstractTileSet which VIIRS uses since it took over 10s to load a single frame of data with AbstractTileSet and around 20-30s to load a single true color frame of VIIRS. Put true color code in separate projects to encapsulate functionality. Resources need not depend on these projects, they just have to set the ImagingProvider in their ImagingCapability and true color resource can be loaded through a bundle file.
Change-Id: I624edb115b02611470e2e434e27759c45600111c Former-commit-id: 7d75620c07c992ab74a8305a69ed87817f8f0639
This commit is contained in:
parent
603a9c90e4
commit
93e8619fa5
35 changed files with 2751 additions and 7 deletions
|
@ -200,4 +200,16 @@
|
|||
install-size="0"
|
||||
version="0.0.0"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.viz.truecolor"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.viz.truecolor.gl"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"/>
|
||||
|
||||
</feature>
|
||||
|
|
|
@ -30,7 +30,8 @@ Require-Bundle: org.eclipse.ui,
|
|||
com.raytheon.uf.common.dataplugin,
|
||||
com.raytheon.uf.common.dataplugin.level,
|
||||
com.raytheon.uf.common.dataquery;visibility:=reexport,
|
||||
com.raytheon.uf.viz.application;bundle-version="1.0.0"
|
||||
com.raytheon.uf.viz.application;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174"
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Eclipse-BuddyPolicy: ext, registered, global
|
||||
Eclipse-RegisterBuddy: org.apache.velocity, com.raytheon.edex.common, com.raytheon.uf.common.serialization, com.raytheon.uf.common.serialization.comm, com.raytheon.uf.common.status, com.raytheon.uf.common.dataplugin.level
|
||||
|
@ -72,6 +73,7 @@ Export-Package: com.raytheon.uf.viz.core,
|
|||
com.raytheon.uf.viz.core.status,
|
||||
com.raytheon.uf.viz.core.style,
|
||||
com.raytheon.uf.viz.core.style.level,
|
||||
com.raytheon.uf.viz.core.tile,
|
||||
com.raytheon.uf.viz.core.time,
|
||||
com.raytheon.uf.viz.core.topo,
|
||||
com.raytheon.uf.viz.core.velocity,
|
||||
|
@ -87,7 +89,6 @@ Import-Package: com.raytheon.edex.colormap,
|
|||
com.raytheon.uf.common.comm,
|
||||
com.raytheon.uf.common.datastorage,
|
||||
com.raytheon.uf.common.datastorage.records,
|
||||
com.raytheon.uf.common.geospatial,
|
||||
com.raytheon.uf.common.message,
|
||||
com.raytheon.uf.common.message.response,
|
||||
com.raytheon.uf.common.pointdata,
|
||||
|
|
|
@ -74,6 +74,11 @@ public class PixelCoverage {
|
|||
new Coordinate(center.x - width / 2, center.y + height / 2));
|
||||
}
|
||||
|
||||
public PixelCoverage(IMesh mesh) {
|
||||
this(new Coordinate(0, 0), 0, 0);
|
||||
this.mesh = mesh;
|
||||
}
|
||||
|
||||
public Coordinate getLl() {
|
||||
return ll;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.core.drawables.ext;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension.IGraphicsExtensionInterface;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
@ -43,6 +46,11 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
|
||||
public interface IImagingExtension extends IGraphicsExtensionInterface {
|
||||
|
||||
public static interface ImageProvider {
|
||||
public Collection<DrawableImage> getImages(IGraphicsTarget target,
|
||||
PaintProperties paintProps) throws VizException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the images passed in
|
||||
*
|
||||
|
|
|
@ -23,6 +23,8 @@ import javax.xml.bind.annotation.XmlAccessType;
|
|||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension.ImageProvider;
|
||||
|
||||
/**
|
||||
* Capability for imaging features
|
||||
*
|
||||
|
@ -42,6 +44,8 @@ import javax.xml.bind.annotation.XmlAttribute;
|
|||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class ImagingCapability extends AbstractCapability {
|
||||
|
||||
private ImageProvider provider;
|
||||
|
||||
@XmlAttribute
|
||||
private float contrast = 1.0f;
|
||||
|
||||
|
@ -144,9 +148,25 @@ public class ImagingCapability extends AbstractCapability {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the provider
|
||||
*/
|
||||
public ImageProvider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param provider
|
||||
* the provider to set
|
||||
*/
|
||||
public void setProvider(ImageProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractCapability clone() {
|
||||
ImagingCapability ic = new ImagingCapability();
|
||||
ic.provider = provider;
|
||||
ic.contrast = contrast;
|
||||
ic.brightness = brightness;
|
||||
ic.interpolationState = interpolationState;
|
||||
|
|
|
@ -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.uf.viz.core.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
* Object that represents a single Tile. Contains a level and GridGeometry as
|
||||
* well as a border which is used in {@link #intersects(Geometry)}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class Tile {
|
||||
|
||||
public final int tileLevel;
|
||||
|
||||
public final GridGeometry2D tileGeometry;
|
||||
|
||||
public final List<PreparedGeometry> tileBorder;
|
||||
|
||||
/**
|
||||
* Create a Tile specifying a border for intersection checks
|
||||
*
|
||||
* @param tileLevel
|
||||
* @param tileGeometry
|
||||
* @param tileBorder
|
||||
*/
|
||||
public Tile(int tileLevel, GridGeometry2D tileGeometry, Geometry tileBorder) {
|
||||
this.tileLevel = tileLevel;
|
||||
this.tileGeometry = tileGeometry;
|
||||
if (tileBorder != null) {
|
||||
int num = tileBorder.getNumGeometries();
|
||||
this.tileBorder = new ArrayList<PreparedGeometry>(num);
|
||||
for (int n = 0; n < num; ++n) {
|
||||
this.tileBorder.add(PreparedGeometryFactory.prepare(tileBorder
|
||||
.getGeometryN(n)));
|
||||
}
|
||||
} else {
|
||||
this.tileBorder = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Tile with no border. intersects calls will always return true
|
||||
*
|
||||
* @param tileLevel
|
||||
* @param tileGeometry
|
||||
*/
|
||||
public Tile(int tileLevel, GridGeometry2D tileGeometry) {
|
||||
this(tileLevel, tileGeometry, null);
|
||||
}
|
||||
|
||||
public Rectangle getRectangle() {
|
||||
GridEnvelope env = tileGeometry.getGridRange();
|
||||
return new Rectangle(env.getLow(0), env.getLow(1), env.getSpan(0),
|
||||
env.getSpan(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the geometry intersects the Tile. Tiles without a
|
||||
* {@link #tileBorder} will always return true
|
||||
*
|
||||
* @param geometry
|
||||
* @return
|
||||
*/
|
||||
public boolean intersects(Geometry geometry) {
|
||||
if (tileBorder == null) {
|
||||
return true;
|
||||
}
|
||||
for (PreparedGeometry border : tileBorder) {
|
||||
if (border.intersects(geometry)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the x/y coordinate is contained by the Tile's CRS
|
||||
* Envelope
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(double x, double y) {
|
||||
Envelope env = tileGeometry.getEnvelope();
|
||||
return env.getMinimum(0) <= x && env.getMaximum(0) >= x
|
||||
&& env.getMinimum(1) <= y && env.getMaximum(1) >= y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the Coordinate is contained by the Tile's CRS Envelope
|
||||
*
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(Coordinate c) {
|
||||
return contains(c.x, c.y);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((tileGeometry == null) ? 0 : tileGeometry.hashCode());
|
||||
result = prime * result + tileLevel;
|
||||
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;
|
||||
Tile other = (Tile) obj;
|
||||
if (tileGeometry == null) {
|
||||
if (other.tileGeometry != null)
|
||||
return false;
|
||||
} else if (!tileGeometry.equals(other.tileGeometry))
|
||||
return false;
|
||||
if (tileLevel != other.tileLevel)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,415 @@
|
|||
/**
|
||||
* 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridEnvelope;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.geotools.geometry.jts.JTS;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.CRSCache;
|
||||
import com.raytheon.uf.common.geospatial.util.WorldWrapCorrector;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* This object represents a single tile level. It does this by containing a 2
|
||||
* dimensional array of {@link Tile} objects.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TileLevel {
|
||||
|
||||
/** Tile level's GridGeometry */
|
||||
private GridGeometry2D levelGeometry;
|
||||
|
||||
/** GridGeometry tile level was created for */
|
||||
private GeneralGridGeometry targetGeometry;
|
||||
|
||||
// Cached MathTransforms
|
||||
private MathTransform crsToGrid;
|
||||
|
||||
private MathTransform gridToCRS;
|
||||
|
||||
private MathTransform tileCRSToTargetGrid;
|
||||
|
||||
/** Target grid to lat/lon for world wrap correcting */
|
||||
private MathTransform targetGridToLatLon;
|
||||
|
||||
/** World wrap corrector, corrects Tile borders */
|
||||
private WorldWrapCorrector corrector;
|
||||
|
||||
/** Level of this TileLevel */
|
||||
private int tileLevel;
|
||||
|
||||
/** size for tiles in this level */
|
||||
private int tileSize;
|
||||
|
||||
/** Pixel density of the tile level */
|
||||
private double pixelDensity;
|
||||
|
||||
/** Tile array */
|
||||
private Tile[][] tiles;
|
||||
|
||||
TileLevel(GridGeometry2D levelGeometry, GeneralGridGeometry targetGeometry,
|
||||
int tileLevel, int tileSize) {
|
||||
this.levelGeometry = levelGeometry;
|
||||
this.targetGeometry = targetGeometry;
|
||||
this.tileLevel = tileLevel;
|
||||
this.tileSize = tileSize;
|
||||
intialize(levelGeometry.getGridRange(), levelGeometry.getEnvelope());
|
||||
}
|
||||
|
||||
private void intialize(GridEnvelope range, Envelope envelope) {
|
||||
int width = range.getSpan(0);
|
||||
int height = range.getSpan(1);
|
||||
int fullTileDimX = width / tileSize;
|
||||
int tileRemainderX = width % tileSize;
|
||||
int fullTileDimY = height / tileSize;
|
||||
int tileRemainderY = height % tileSize;
|
||||
|
||||
int totalTilesX = fullTileDimX;
|
||||
if (tileRemainderX > 0) {
|
||||
totalTilesX++;
|
||||
}
|
||||
|
||||
int totalTilesY = fullTileDimY;
|
||||
if (tileRemainderY > 0) {
|
||||
totalTilesY++;
|
||||
}
|
||||
|
||||
tiles = new Tile[totalTilesY][totalTilesX];
|
||||
|
||||
try {
|
||||
gridToCRS = levelGeometry.getGridToCRS(PixelInCell.CELL_CORNER);
|
||||
crsToGrid = gridToCRS.inverse();
|
||||
|
||||
DefaultMathTransformFactory factory = new DefaultMathTransformFactory();
|
||||
tileCRSToTargetGrid = factory.createConcatenatedTransform(
|
||||
CRSCache.getInstance().findMathTransform(
|
||||
levelGeometry.getCoordinateReferenceSystem(),
|
||||
targetGeometry.getCoordinateReferenceSystem()),
|
||||
targetGeometry.getGridToCRS(PixelInCell.CELL_CORNER)
|
||||
.inverse());
|
||||
targetGridToLatLon = factory.createConcatenatedTransform(
|
||||
targetGeometry.getGridToCRS(PixelInCell.CELL_CORNER),
|
||||
CRSCache.getInstance().findMathTransform(
|
||||
targetGeometry.getCoordinateReferenceSystem(),
|
||||
DefaultGeographicCRS.WGS84));
|
||||
corrector = new WorldWrapCorrector(targetGeometry);
|
||||
|
||||
// Calculate pixel density
|
||||
// Grab the center x, 3/4 y of the map
|
||||
double mapXCenter = targetGeometry.getGridRange().getSpan(0) * 0.5;
|
||||
double mapYCenter = targetGeometry.getGridRange().getSpan(1) * 0.75;
|
||||
|
||||
double[] input = new double[] { mapXCenter, mapYCenter,
|
||||
mapXCenter + 1, mapYCenter + 1 };
|
||||
double[] output = new double[input.length];
|
||||
|
||||
tileCRSToTargetGrid.inverse().transform(input, 0, output, 0, 2);
|
||||
levelGeometry.getGridToCRS(PixelInCell.CELL_CORNER).inverse()
|
||||
.transform(output, 0, input, 0, 2);
|
||||
pixelDensity = 1.0 / Math.abs(new Coordinate(input[0], input[1],
|
||||
0.0).distance(new Coordinate(input[2], input[3], 0.0)));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Cannot tranform tile CRS into target CRS", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pixel density for the tile level. This is the approximate
|
||||
* number of target grid pixels a single tile grid pixel takes up
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getPixelDensity() {
|
||||
return pixelDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of tiles in the x direction (number of columns)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNumXTiles() {
|
||||
return tiles[0].length;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of tiles in the y direction (number of rows)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNumYTiles() {
|
||||
return tiles.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Level of this TileLevel
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLevel() {
|
||||
return tileLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Tile at the specified x/y index in the tile set
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public Tile getTile(int x, int y) {
|
||||
Tile tile = tiles[y][x];
|
||||
if (tile == null) {
|
||||
synchronized (tiles) {
|
||||
// Double check tile to see if another thread created it
|
||||
tile = tiles[y][x];
|
||||
if (tile == null) {
|
||||
tiles[y][x] = tile = createTile(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Tile for the specified tile grid location
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public Tile getTile(double x, double y) {
|
||||
int xIdx = (int) x / tileSize;
|
||||
int yIdx = (int) y / tileSize;
|
||||
if (xIdx >= 0 && yIdx >= 0 && xIdx < getNumXTiles()
|
||||
&& yIdx < getNumYTiles()) {
|
||||
return tiles[yIdx][xIdx];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms TileLevel crs x,y into tile level grid space x,y
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public double[] crsToGrid(double x, double y) throws TransformException {
|
||||
double[] out = new double[2];
|
||||
crsToGrid.transform(new double[] { x, y }, 0, out, 0, 1);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Tile for the specified x/y {@link #tiles} index
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
private Tile createTile(int x, int y) {
|
||||
GridEnvelope range = levelGeometry.getGridRange();
|
||||
// Get grid range ranges and calculate grid range for the tile
|
||||
int startX = range.getLow(0);
|
||||
int startY = range.getLow(1);
|
||||
int endX = range.getHigh(0) + 1;
|
||||
int endY = range.getHigh(1) + 1;
|
||||
|
||||
int tileY = startY + y * tileSize;
|
||||
int tileX = startX + x * tileSize;
|
||||
|
||||
int tileEndX = Math.min(endX, tileX + tileSize);
|
||||
int tileEndY = Math.min(endY, tileY + tileSize);
|
||||
|
||||
// Convert grid range into crs envelope range
|
||||
double[] in = new double[] { tileX, tileY, tileEndX, tileEndY };
|
||||
double[] out = new double[in.length];
|
||||
try {
|
||||
gridToCRS.transform(in, 0, out, 0, 2);
|
||||
} catch (TransformException e) {
|
||||
throw new RuntimeException("Error getting tile envelope from grid",
|
||||
e);
|
||||
}
|
||||
double envTileX = out[0];
|
||||
double envTileY = out[1];
|
||||
double envTileEndX = out[2];
|
||||
double envTileEndY = out[3];
|
||||
|
||||
// Create tile GridGeometry
|
||||
range = new GeneralGridEnvelope(new int[] { tileX, tileY }, new int[] {
|
||||
tileEndX, tileEndY }, false);
|
||||
GridGeometry2D tileGridGeom = new GridGeometry2D(range, new Envelope2D(
|
||||
levelGeometry.getCoordinateReferenceSystem(), out[0], envTileY,
|
||||
envTileEndX - envTileX, envTileEndY - envTileY));
|
||||
|
||||
// Calculate the border in target grid space for the Tile
|
||||
Geometry border = null;
|
||||
try {
|
||||
double[] UL = new double[] { envTileX, envTileY };
|
||||
double[] UR = new double[] { envTileEndX, envTileY };
|
||||
double[] LR = new double[] { envTileEndX, envTileEndY };
|
||||
double[] LL = new double[] { envTileX, envTileEndY };
|
||||
|
||||
// Create tile border based on pixel density tile level 0 should
|
||||
// always have threshold of 1.0
|
||||
border = createTileBorder(UL, UR, LR, LL,
|
||||
Math.max(range.getSpan(0) / 4, 1),
|
||||
Math.max(range.getSpan(1) / 4, 1),
|
||||
tileLevel > 0 ? Math.max(pixelDensity, 1.0) : 1.0);
|
||||
} catch (TransformException e) {
|
||||
// Invalid geometry, don't add a border
|
||||
}
|
||||
|
||||
// Create the Tile object
|
||||
return new Tile(tileLevel, tileGridGeom, border);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures all Tile objects are created for the level. This method can takes
|
||||
* lots of time depending on grid resolution of level and {@link #tileSize}.
|
||||
* Tiles are created dynamically as requested otherwise
|
||||
*/
|
||||
public void populateTiles() {
|
||||
int totalTilesY = getNumYTiles();
|
||||
int totalTilesX = getNumXTiles();
|
||||
for (int y = 0; y < totalTilesY; ++y) {
|
||||
for (int x = 0; x < totalTilesX; ++x) {
|
||||
if (tiles[y][x] == null) {
|
||||
tiles[y][x] = createTile(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Geometry createTileBorder(double[] UL, double[] UR, double[] LR,
|
||||
double[] LL, int maxHorDivisions, int maxVertDivisions,
|
||||
double threshold) throws TransformException {
|
||||
List<Coordinate> borderPoints = new ArrayList<Coordinate>(
|
||||
maxVertDivisions * 2 + maxHorDivisions * 2);
|
||||
double[] out = new double[2];
|
||||
|
||||
// UL to UR
|
||||
tileCRSToTargetGrid.transform(UL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, UL, null, UR, null, maxHorDivisions,
|
||||
threshold);
|
||||
|
||||
// UR to LR
|
||||
tileCRSToTargetGrid.transform(UR, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, UR, null, LR, null, maxVertDivisions, 1.0);
|
||||
|
||||
// LR to LL
|
||||
tileCRSToTargetGrid.transform(LR, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, LR, null, LL, null, maxHorDivisions, 1.0);
|
||||
|
||||
// LL to UL
|
||||
tileCRSToTargetGrid.transform(LL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, LL, null, UL, null, maxVertDivisions, 1.0);
|
||||
|
||||
// Add start point to complete linear ring
|
||||
tileCRSToTargetGrid.transform(UL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
|
||||
// Create Geometry and world wrap correct (need to be in lat/lon)
|
||||
return JTS.transform(corrector.correct(JTS.transform(TileSet.gf
|
||||
.createPolygon(TileSet.gf.createLinearRing(borderPoints
|
||||
.toArray(new Coordinate[borderPoints.size()])), null),
|
||||
targetGridToLatLon)), targetGridToLatLon.inverse());
|
||||
}
|
||||
|
||||
private int calculateBorder(List<Coordinate> borderList, double[] point1,
|
||||
double[] transformedPoint1, double[] point3,
|
||||
double[] transformedPoint3, double maxNumDivs, double threshold)
|
||||
throws TransformException {
|
||||
if (transformedPoint1 == null) {
|
||||
transformedPoint1 = new double[point1.length];
|
||||
tileCRSToTargetGrid.transform(point1, 0, transformedPoint1, 0, 1);
|
||||
}
|
||||
if (transformedPoint3 == null) {
|
||||
transformedPoint3 = new double[point3.length];
|
||||
tileCRSToTargetGrid.transform(point3, 0, transformedPoint3, 0, 1);
|
||||
}
|
||||
if (transformedPoint1 == null || transformedPoint3 == null) {
|
||||
// if the image has some points outside the valid range of the
|
||||
// screen then give up optimizing and assume the max number of
|
||||
// points.
|
||||
return (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
double[] point2 = { (point1[0] + point3[0]) / 2,
|
||||
(point1[1] + point3[1]) / 2 };
|
||||
double[] transformedPoint2 = new double[point2.length];
|
||||
tileCRSToTargetGrid.transform(point2, 0, transformedPoint2, 0, 1);
|
||||
double[] interp2 = { (transformedPoint1[0] + transformedPoint3[0]) / 2,
|
||||
(transformedPoint1[1] + transformedPoint3[1]) / 2 };
|
||||
double dX = transformedPoint2[0] - interp2[0];
|
||||
double dY = transformedPoint2[1] - interp2[1];
|
||||
double d = Math.hypot(dX, dY);
|
||||
if (d < threshold || maxNumDivs < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
int nd1 = calculateBorder(borderList, point1, transformedPoint1,
|
||||
point2, transformedPoint2, maxNumDivs / 2, threshold);
|
||||
borderList.add(new Coordinate(transformedPoint2[0],
|
||||
transformedPoint2[1]));
|
||||
if (nd1 * 2 >= maxNumDivs) {
|
||||
nd1 = (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
int nd2 = calculateBorder(borderList, point2, transformedPoint2,
|
||||
point3, transformedPoint3, maxNumDivs / 2, threshold);
|
||||
if (nd2 * 2 >= maxNumDivs) {
|
||||
nd2 = (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
return (Math.max(nd1, nd2) * 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/**
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.keyvalue.MultiKey;
|
||||
import org.geotools.coverage.grid.GeneralGridEnvelope;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
|
||||
/**
|
||||
* A TileSet is an object that consists of multiple tile levels. Each tile level
|
||||
* is represented by a {@link TileLevel} object. These objects are only accessed
|
||||
* via static funtion
|
||||
* {@link #getTileSet(GridGeometry2D, GeneralGridGeometry, int, int)} to ensure
|
||||
* tile set sharing. When a TileSet is no longer needed, dispose must be called
|
||||
* on it to make sure it is cleaned up
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TileSet {
|
||||
|
||||
/** Each tile level is LEVEL_FACTOR much smaller than the previous level */
|
||||
private static final int LEVEL_FACTOR = 2;
|
||||
|
||||
static final GeometryFactory gf = new GeometryFactory();
|
||||
|
||||
/** Static cache for TileSets */
|
||||
private static Map<MultiKey, TileSet> tileSetCache = new HashMap<MultiKey, TileSet>();
|
||||
|
||||
/**
|
||||
* Creates a {@link TileSet} object with the specified tile size and levels
|
||||
*
|
||||
* @param tileSetGeometry
|
||||
* @param targetGeometry
|
||||
* @param levels
|
||||
* @param tileSize
|
||||
* @return
|
||||
*/
|
||||
public static TileSet getTileSet(GridGeometry2D tileSetGeometry,
|
||||
GeneralGridGeometry targetGeometry, int levels, int tileSize) {
|
||||
synchronized (TileSet.class) {
|
||||
MultiKey key = new MultiKey(tileSetGeometry, targetGeometry,
|
||||
levels, tileSize);
|
||||
TileSet tileSet = tileSetCache.get(key);
|
||||
if (tileSet == null) {
|
||||
// No tileset for key, create one
|
||||
tileSet = new TileSet(tileSetGeometry, targetGeometry, levels,
|
||||
tileSize, key);
|
||||
tileSetCache.put(key, tileSet);
|
||||
}
|
||||
++tileSet.refCount;
|
||||
return tileSet;
|
||||
}
|
||||
}
|
||||
|
||||
/** GridGeometry tileSet is created for */
|
||||
private GeneralGridGeometry targetGeometry;
|
||||
|
||||
/** {@link TileLevel} array, one per tile level */
|
||||
private TileLevel[] tileLevels;
|
||||
|
||||
private int tileSize;
|
||||
|
||||
private int refCount = 0;
|
||||
|
||||
private MultiKey cacheKey;
|
||||
|
||||
private TileSet(GridGeometry2D tileSetGeometry,
|
||||
GeneralGridGeometry targetGeometry, int levels, int tileSize,
|
||||
MultiKey cacheKey) {
|
||||
this.targetGeometry = targetGeometry;
|
||||
this.tileSize = tileSize;
|
||||
this.cacheKey = cacheKey;
|
||||
initialize(tileSetGeometry, levels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tileSetGeometry
|
||||
* @param levels
|
||||
*/
|
||||
private void initialize(GridGeometry2D tileSetGeometry, int levels) {
|
||||
Envelope envelope = tileSetGeometry.getEnvelope();
|
||||
GridEnvelope range = tileSetGeometry.getGridRange();
|
||||
int startX = range.getLow(0);
|
||||
int startY = range.getLow(1);
|
||||
int width = range.getSpan(0);
|
||||
int height = range.getSpan(1);
|
||||
|
||||
tileLevels = new TileLevel[levels];
|
||||
for (int i = 0; i < levels; ++i) {
|
||||
if (i > 0) {
|
||||
startX /= LEVEL_FACTOR;
|
||||
startY /= LEVEL_FACTOR;
|
||||
width /= LEVEL_FACTOR;
|
||||
height /= LEVEL_FACTOR;
|
||||
tileSetGeometry = new GridGeometry2D(new GeneralGridEnvelope(
|
||||
new int[] { startX, startY },
|
||||
new int[] { width, height }, false), envelope);
|
||||
}
|
||||
tileLevels[i] = new TileLevel(tileSetGeometry, targetGeometry, i,
|
||||
tileSize);
|
||||
}
|
||||
|
||||
// Fully populate lowest resolution tile level
|
||||
tileLevels[tileLevels.length - 1].populateTiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the TileSet, needs to be called when tile set is no longer
|
||||
* needed
|
||||
*/
|
||||
public void dispose() {
|
||||
synchronized (TileSet.class) {
|
||||
--refCount;
|
||||
if (refCount == 0) {
|
||||
tileSetCache.remove(cacheKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TileLevel} object for the specified level. Lower level
|
||||
* = higher resolution
|
||||
*
|
||||
* @param level
|
||||
* @return
|
||||
*/
|
||||
public TileLevel getTileLevel(int level) {
|
||||
return tileLevels[level];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all intersecting tiles in the level for the given extent. Lower
|
||||
* tile level = higher resolution with 0 being the highest
|
||||
*
|
||||
* @param level
|
||||
* level to get tiles at
|
||||
* @param extent
|
||||
* area requesting tiles at in targetGeometry space
|
||||
* @return
|
||||
*/
|
||||
public Collection<Tile> getIntersectingTiles(int level, IExtent extent) {
|
||||
// Start with level 0 and work way up to requested level
|
||||
Geometry extentGeom = gf.createPolygon(
|
||||
gf.createLinearRing(new Coordinate[] {
|
||||
new Coordinate(extent.getMinX(), extent.getMinY()),
|
||||
new Coordinate(extent.getMaxX(), extent.getMinY()),
|
||||
new Coordinate(extent.getMaxX(), extent.getMaxY()),
|
||||
new Coordinate(extent.getMinX(), extent.getMaxY()),
|
||||
new Coordinate(extent.getMinX(), extent.getMinY()) }),
|
||||
null);
|
||||
TileLevel tileLevel = getTileLevel(tileLevels.length - 1);
|
||||
return getIntersectingTiles(tileLevel, level, 0, 0,
|
||||
tileLevel.getNumXTiles(), tileLevel.getNumYTiles(), extentGeom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns intersecting tiles for the desired level. Recursive function that
|
||||
* checks intersection by looking at previous tile level tiles
|
||||
*
|
||||
* @param tileLevel
|
||||
* @param level
|
||||
* @param startX
|
||||
* @param startY
|
||||
* @param endX
|
||||
* @param endY
|
||||
* @param extent
|
||||
* @return
|
||||
*/
|
||||
private Collection<Tile> getIntersectingTiles(TileLevel tileLevel,
|
||||
int level, int startX, int startY, int endX, int endY,
|
||||
Geometry extent) {
|
||||
TileLevel nextTileLevel = null;
|
||||
if (tileLevel.getLevel() != level) {
|
||||
// If we are not at desired level, get next tile level
|
||||
nextTileLevel = getTileLevel(tileLevel.getLevel() - 1);
|
||||
}
|
||||
List<Tile> intersecting = new ArrayList<Tile>();
|
||||
for (int y = startY; y < endY; ++y) {
|
||||
for (int x = startX; x < endX; ++x) {
|
||||
Tile tile = tileLevel.getTile(x, y);
|
||||
if (tile.intersects(extent)) {
|
||||
if (nextTileLevel != null) {
|
||||
// nextTileLevel is not null meaning we are not at
|
||||
// desired level. Calculate index into next tile level
|
||||
// and call recursively
|
||||
int nextStartX = x * LEVEL_FACTOR;
|
||||
int nextStartY = y * LEVEL_FACTOR;
|
||||
int nextEndX = Math.min(nextStartX + LEVEL_FACTOR,
|
||||
nextTileLevel.getNumXTiles());
|
||||
int nextEndY = Math.min(nextStartY + LEVEL_FACTOR,
|
||||
nextTileLevel.getNumYTiles());
|
||||
intersecting.addAll(getIntersectingTiles(nextTileLevel,
|
||||
level, nextStartX, nextStartY, nextEndX,
|
||||
nextEndY, extent));
|
||||
} else if (tile.tileBorder != null) {
|
||||
// This is desired tile level, add to list if we
|
||||
// actually have a valid border that intersects
|
||||
intersecting.add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return intersecting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GridGeometry the tileSet is created for
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GeneralGridGeometry getTargetGeometry() {
|
||||
return targetGeometry;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,461 @@
|
|||
/**
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.CRSCache;
|
||||
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.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.IMesh;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage.Status;
|
||||
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.jobs.JobPool;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Renderable tile set class that creates a {@link TileSet} and renders images
|
||||
* for tiles displayed using the {@link TileImageCreator} passed in at
|
||||
* construction
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TileSetRenderable implements IRenderable {
|
||||
|
||||
public static interface TileImageCreator {
|
||||
|
||||
/**
|
||||
* Create a complete DrawableImage for the given tile on the
|
||||
* targetGeometry
|
||||
*/
|
||||
public DrawableImage createTileImage(IGraphicsTarget target, Tile tile,
|
||||
GeneralGridGeometry targetGeometry) throws VizException;
|
||||
|
||||
}
|
||||
|
||||
private class TileImageCreatorTask implements Runnable {
|
||||
|
||||
private IGraphicsTarget target;
|
||||
|
||||
private Tile tile;
|
||||
|
||||
private TileImageCreatorTask(IGraphicsTarget target, Tile tile) {
|
||||
this.target = target;
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DrawableImage di = tileCreator.createTileImage(target, tile,
|
||||
tileSet.getTargetGeometry());
|
||||
if (di != null) {
|
||||
di.getImage().stage();
|
||||
}
|
||||
addTileImage(tile, di);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(TileSetRenderable.class);
|
||||
|
||||
/** Screen pixel to image pixel threshold at which we change levels */
|
||||
protected static final double LEVEL_CHANGE_THRESHOLD = 2.0;
|
||||
|
||||
/** Job pool for tile creation */
|
||||
protected static final JobPool tileCreationPool = new JobPool(
|
||||
"Creating Image Tiles", 10, false);
|
||||
|
||||
/** Job map, should only have one job running per tile at a time */
|
||||
protected Map<Tile, Runnable> jobMap = new ConcurrentHashMap<Tile, Runnable>();
|
||||
|
||||
/** Image map for tiles */
|
||||
protected Map<Tile, DrawableImage> imageMap = new HashMap<Tile, DrawableImage>();
|
||||
|
||||
/** Full resolution tile set GridGeometry2D */
|
||||
protected final GridGeometry2D tileSetGeometry;
|
||||
|
||||
protected final TileImageCreator tileCreator;
|
||||
|
||||
/** Desired size for each tile */
|
||||
protected final int tileSize;
|
||||
|
||||
/** Number of tile levels to create */
|
||||
protected final int tileLevels;
|
||||
|
||||
/** {@link TileSet} object, manages tiles */
|
||||
protected TileSet tileSet;
|
||||
|
||||
/** Transform for tileset CRS to lat/lon */
|
||||
protected final MathTransform localProjToLL;
|
||||
|
||||
/** Transform for lat/lon to tileset CRS */
|
||||
protected final MathTransform llToLocalProj;
|
||||
|
||||
/** Stored imaging capability */
|
||||
protected final ImagingCapability imaging;
|
||||
|
||||
/** Last painted tile level, used for interrogating proper level */
|
||||
protected int lastPaintedLevel;
|
||||
|
||||
/** The ratio of target grid pixels / image pixel for each tile level */
|
||||
protected double[] pixelWidth;
|
||||
|
||||
/**
|
||||
* Constructs a tile set renderable, creators needs to call
|
||||
* {@link #project(GeneralGridGeometry)} before the renderable can be used
|
||||
*
|
||||
* @param resource
|
||||
* @param tileSetGeometry
|
||||
* @param tileCreator
|
||||
* @param tileLevels
|
||||
* @param tileSize
|
||||
*/
|
||||
public TileSetRenderable(ImagingCapability imaging,
|
||||
GridGeometry2D tileSetGeometry, TileImageCreator tileCreator,
|
||||
int tileLevels, int tileSize) {
|
||||
this.tileSetGeometry = tileSetGeometry;
|
||||
this.tileCreator = tileCreator;
|
||||
this.tileLevels = tileLevels;
|
||||
this.tileSize = tileSize;
|
||||
this.pixelWidth = new double[tileLevels];
|
||||
this.imaging = imaging;
|
||||
|
||||
try {
|
||||
// Set lat/lon math transforms for tile set
|
||||
llToLocalProj = CRSCache.getInstance().findMathTransform(
|
||||
DefaultGeographicCRS.WGS84,
|
||||
tileSetGeometry.getCoordinateReferenceSystem());
|
||||
localProjToLL = llToLocalProj.inverse();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not get tranform from tile crs to lat/lon", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects the tile set for use with the target geometry
|
||||
*
|
||||
* @param targetGeometry
|
||||
*/
|
||||
public synchronized void project(GeneralGridGeometry targetGeometry) {
|
||||
// dispose the old TileSet
|
||||
if (tileSet != null) {
|
||||
tileSet.dispose();
|
||||
}
|
||||
// Create TileSet for new target geometry
|
||||
tileSet = TileSet.getTileSet(tileSetGeometry, targetGeometry,
|
||||
tileLevels, tileSize);
|
||||
|
||||
// Clear out meshes and create new ones cloning old ones
|
||||
for (DrawableImage di : imageMap.values()) {
|
||||
if (di != null) {
|
||||
IMesh currentMesh = di.getCoverage().getMesh();
|
||||
if (currentMesh != null) {
|
||||
try {
|
||||
di.getCoverage().setMesh(
|
||||
currentMesh.clone(targetGeometry));
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
currentMesh.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the pixel densities for each tile level. This is approximately
|
||||
// how many target grid pixels per image pixel there are for the level
|
||||
for (int level = 0; level < tileLevels; ++level) {
|
||||
TileLevel tileLevel = tileSet.getTileLevel(level);
|
||||
pixelWidth[level] = tileLevel.getPixelDensity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.IRenderable#paint(com.raytheon.uf.
|
||||
* viz.core.IGraphicsTarget,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void paint(IGraphicsTarget target, PaintProperties paintProps)
|
||||
throws VizException {
|
||||
Collection<DrawableImage> images = getImagesToRender(target, paintProps);
|
||||
target.drawRasters(paintProps,
|
||||
images.toArray(new DrawableImage[images.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the tile set and any data associated with it
|
||||
*/
|
||||
public synchronized void dispose() {
|
||||
// Make sure any lingering jobs are canceled and joined on
|
||||
for (Runnable job : jobMap.values()) {
|
||||
tileCreationPool.cancel(job);
|
||||
}
|
||||
tileCreationPool.join();
|
||||
|
||||
// Dispose the tile set
|
||||
if (tileSet != null) {
|
||||
tileSet.dispose();
|
||||
tileSet = null;
|
||||
}
|
||||
|
||||
// Dispose of all the images for the tile set
|
||||
for (DrawableImage image : imageMap.values()) {
|
||||
if (image != null) {
|
||||
image.dispose();
|
||||
}
|
||||
}
|
||||
imageMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link DrawableImage} list to display for the given target and
|
||||
* paint properties
|
||||
*
|
||||
* @param target
|
||||
* @param paintProps
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public synchronized Collection<DrawableImage> getImagesToRender(
|
||||
IGraphicsTarget target, PaintProperties paintProps)
|
||||
throws VizException {
|
||||
double screenToWorldRatio = paintProps.getCanvasBounds().width
|
||||
/ paintProps.getView().getExtent().getWidth();
|
||||
|
||||
int usedTileLevel = tileLevels - 1;
|
||||
|
||||
/*
|
||||
* pixelRatios[usedTileLevel] * screenToWorldRatio gives us
|
||||
* canvasPixels/image pixel at the level, We should use the level if
|
||||
* there are less than LEVEL_CHANGE_THRESHOLD canvas pixels per image
|
||||
* pixel
|
||||
*/
|
||||
while ((pixelWidth[usedTileLevel] * screenToWorldRatio > LEVEL_CHANGE_THRESHOLD)
|
||||
&& usedTileLevel > 0) {
|
||||
usedTileLevel--;
|
||||
}
|
||||
lastPaintedLevel = usedTileLevel;
|
||||
|
||||
return getImagesWithinExtent(target, paintProps.getView().getExtent(),
|
||||
usedTileLevel, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target
|
||||
* @param paintProps
|
||||
* @param level
|
||||
* @param depth
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
protected List<DrawableImage> getImagesWithinExtent(IGraphicsTarget target,
|
||||
IExtent extent, int level, int depth) throws VizException {
|
||||
if (tileSet == null) {
|
||||
// Early exit condition, disposed or haven't projected yet
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Flag to determine if we should draw lower tile levels. This will be
|
||||
// the case if we don't have all the images for all intersecting tiles
|
||||
// at this level
|
||||
boolean needDrawLower = false;
|
||||
// Get the intersecting tiles for the level
|
||||
Collection<Tile> intersecting = tileSet.getIntersectingTiles(level,
|
||||
extent);
|
||||
|
||||
// These Tiles still need images created for them
|
||||
List<Tile> tilesNeedingImage = new ArrayList<Tile>(intersecting.size());
|
||||
List<DrawableImage> drawableImages = new ArrayList<DrawableImage>(
|
||||
intersecting.size());
|
||||
|
||||
for (Tile tile : intersecting) {
|
||||
// Flag to indicate if a tile needs an image created for it
|
||||
boolean needsImage = false;
|
||||
DrawableImage di = imageMap.get(tile);
|
||||
if (di != null) {
|
||||
IImage image = di.getImage();
|
||||
if (image.getStatus() == Status.FAILED
|
||||
|| image.getStatus() == Status.INVALID) {
|
||||
// Image is invalid, re-request creation
|
||||
needsImage = true;
|
||||
} else {
|
||||
image.setBrightness(imaging.getBrightness());
|
||||
image.setContrast(imaging.getContrast());
|
||||
image.setInterpolated(imaging.isInterpolationState());
|
||||
|
||||
if (image.getStatus() != Status.LOADED) {
|
||||
needDrawLower = true;
|
||||
}
|
||||
drawableImages.add(di);
|
||||
}
|
||||
} else {
|
||||
needsImage = true;
|
||||
}
|
||||
|
||||
if (needsImage) {
|
||||
tilesNeedingImage.add(tile);
|
||||
needDrawLower = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == 0) {
|
||||
// Only request images to be created if we are at the desired level
|
||||
// i.e. the recursion depth is 0
|
||||
if (tilesNeedingImage.isEmpty()) {
|
||||
// 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);
|
||||
}
|
||||
jobMap.clear();
|
||||
} else {
|
||||
// Create tiles needing images
|
||||
createTileImages(target, tilesNeedingImage);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw lower resolution data first
|
||||
if (needDrawLower && (level + 1) < tileLevels) {
|
||||
// put lower levels first in the list so they are drawn first.
|
||||
List<DrawableImage> lowerImages = getImagesWithinExtent(target,
|
||||
extent, level + 1, depth + 1);
|
||||
lowerImages.addAll(drawableImages);
|
||||
drawableImages = lowerImages;
|
||||
}
|
||||
|
||||
return drawableImages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create tile images for the specified tiles
|
||||
*
|
||||
* @param target
|
||||
* @param tilesToCreate
|
||||
*/
|
||||
protected void createTileImages(IGraphicsTarget target,
|
||||
Collection<Tile> tilesToCreate) {
|
||||
for (Tile tile : tilesToCreate) {
|
||||
if (jobMap.get(tile) == null) {
|
||||
// No job already running for tile, create and schedule one
|
||||
TileImageCreatorTask job = new TileImageCreatorTask(target,
|
||||
tile);
|
||||
jobMap.put(tile, job);
|
||||
tileCreationPool.schedule(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DrawableImage for the specified Tile. Disposes of any old image
|
||||
*
|
||||
* @param tile
|
||||
* @param image
|
||||
*/
|
||||
public void addTileImage(Tile tile, DrawableImage image) {
|
||||
DrawableImage oldImage = imageMap.put(tile, image);
|
||||
if (oldImage != null) {
|
||||
oldImage.dispose();
|
||||
}
|
||||
Runnable task = jobMap.remove(tile);
|
||||
if (task != null) {
|
||||
tileCreationPool.cancel(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate) throws VizException {
|
||||
try {
|
||||
double[] local = new double[2];
|
||||
llToLocalProj
|
||||
.transform(new double[] { coordinate.x, coordinate.y }, 0,
|
||||
local, 0, 1);
|
||||
double localX = local[0];
|
||||
double localY = local[1];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
throw new VizException("Error interrogating ", e);
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
7
cave/com.raytheon.uf.viz.truecolor.gl/.classpath
Normal file
7
cave/com.raytheon.uf.viz.truecolor.gl/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
cave/com.raytheon.uf.viz.truecolor.gl/.project
Normal file
28
cave/com.raytheon.uf.viz.truecolor.gl/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.viz.truecolor.gl</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Mon Aug 06 13:10:16 CDT 2012
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
15
cave/com.raytheon.uf.viz.truecolor.gl/META-INF/MANIFEST.MF
Normal file
15
cave/com.raytheon.uf.viz.truecolor.gl/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,15 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: True Color GL
|
||||
Bundle-SymbolicName: com.raytheon.uf.viz.truecolor.gl;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.raytheon.uf.viz.truecolor.gl.Activator
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.viz.truecolor;bundle-version="1.0.0",
|
||||
com.raytheon.viz.core.gl;bundle-version="1.12.1174",
|
||||
javax.media.opengl;bundle-version="1.1.0",
|
||||
com.raytheon.uf.common.util;bundle-version="1.12.1174"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
6
cave/com.raytheon.uf.viz.truecolor.gl/build.properties
Normal file
6
cave/com.raytheon.uf.viz.truecolor.gl/build.properties
Normal file
|
@ -0,0 +1,6 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
localization/,\
|
||||
plugin.xml
|
|
@ -0,0 +1,56 @@
|
|||
#include <colorUtil>
|
||||
#include <indexing>
|
||||
|
||||
uniform sampler2D rawTex;
|
||||
uniform float naturalMin;
|
||||
uniform float naturalMax;
|
||||
uniform float cmapMin;
|
||||
uniform float cmapMax;
|
||||
uniform int isFloat;
|
||||
|
||||
uniform int band;
|
||||
|
||||
uniform sampler2D trueColorTexture;
|
||||
uniform int height;
|
||||
uniform int width;
|
||||
|
||||
float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin, float naturalMax, int isFloat) {
|
||||
vec4 textureValue = texture2D(rawTex, gl_TexCoord[0].st);
|
||||
float naturalVal = textureValue.r;
|
||||
if ( isFloat == 0 ) {
|
||||
naturalVal = ((naturalVal * (naturalMax - naturalMin)) + naturalMin);
|
||||
}
|
||||
float index = findIndex(naturalVal, cmapMin, cmapMax);
|
||||
if (index < 0.0 || index > 1.0) {
|
||||
index = -1.0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 xy = gl_FragCoord.xy;
|
||||
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
|
||||
vec4 curVal = texture2D(trueColorTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
|
||||
|
||||
float r = curVal.r;
|
||||
float g = curVal.g;
|
||||
float b = curVal.b;
|
||||
float a = curVal.a;
|
||||
|
||||
float index = getIndex(rawTex, cmapMin, cmapMax, naturalMin, naturalMax, isFloat);
|
||||
if ( index < 0.0 ) {
|
||||
index = a = 0.0;
|
||||
} else {
|
||||
a = 1.0;
|
||||
}
|
||||
if ( band == 0 && index > r ) {
|
||||
r = index;
|
||||
} else if ( band == 1 && index > g ) {
|
||||
g = index;
|
||||
} else if ( band == 2 && index > b ) {
|
||||
b = index;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(r,g,b,a);
|
||||
}
|
29
cave/com.raytheon.uf.viz.truecolor.gl/plugin.xml
Normal file
29
cave/com.raytheon.uf.viz.truecolor.gl/plugin.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="com.raytheon.uf.viz.core.graphicsExtension">
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.truecolor.gl.extension.GLTrueColorImagingExtension">
|
||||
</graphicsExtension>
|
||||
</extension>
|
||||
</plugin>
|
|
@ -0,0 +1,30 @@
|
|||
package com.raytheon.uf.viz.truecolor.gl;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
|
||||
private static BundleContext context;
|
||||
|
||||
static BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = bundleContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* 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.truecolor.gl.extension;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.PixelCoverage;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ImagingSupport;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
||||
import com.raytheon.uf.viz.truecolor.gl.image.GLTrueColorImage;
|
||||
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
||||
|
||||
/**
|
||||
* GL implementation of the {@link ITrueColorImagingExtension}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||
implements ITrueColorImagingExtension {
|
||||
|
||||
private AbstractGLImage writeToImage;
|
||||
|
||||
private Channel renderingChannel;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension#
|
||||
* initializeRaster(int[], com.raytheon.uf.viz.core.IExtent)
|
||||
*/
|
||||
@Override
|
||||
public ITrueColorImage initializeRaster(int[] imageBounds,
|
||||
IExtent imageExtent) throws VizException {
|
||||
return new GLTrueColorImage(GLTrueColorImagingExtension.class,
|
||||
imageBounds, imageExtent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#getShaderProgramName
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public String getShaderProgramName() {
|
||||
return "truecolor";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#preImageRender
|
||||
* (com.raytheon.uf.viz.core.drawables.PaintProperties,
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage,
|
||||
* com.raytheon.uf.viz.core.PixelCoverage)
|
||||
*/
|
||||
@Override
|
||||
public Object preImageRender(PaintProperties paintProps,
|
||||
AbstractGLImage image, PixelCoverage imageCoverage)
|
||||
throws VizException {
|
||||
if (image instanceof GLTrueColorImage) {
|
||||
GLTrueColorImage trueColorImage = (GLTrueColorImage) image;
|
||||
if (trueColorImage.isRepaint()) {
|
||||
writeToImage = trueColorImage;
|
||||
GLOffscreenRenderingExtension extension = target
|
||||
.getExtension(GLOffscreenRenderingExtension.class);
|
||||
try {
|
||||
extension.renderOffscreen(trueColorImage,
|
||||
trueColorImage.getImageExtent());
|
||||
boolean allPainted = true;
|
||||
for (Channel channel : Channel.values()) {
|
||||
renderingChannel = channel;
|
||||
DrawableImage[] imagesToDraw = trueColorImage
|
||||
.getImages(channel);
|
||||
if (imagesToDraw != null && imagesToDraw.length > 0) {
|
||||
// Make sure images are staged before we mosaic them
|
||||
ImagingSupport.prepareImages(target, imagesToDraw);
|
||||
|
||||
// Each image needs to draw separately due to gl
|
||||
// issues when
|
||||
// zoomed in very far, rendered parts near the
|
||||
// corners don't
|
||||
// show all the pixels for each image. Pushing and
|
||||
// popping
|
||||
// GL_TEXTURE_BIT before/after each render fixes
|
||||
// this issue
|
||||
for (DrawableImage di : imagesToDraw) {
|
||||
allPainted &= drawRasters(paintProps, di);
|
||||
}
|
||||
// Need to set repaint based on if drawing
|
||||
// completed.
|
||||
trueColorImage.setRepaint(allPainted == false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
extension.renderOnscreen();
|
||||
}
|
||||
renderingChannel = null;
|
||||
writeToImage = null;
|
||||
}
|
||||
|
||||
target.drawRasters(paintProps,
|
||||
new DrawableImage(trueColorImage.getWrappedImage(),
|
||||
imageCoverage));
|
||||
// Don't actually render this image now since we just did it
|
||||
return null;
|
||||
} else {
|
||||
GL gl = target.getGl();
|
||||
// bind on GL_TEXTURE1 as 0 is channel image
|
||||
writeToImage.bind(gl, GL.GL_TEXTURE1);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#postImageRender
|
||||
* (com.raytheon.uf.viz.core.drawables.PaintProperties,
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void postImageRender(PaintProperties paintProps,
|
||||
AbstractGLImage image, Object data) throws VizException {
|
||||
GL gl = target.getGl();
|
||||
// Unbind the writeToImage from GL_TEXTURE1
|
||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#loadShaderData
|
||||
* (com.raytheon.viz.core.gl.glsl.GLShaderProgram,
|
||||
* com.raytheon.uf.viz.core.drawables.IImage,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void loadShaderData(GLShaderProgram program, IImage image,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
if (image instanceof GLColormappedImage == false) {
|
||||
throw new VizException(
|
||||
"Can only render colormapped images in true color");
|
||||
}
|
||||
|
||||
GLColormappedImage cmapImage = (GLColormappedImage) image;
|
||||
ColorMapParameters colorMapParameters = cmapImage
|
||||
.getColorMapParameters();
|
||||
int textureType = cmapImage.getTextureType();
|
||||
|
||||
// Set the band image data
|
||||
program.setUniform("rawTex", 0);
|
||||
program.setUniform("naturalMin", colorMapParameters.getDataMin());
|
||||
program.setUniform("naturalMax", colorMapParameters.getDataMax());
|
||||
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
|
||||
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
|
||||
program.setUniform("isFloat", textureType == GL.GL_FLOAT
|
||||
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1 : 0);
|
||||
|
||||
// Set the composite image data
|
||||
program.setUniform("trueColorTexture", 1);
|
||||
program.setUniform("width", writeToImage.getWidth());
|
||||
program.setUniform("height", writeToImage.getHeight());
|
||||
|
||||
// Set the band we are rendering to
|
||||
program.setUniform("band", renderingChannel.ordinal());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* 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.truecolor.gl.image;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.ITrueColorImage;
|
||||
import com.raytheon.viz.core.gl.images.GLDelegateImage;
|
||||
import com.raytheon.viz.core.gl.images.GLImage;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLTrueColorImage extends GLDelegateImage<GLImage> implements
|
||||
ITrueColorImage {
|
||||
|
||||
private static class RGBCallback implements IRenderedImageCallback {
|
||||
private int[] bounds;
|
||||
|
||||
private RGBCallback(int[] bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderedImage getImage() throws VizException {
|
||||
return new BufferedImage(bounds[0], bounds[1],
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean repaint = true;
|
||||
|
||||
private int[] bounds;
|
||||
|
||||
private IExtent imageExtent;
|
||||
|
||||
private Map<Channel, DrawableImage[]> channelMap = new HashMap<Channel, DrawableImage[]>();
|
||||
|
||||
/**
|
||||
* @param extensionClass
|
||||
*/
|
||||
public GLTrueColorImage(Class<? extends IImagingExtension> extensionClass,
|
||||
int[] bounds, IExtent imageExtent) {
|
||||
super(new GLImage(new RGBCallback(bounds), IImagingExtension.class),
|
||||
extensionClass);
|
||||
this.bounds = bounds;
|
||||
this.imageExtent = imageExtent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the imageExtent
|
||||
*/
|
||||
public IExtent getImageExtent() {
|
||||
return imageExtent;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage
|
||||
* #setImages(com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension
|
||||
* .Channel, com.raytheon.uf.viz.core.DrawableImage[])
|
||||
*/
|
||||
@Override
|
||||
public void setImages(Channel channel, DrawableImage... images) {
|
||||
DrawableImage[] prev = channelMap.put(channel, images);
|
||||
if (prev != images) {
|
||||
// Try to find equal array
|
||||
if (prev != null && images != null && prev.length == images.length) {
|
||||
for (int i = 0; i < images.length; ++i) {
|
||||
if (images[i].getImage() != prev[i].getImage()) {
|
||||
repaint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the images for the specified channel
|
||||
*
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public DrawableImage[] getImages(Channel channel) {
|
||||
return channelMap.get(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the repaint
|
||||
*/
|
||||
public boolean isRepaint() {
|
||||
return repaint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param repaint
|
||||
* the repaint to set
|
||||
*/
|
||||
public void setRepaint(boolean repaint) {
|
||||
this.repaint = repaint;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage#setSize(int[])
|
||||
*/
|
||||
@Override
|
||||
public void setSize(int[] bounds) {
|
||||
if (Arrays.equals(bounds, this.bounds) == false) {
|
||||
this.bounds = bounds;
|
||||
image.dispose();
|
||||
image = new GLImage(new RGBCallback(bounds),
|
||||
IImagingExtension.class);
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage#setImageExtent(com.raytheon.uf.viz.core.IExtent)
|
||||
*/
|
||||
@Override
|
||||
public void setImageExtent(IExtent extent) {
|
||||
if (extent.equals(this.imageExtent) == false) {
|
||||
this.imageExtent = extent;
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
7
cave/com.raytheon.uf.viz.truecolor/.classpath
Normal file
7
cave/com.raytheon.uf.viz.truecolor/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
cave/com.raytheon.uf.viz.truecolor/.project
Normal file
28
cave/com.raytheon.uf.viz.truecolor/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.viz.truecolor</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Mon Aug 06 11:45:00 CDT 2012
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
17
cave/com.raytheon.uf.viz.truecolor/META-INF/MANIFEST.MF
Normal file
17
cave/com.raytheon.uf.viz.truecolor/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,17 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Truecolor
|
||||
Bundle-SymbolicName: com.raytheon.uf.viz.truecolor;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.raytheon.uf.viz.truecolor.Activator
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Eclipse-RegisterBuddy: com.raytheon.uf.viz.core
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
|
||||
com.raytheon.viz.ui;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.time;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.uf.viz.truecolor.extension
|
|
@ -0,0 +1 @@
|
|||
com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroupData
|
5
cave/com.raytheon.uf.viz.truecolor/build.properties
Normal file
5
cave/com.raytheon.uf.viz.truecolor/build.properties
Normal file
|
@ -0,0 +1,5 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml
|
31
cave/com.raytheon.uf.viz.truecolor/plugin.xml
Normal file
31
cave/com.raytheon.uf.viz.truecolor/plugin.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="com.raytheon.uf.viz.core.resource">
|
||||
<resource
|
||||
class="com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup"
|
||||
name="True Color Imagery"
|
||||
renderingOrderId="IMAGE_COUNTRY"
|
||||
resourceType="PLAN_VIEW"/>
|
||||
</extension>
|
||||
</plugin>
|
|
@ -0,0 +1,62 @@
|
|||
package com.raytheon.uf.viz.truecolor;
|
||||
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends AbstractUIPlugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "com.raytheon.uf.viz.truecolor"; //$NON-NLS-1$
|
||||
|
||||
public static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(Activator.class);
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
|
||||
* )
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* 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.truecolor.extension;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
* Imaging extension for "true color" images. Where a set of
|
||||
* {@link IColormappedImage} images are assigned to each band of an RGB channel
|
||||
* image
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface ITrueColorImagingExtension extends IImagingExtension {
|
||||
|
||||
public static enum Channel {
|
||||
RED, GREEN, BLUE;
|
||||
}
|
||||
|
||||
public static interface ITrueColorImage extends IImage {
|
||||
|
||||
public void setImages(Channel channel, DrawableImage... images);
|
||||
|
||||
public void setSize(int[] bounds);
|
||||
|
||||
public void setImageExtent(IExtent extent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a true color image with the given imageBounds and imageExtent
|
||||
*
|
||||
* @param imageBounds
|
||||
* @param imageExtent
|
||||
* @param params
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public ITrueColorImage initializeRaster(int[] imageBounds,
|
||||
IExtent imageExtent) throws VizException;
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/**
|
||||
* 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.truecolor.rsc;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
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.PixelCoverage;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension.ImageProvider;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.GroupNamingCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
|
||||
import com.raytheon.uf.viz.truecolor.Activator;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.ITrueColorImage;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Resource group that operates on 3 resources, one assigned to each band of an
|
||||
* RGB image. This resource checks for the {@link ImageProvider} on the
|
||||
* {@link ImagingCapability}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TrueColorResourceGroup extends
|
||||
AbstractVizResource<TrueColorResourceGroupData, IDescriptor> implements
|
||||
IResourceGroup, IResourceDataChanged {
|
||||
|
||||
private ITrueColorImage image;
|
||||
|
||||
private boolean timeAgnostic = true;
|
||||
|
||||
/**
|
||||
* @param resourceData
|
||||
* @param loadProperties
|
||||
*/
|
||||
public TrueColorResourceGroup(TrueColorResourceGroupData resourceData,
|
||||
LoadProperties loadProperties) {
|
||||
super(resourceData, loadProperties);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.IResourceGroup#getResourceList()
|
||||
*/
|
||||
@Override
|
||||
public ResourceList getResourceList() {
|
||||
return resourceData.getResourceList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
|
||||
*/
|
||||
@Override
|
||||
protected void disposeInternal() {
|
||||
resourceData.removeChangeListener(this);
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
rp.getResource().dispose();
|
||||
}
|
||||
image.dispose();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
|
||||
* .uf.viz.core.IGraphicsTarget,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
protected void paintInternal(IGraphicsTarget target,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
Rectangle rect = paintProps.getCanvasBounds();
|
||||
IExtent extent = paintProps.getView().getExtent();
|
||||
image.setSize(new int[] { rect.width, rect.height });
|
||||
image.setImageExtent(extent);
|
||||
|
||||
for (Channel c : Channel.values()) {
|
||||
ResourcePair rp = resourceData.getResource(c);
|
||||
if (rp != null) {
|
||||
image.setImages(c, getImages(rp, target, paintProps));
|
||||
}
|
||||
}
|
||||
|
||||
Coordinate ul = new Coordinate(extent.getMinX(), extent.getMaxY());
|
||||
Coordinate ur = new Coordinate(extent.getMaxX(), extent.getMaxY());
|
||||
Coordinate lr = new Coordinate(extent.getMaxX(), extent.getMinY());
|
||||
Coordinate ll = new Coordinate(extent.getMinX(), extent.getMinY());
|
||||
|
||||
target.drawRaster(image, new PixelCoverage(ul, ur, lr, ll), paintProps);
|
||||
}
|
||||
|
||||
private DrawableImage[] getImages(ResourcePair rp, IGraphicsTarget target,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
paintProps.setDataTime(paintProps.getFramesInfo().getTimeForResource(
|
||||
rp.getResource()));
|
||||
ImagingCapability imaging = rp.getResource().getCapability(
|
||||
ImagingCapability.class);
|
||||
Collection<DrawableImage> images = imaging.getProvider().getImages(
|
||||
target, paintProps);
|
||||
return images.toArray(new DrawableImage[images.size()]);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#isTimeAgnostic()
|
||||
*/
|
||||
@Override
|
||||
public boolean isTimeAgnostic() {
|
||||
return timeAgnostic;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
|
||||
* .uf.viz.core.IGraphicsTarget)
|
||||
*/
|
||||
@Override
|
||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
||||
// We will name the composite
|
||||
getCapability(GroupNamingCapability.class);
|
||||
|
||||
// Initialize them
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
AbstractVizResource<?, ?> resource = rp.getResource();
|
||||
resource.init(target);
|
||||
// Check resource for required capabilities
|
||||
String error = null;
|
||||
if (resource.hasCapability(ImagingCapability.class)) {
|
||||
ImagingCapability imaging = resource
|
||||
.getCapability(ImagingCapability.class);
|
||||
if (imaging.getProvider() != null) {
|
||||
if (resource.hasCapability(ColorMapCapability.class) == false) {
|
||||
error = "does not have ColorMapCapability";
|
||||
}
|
||||
} else {
|
||||
error = "does not have image provider set on the ImagingCapability";
|
||||
}
|
||||
} else {
|
||||
error = "does not have the ImagingCapability";
|
||||
}
|
||||
if (error != null) {
|
||||
Activator.statusHandler.handle(Priority.PROBLEM,
|
||||
resourceData.getCompositeName(rp)
|
||||
+ " resource in true color composite " + error);
|
||||
resourceData.removeResource(rp);
|
||||
}
|
||||
}
|
||||
|
||||
ITrueColorImagingExtension ext = target
|
||||
.getExtension(ITrueColorImagingExtension.class);
|
||||
image = ext.initializeRaster(new int[] { 0, 0 }, null);
|
||||
resourceData.addChangeListener(this);
|
||||
resourceChanged(ChangeType.CAPABILITY,
|
||||
getCapability(ImagingCapability.class));
|
||||
|
||||
timeAgnostic = true;
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
// If any resource is not time agnostic, neither are we
|
||||
timeAgnostic &= rp.getResource().isTimeAgnostic();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#project(org.opengis.
|
||||
* referencing.crs.CoordinateReferenceSystem)
|
||||
*/
|
||||
@Override
|
||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
rp.getResource().project(crs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.IResourceDataChanged#resourceChanged(com
|
||||
* .raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void resourceChanged(ChangeType type, Object object) {
|
||||
if (type == ChangeType.CAPABILITY) {
|
||||
if (object instanceof ImagingCapability) {
|
||||
ImagingCapability imaging = (ImagingCapability) object;
|
||||
image.setBrightness(imaging.getBrightness());
|
||||
image.setContrast(imaging.getContrast());
|
||||
image.setInterpolated(imaging.isInterpolationState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
/**
|
||||
* 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.truecolor.rsc;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractNameGenerator;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
|
||||
/**
|
||||
* {@link TrueColorResourceGroup} resource data. Contains a red/blue/green
|
||||
* channel resource and a name. Sub resources that .equal each other will be
|
||||
* replaced with the first reference to save time
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TrueColorResourceGroupData extends AbstractResourceData implements
|
||||
IResourceGroup {
|
||||
|
||||
private ResourceList resourceList;
|
||||
|
||||
@XmlElement
|
||||
private String groupName;
|
||||
|
||||
@XmlElement
|
||||
private AbstractResourceData redChannelResource;
|
||||
|
||||
@XmlElement
|
||||
private AbstractResourceData greenChannelResource;
|
||||
|
||||
@XmlElement
|
||||
private AbstractResourceData blueChannelResource;
|
||||
|
||||
public TrueColorResourceGroupData() {
|
||||
nameGenerator = new AbstractNameGenerator() {
|
||||
@Override
|
||||
public String getName(AbstractVizResource<?, ?> resource) {
|
||||
return groupName;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.IResourceGroup#getResourceList()
|
||||
*/
|
||||
@Override
|
||||
public ResourceList getResourceList() {
|
||||
if (resourceList == null) {
|
||||
resourceList = new ResourceList();
|
||||
// Initialize the resource list, if any of the resources equal each
|
||||
// other, replace with reference instead of copy to save memory
|
||||
if (redChannelResource != null) {
|
||||
addResource(redChannelResource);
|
||||
}
|
||||
if (greenChannelResource != null) {
|
||||
if (greenChannelResource.equals(redChannelResource)) {
|
||||
greenChannelResource = redChannelResource;
|
||||
} else {
|
||||
addResource(greenChannelResource);
|
||||
}
|
||||
}
|
||||
if (blueChannelResource != null) {
|
||||
if (blueChannelResource.equals(redChannelResource)) {
|
||||
blueChannelResource = redChannelResource;
|
||||
} else if (blueChannelResource.equals(greenChannelResource)) {
|
||||
blueChannelResource = greenChannelResource;
|
||||
} else {
|
||||
addResource(blueChannelResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resourceList;
|
||||
}
|
||||
|
||||
private void addResource(AbstractResourceData resourceData) {
|
||||
ResourcePair rp = new ResourcePair();
|
||||
rp.setResourceData(resourceData);
|
||||
rp.setLoadProperties(new LoadProperties());
|
||||
rp.setProperties(new ResourceProperties());
|
||||
resourceList.add(rp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a resource from the resource data
|
||||
*
|
||||
* @param rp
|
||||
*/
|
||||
public void removeResource(ResourcePair rp) {
|
||||
resourceList.remove(rp);
|
||||
if (rp.getResourceData() == redChannelResource) {
|
||||
redChannelResource = null;
|
||||
}
|
||||
if (rp.getResourceData() == greenChannelResource) {
|
||||
greenChannelResource = null;
|
||||
}
|
||||
if (rp.getResourceData() == blueChannelResource) {
|
||||
blueChannelResource = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the composite name of the resource pair (Red, Red/Green, Blue, etc)
|
||||
*
|
||||
* @param rp
|
||||
* @return
|
||||
*/
|
||||
public String getCompositeName(ResourcePair rp) {
|
||||
String name = "";
|
||||
if (rp.getResourceData() == redChannelResource) {
|
||||
name += "Red";
|
||||
}
|
||||
if (rp.getResourceData() == greenChannelResource) {
|
||||
if (name.isEmpty() == false) {
|
||||
name += "/";
|
||||
}
|
||||
name += "Green";
|
||||
}
|
||||
if (rp.getResourceData() == blueChannelResource) {
|
||||
if (name.isEmpty() == false) {
|
||||
name += "/";
|
||||
}
|
||||
name += "Blue";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
|
||||
* .uf.viz.core.rsc.LoadProperties,
|
||||
* com.raytheon.uf.viz.core.drawables.IDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public AbstractVizResource<?, ?> construct(LoadProperties loadProperties,
|
||||
IDescriptor descriptor) throws VizException {
|
||||
return new TrueColorResourceGroup(this, loadProperties);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void update(Object updateData) {
|
||||
// Nothing to update, updates will be handled by sub resources
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource pair associated with the {@link Channel}
|
||||
*
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public ResourcePair getResource(Channel channel) {
|
||||
AbstractResourceData toCheckFor = null;
|
||||
switch (channel) {
|
||||
case RED:
|
||||
toCheckFor = redChannelResource;
|
||||
break;
|
||||
case GREEN:
|
||||
toCheckFor = greenChannelResource;
|
||||
break;
|
||||
case BLUE:
|
||||
toCheckFor = blueChannelResource;
|
||||
break;
|
||||
}
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
if (rp.getResourceData() == toCheckFor) {
|
||||
return rp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the groupName
|
||||
*/
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupName
|
||||
* the groupName to set
|
||||
*/
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the redChannelResource
|
||||
*/
|
||||
public AbstractResourceData getRedChannelResource() {
|
||||
return redChannelResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redChannelResource
|
||||
* the redChannelResource to set
|
||||
*/
|
||||
public void setRedChannelResource(AbstractResourceData redChannelResource) {
|
||||
this.redChannelResource = redChannelResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the greenChannelResource
|
||||
*/
|
||||
public AbstractResourceData getGreenChannelResource() {
|
||||
return greenChannelResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param greenChannelResource
|
||||
* the greenChannelResource to set
|
||||
*/
|
||||
public void setGreenChannelResource(
|
||||
AbstractResourceData greenChannelResource) {
|
||||
this.greenChannelResource = greenChannelResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the blueChannelResource
|
||||
*/
|
||||
public AbstractResourceData getBlueChannelResource() {
|
||||
return blueChannelResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blueChannelResource
|
||||
* the blueChannelResource to set
|
||||
*/
|
||||
public void setBlueChannelResource(AbstractResourceData blueChannelResource) {
|
||||
this.blueChannelResource = blueChannelResource;
|
||||
}
|
||||
|
||||
/*
|
||||
* (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;
|
||||
TrueColorResourceGroupData other = (TrueColorResourceGroupData) obj;
|
||||
if (blueChannelResource == null) {
|
||||
if (other.blueChannelResource != null)
|
||||
return false;
|
||||
} else if (!blueChannelResource.equals(other.blueChannelResource))
|
||||
return false;
|
||||
if (greenChannelResource == null) {
|
||||
if (other.greenChannelResource != null)
|
||||
return false;
|
||||
} else if (!greenChannelResource.equals(other.greenChannelResource))
|
||||
return false;
|
||||
if (groupName == null) {
|
||||
if (other.groupName != null)
|
||||
return false;
|
||||
} else if (!groupName.equals(other.groupName))
|
||||
return false;
|
||||
if (redChannelResource == null) {
|
||||
if (other.redChannelResource != null)
|
||||
return false;
|
||||
} else if (!redChannelResource.equals(other.redChannelResource))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ void main(void) {
|
|||
}
|
||||
} else {
|
||||
float naturalValue = ((rawValue * (naturalMax - naturalMin)) + naturalMin);
|
||||
index = findIndex(naturalValue, cmapMin, cmapMax);
|
||||
index = capIndex(findIndex(naturalValue, cmapMin, cmapMax));
|
||||
}
|
||||
|
||||
// Lookup color in colorMap for index
|
||||
|
|
|
@ -96,9 +96,9 @@ float findFloatIndexLog(float rawValue, float cmapMin, float cmapMax, int mirror
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a raw data value linearly determine the index(0-1) into cmapMin/cmapMax
|
||||
* Given a raw data value linearly determine the index into cmapMin/cmapMax.
|
||||
* Index is not capped and may be outsite of 0-1
|
||||
*/
|
||||
float findIndex(float rawValue, float cmapMin, float cmapMax) {
|
||||
float index = ((rawValue - cmapMin) / abs(cmapMax-cmapMin));
|
||||
return capIndex(index);
|
||||
return ((rawValue - cmapMin) / abs(cmapMax-cmapMin));
|
||||
}
|
||||
|
|
|
@ -74,6 +74,11 @@ public abstract class AbstractGLColorMapDataFormat {
|
|||
*/
|
||||
public abstract Number getValue(int x, int y, GLColorMapData data);
|
||||
|
||||
/**
|
||||
* Get the number of bytes each pixel takes up
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract int getBytesPerPixel();
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,4 +112,8 @@ public class GLColorMapData {
|
|||
public int[] getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
public int getBytesPerPixel() {
|
||||
return dataFormat.getBytesPerPixel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ public class GLCMTextureData implements IImageCacheable {
|
|||
public int getSize() {
|
||||
if (data != null) {
|
||||
int[] dimensions = data.getDimensions();
|
||||
int totalSize = 1;
|
||||
int totalSize = data.getBytesPerPixel();
|
||||
for (int i = 0; i < dimensions.length; ++i) {
|
||||
totalSize *= dimensions[i];
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue