Improve WWA performance
AbstractWWAResource - cache current frame - cache current list of WWA entries - add color, string, and DrawableString objects to the internal WarningEntry class - use cached information when drawing, to draw faster (paintInternal method)
This commit is contained in:
parent
0e811947f9
commit
fe81f4ba69
1 changed files with 163 additions and 95 deletions
|
@ -98,6 +98,7 @@ import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
|
||||||
* Mar 15, 2022 srcarter@ucar Add support for display settings for outline, fill, text and time displays
|
* Mar 15, 2022 srcarter@ucar Add support for display settings for outline, fill, text and time displays
|
||||||
* Jun 24, 2022 srcarter@ucar Add 'statement/other' display settings, set enabled for only relevant WWA types
|
* Jun 24, 2022 srcarter@ucar Add 'statement/other' display settings, set enabled for only relevant WWA types
|
||||||
* Jun 28, 2022 srcarter@ucar Display sampling based on new 'sampling' settings
|
* Jun 28, 2022 srcarter@ucar Display sampling based on new 'sampling' settings
|
||||||
|
* Mar 27, 2023 srcarter@ucar Optimize drawing to improve performance
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -136,6 +137,28 @@ public abstract class AbstractWWAResource extends
|
||||||
* set to true if paint needs to re-init the shape
|
* set to true if paint needs to re-init the shape
|
||||||
*/
|
*/
|
||||||
protected boolean project = false;
|
protected boolean project = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the display color
|
||||||
|
*/
|
||||||
|
protected RGB color = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the text string that can be displayed
|
||||||
|
*/
|
||||||
|
protected String textStr = null;
|
||||||
|
/**
|
||||||
|
* the time string that can be displayed
|
||||||
|
*/
|
||||||
|
protected String timeStr = null;
|
||||||
|
/**
|
||||||
|
* the stylized emergency display string
|
||||||
|
*/
|
||||||
|
protected DrawableString emergencyDS = null;
|
||||||
|
/**
|
||||||
|
* the stylized params display string
|
||||||
|
*/
|
||||||
|
protected DrawableString paramsDS = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +225,12 @@ public abstract class AbstractWWAResource extends
|
||||||
private static final String WATCH_SIG = "A";
|
private static final String WATCH_SIG = "A";
|
||||||
private static final String ADVISORY_SIG = "Y";
|
private static final String ADVISORY_SIG = "Y";
|
||||||
|
|
||||||
|
// Current drawing objects
|
||||||
|
private int currentFrameIdx = Integer.MIN_VALUE;
|
||||||
|
private TimeRange currentFramePeriod = null;
|
||||||
|
private boolean currentLastFrame = false;
|
||||||
|
private HashMap<String, WarningEntry> currentCandidates = new HashMap<>();
|
||||||
|
|
||||||
/** The dialog used to change display properties */
|
/** The dialog used to change display properties */
|
||||||
private DrawingPropertiesDialog drawingDialog;
|
private DrawingPropertiesDialog drawingDialog;
|
||||||
|
|
||||||
|
@ -420,47 +449,59 @@ public abstract class AbstractWWAResource extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int index = info.getFrameIndex();
|
int index = info.getFrameIndex();
|
||||||
if (!this.recordsToLoad.isEmpty()) {
|
boolean framesChanged = false;
|
||||||
this.updateDisplay(target);
|
//only do the frame logic if the frame has changed
|
||||||
|
if(currentFrameIdx == Integer.MIN_VALUE || currentFrameIdx != index) {
|
||||||
|
framesChanged = true;
|
||||||
|
currentFrameIdx = index;
|
||||||
|
currentCandidates.clear();
|
||||||
|
|
||||||
|
if (!this.recordsToLoad.isEmpty()) {
|
||||||
|
this.updateDisplay(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTime thisFrameTime = null;
|
||||||
|
if (index > -1 && index < frames.length) {
|
||||||
|
thisFrameTime = frames[index];
|
||||||
|
}
|
||||||
|
if (thisFrameTime == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeRange framePeriod = null;
|
||||||
|
boolean lastFrame = false;
|
||||||
|
if (index + 1 < frames.length) {
|
||||||
|
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
||||||
|
frames[index + 1].getRefTime());
|
||||||
|
} else {
|
||||||
|
framePeriod = getLastFrameTimeRange(thisFrameTime.getRefTime());
|
||||||
|
lastFrame = true;
|
||||||
|
}
|
||||||
|
currentFramePeriod = framePeriod;
|
||||||
|
currentLastFrame = lastFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataTime thisFrameTime = null;
|
|
||||||
if (index > -1 && index < frames.length) {
|
|
||||||
thisFrameTime = frames[index];
|
|
||||||
}
|
|
||||||
if (thisFrameTime == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeRange framePeriod = null;
|
|
||||||
boolean lastFrame = false;
|
|
||||||
if (index + 1 < frames.length) {
|
|
||||||
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
|
||||||
frames[index + 1].getRefTime());
|
|
||||||
} else {
|
|
||||||
framePeriod = getLastFrameTimeRange(thisFrameTime.getRefTime());
|
|
||||||
lastFrame = true;
|
|
||||||
}
|
|
||||||
synchronized (paintLock) {
|
synchronized (paintLock) {
|
||||||
HashMap<String, WarningEntry> candidates = new HashMap<>();
|
if(currentCandidates.size() == 0 || framesChanged) {
|
||||||
for (WarningEntry entry : entryMap.values()) {
|
for (WarningEntry entry : entryMap.values()) {
|
||||||
if (matchesFrame(entry, paintProps.getDataTime(), framePeriod,
|
if (matchesFrame(entry, paintProps.getDataTime(), currentFramePeriod,
|
||||||
lastFrame)) {
|
currentLastFrame)) {
|
||||||
String key = getEventKey(entry);
|
String key = getEventKey(entry);
|
||||||
WarningEntry current = candidates.get(key);
|
WarningEntry current = currentCandidates.get(key);
|
||||||
|
|
||||||
if (current == null
|
if (current == null
|
||||||
|| current.record.getIssueTime().before(
|
|| current.record.getIssueTime().before(
|
||||||
entry.record.getIssueTime())
|
entry.record.getIssueTime())
|
||||||
|| (current.record.getIssueTime().equals(
|
|| (current.record.getIssueTime().equals(
|
||||||
entry.record.getIssueTime()) && current.record
|
entry.record.getIssueTime()) && current.record
|
||||||
.getInsertTime().before(
|
.getInsertTime().before(
|
||||||
entry.record.getInsertTime()))) {
|
entry.record.getInsertTime()))) {
|
||||||
candidates.put(key, entry);
|
currentCandidates.put(key, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (WarningEntry entry : candidates.values()) {
|
for (WarningEntry entry : currentCandidates.values()) {
|
||||||
AbstractWarningRecord record = entry.record;
|
AbstractWarningRecord record = entry.record;
|
||||||
boolean drawShape = true;
|
boolean drawShape = true;
|
||||||
boolean drawOutline = true;
|
boolean drawOutline = true;
|
||||||
|
@ -510,9 +551,12 @@ public abstract class AbstractWWAResource extends
|
||||||
entry.project = false;
|
entry.project = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGB displaycolor = color;
|
if(entry.color == null) {
|
||||||
if ( ! record.getPil().equals("SPS")) {
|
RGB displaycolor = color;
|
||||||
displaycolor = RGBColors.getRGBColor(getPhensigColor(record.getPhensig()));
|
if ( ! record.getPil().equals("SPS")) {
|
||||||
|
displaycolor = RGBColors.getRGBColor(getPhensigColor(record.getPhensig()));
|
||||||
|
}
|
||||||
|
entry.color = displaycolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entry != null){
|
if(entry != null){
|
||||||
|
@ -532,71 +576,92 @@ public abstract class AbstractWWAResource extends
|
||||||
|
|
||||||
target.drawWireframeShape(
|
target.drawWireframeShape(
|
||||||
entry.wireframeShape,
|
entry.wireframeShape,
|
||||||
displaycolor,
|
entry.color,
|
||||||
outlineWidth, lineStyle);
|
outlineWidth, lineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record != null && record.getGeometry() != null) {
|
if (record != null && record.getGeometry() != null) {
|
||||||
// Calculate the upper left portion of the polygon
|
//only calculate the drawable strings the first time through
|
||||||
Coordinate upperLeft = new Coordinate(180, -90);
|
if(entry.paramsDS == null || (entry.emergencyDS == null && EmergencyType.isEmergency(record.getRawmessage()))){
|
||||||
|
// Calculate the upper left portion of the polygon
|
||||||
for (Coordinate c : record.getGeometry().getCoordinates()) {
|
Coordinate upperLeft = new Coordinate(180, -90);
|
||||||
if (c.y - c.x > upperLeft.y - upperLeft.x) {
|
|
||||||
upperLeft = c;
|
for (Coordinate c : record.getGeometry().getCoordinates()) {
|
||||||
|
if (c.y - c.x > upperLeft.y - upperLeft.x) {
|
||||||
|
upperLeft = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double[] d = descriptor.worldToPixel(new double[] {
|
||||||
|
upperLeft.x, upperLeft.y });
|
||||||
|
d[0] -= paintProps.getZoomLevel() * 100;
|
||||||
|
|
||||||
|
double mapWidth = descriptor.getMapWidth()
|
||||||
|
* paintProps.getZoomLevel() / 1000;
|
||||||
|
String[] fullText = getText(record, mapWidth);
|
||||||
|
|
||||||
|
String[] textToPrint = {"",""};
|
||||||
|
if(drawText){
|
||||||
|
textToPrint[0] = fullText[0];
|
||||||
|
}
|
||||||
|
if(drawTime){
|
||||||
|
textToPrint[1] = fullText[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (warningsFont == null) {
|
||||||
|
warningsFont = target.initializeFont(target
|
||||||
|
.getDefaultFont().getFontName(), 9,
|
||||||
|
new IFont.Style[0]);
|
||||||
|
emergencyFont = target.getDefaultFont().deriveWithSize(
|
||||||
|
12);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawableString params = new DrawableString(textToPrint, entry.color);
|
||||||
|
params.font = warningsFont;
|
||||||
|
params.setCoordinates(d[0], d[1]);
|
||||||
|
params.horizontalAlignment = HorizontalAlignment.RIGHT;
|
||||||
|
params.verticallAlignment = VerticalAlignment.BOTTOM;
|
||||||
|
params.magnification = getCapability(
|
||||||
|
MagnificationCapability.class).getMagnification();
|
||||||
|
entry.paramsDS = params;
|
||||||
|
|
||||||
|
// Draws the string again to have it appear bolder
|
||||||
|
if (EmergencyType.isEmergency(record.getRawmessage())) {
|
||||||
|
// moves over text to add EMER in a different font
|
||||||
|
textToPrint[1] = String.format("%1$-23" + "s",
|
||||||
|
textToPrint[1]);
|
||||||
|
params.setText(textToPrint, entry.color);
|
||||||
|
|
||||||
|
DrawableString emergencyString = new DrawableString(
|
||||||
|
params);
|
||||||
|
emergencyString.setCoordinates(d[0],
|
||||||
|
d[1] + (paintProps.getZoomLevel()) * 90);
|
||||||
|
emergencyString.font = emergencyFont;
|
||||||
|
emergencyString.setText(new String[] { "", "",
|
||||||
|
" " + EmergencyType.EMER, "" }, entry.color);
|
||||||
|
entry.emergencyDS = emergencyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.textStr = fullText[0];
|
||||||
|
entry.timeStr = fullText[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
double[] d = descriptor.worldToPixel(new double[] {
|
|
||||||
upperLeft.x, upperLeft.y });
|
|
||||||
d[0] -= paintProps.getZoomLevel() * 100;
|
|
||||||
|
|
||||||
double mapWidth = descriptor.getMapWidth()
|
|
||||||
* paintProps.getZoomLevel() / 1000;
|
|
||||||
String[] fullText = getText(record, mapWidth);
|
|
||||||
|
|
||||||
String[] textToPrint = {"",""};
|
|
||||||
if(drawText){
|
|
||||||
textToPrint[0] = fullText[0];
|
|
||||||
}
|
|
||||||
if(drawTime){
|
|
||||||
textToPrint[1] = fullText[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (warningsFont == null) {
|
|
||||||
warningsFont = target.initializeFont(target
|
|
||||||
.getDefaultFont().getFontName(), 9,
|
|
||||||
new IFont.Style[0]);
|
|
||||||
emergencyFont = target.getDefaultFont().deriveWithSize(
|
|
||||||
12);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawableString params = new DrawableString(textToPrint, displaycolor);
|
|
||||||
params.font = warningsFont;
|
|
||||||
params.setCoordinates(d[0], d[1]);
|
|
||||||
params.horizontalAlignment = HorizontalAlignment.RIGHT;
|
|
||||||
params.verticallAlignment = VerticalAlignment.BOTTOM;
|
|
||||||
params.magnification = getCapability(
|
|
||||||
MagnificationCapability.class).getMagnification();
|
|
||||||
|
|
||||||
// Draws the string again to have it appear bolder
|
|
||||||
if (EmergencyType.isEmergency(record.getRawmessage())) {
|
if (EmergencyType.isEmergency(record.getRawmessage())) {
|
||||||
// moves over text to add EMER in a different font
|
target.drawStrings(entry.emergencyDS);
|
||||||
textToPrint[1] = String.format("%1$-23" + "s",
|
|
||||||
textToPrint[1]);
|
|
||||||
params.setText(textToPrint, displaycolor);
|
|
||||||
|
|
||||||
DrawableString emergencyString = new DrawableString(
|
|
||||||
params);
|
|
||||||
emergencyString.setCoordinates(d[0],
|
|
||||||
d[1] + (paintProps.getZoomLevel()) * 90);
|
|
||||||
emergencyString.font = emergencyFont;
|
|
||||||
emergencyString.setText(new String[] { "", "",
|
|
||||||
" " + EmergencyType.EMER, "" }, displaycolor);
|
|
||||||
target.drawStrings(emergencyString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target.drawStrings(params);
|
String[] currentStrs = {"",""};
|
||||||
|
if(drawText) {
|
||||||
|
currentStrs[0] = entry.textStr;
|
||||||
|
}
|
||||||
|
if(drawTime) {
|
||||||
|
currentStrs[1] = entry.timeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.paramsDS.setText(currentStrs, entry.color);
|
||||||
|
|
||||||
|
target.drawStrings(entry.paramsDS);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,6 +753,9 @@ public abstract class AbstractWWAResource extends
|
||||||
|
|
||||||
public synchronized void addRecord(PluginDataObject[] pdos)
|
public synchronized void addRecord(PluginDataObject[] pdos)
|
||||||
throws VizException {
|
throws VizException {
|
||||||
|
//data has changed, so clear the current drawing candidates
|
||||||
|
currentCandidates.clear();
|
||||||
|
|
||||||
for (PluginDataObject pdo : pdos) {
|
for (PluginDataObject pdo : pdos) {
|
||||||
if (pdo instanceof AbstractWarningRecord) {
|
if (pdo instanceof AbstractWarningRecord) {
|
||||||
AbstractWarningRecord record = (AbstractWarningRecord) pdo;
|
AbstractWarningRecord record = (AbstractWarningRecord) pdo;
|
||||||
|
@ -750,7 +818,7 @@ public abstract class AbstractWWAResource extends
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void requestData(DataTime earliest) throws VizException {
|
protected void requestData(DataTime earliest) throws VizException {
|
||||||
System.out.println("requesting data");
|
// System.out.println("requesting data");
|
||||||
Map<String, RequestConstraint> map = (Map<String, RequestConstraint>) resourceData
|
Map<String, RequestConstraint> map = (Map<String, RequestConstraint>) resourceData
|
||||||
.getMetadataMap().clone();
|
.getMetadataMap().clone();
|
||||||
if (earliestRequested != null) {
|
if (earliestRequested != null) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue