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:
srcarter3 2023-03-27 15:09:01 -07:00
parent 0e811947f9
commit fe81f4ba69

View file

@ -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) {