Omaha #5150 Fix Polyline time of arrial.

Former-commit-id: c6ed62707eb88eae8d20da1c2c996e774f784d37
This commit is contained in:
Ben Steffensmeier 2015-12-02 17:27:20 -06:00
parent f595bb5b41
commit 77fa171cea
3 changed files with 354 additions and 185 deletions

View file

@ -71,53 +71,57 @@ import com.vividsolutions.jts.geom.LineString;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 05-28-2010 #6042 bkowal When an Impossible Track Exception
* Is Encountered, The Track Will Now
* Be Reverted Back To Its Previous
* State. Replaced Impossible Storm
* Exception With Impossible Track
* Exception.
* 06-23-2010 #6468 bkowal The Tool Will No Longer Generate
* An Exception When It Is Initially
* Added To The Map While Looping
* Is Running.
* 06-23-2010 #5925 bkowal The Tool Will No Longer Generate An
* Exception When The Polyline Mode
* Is Enabled Even When A Track
* Has Not Been Generated.
* 07-14-2010 #6558 bkowal The tool will no longer generate an
* exception when it is moved from a
* pane with a larger frame count to a
* pane with a smaller frame count.
* The track will now always be centered around
* the initial location of the drag-me point
* when the track was created.
* 10-27-2010 #6964 bkowal The LineStyle is now passed as a parameter to
* the IGraphicsTarget drawWireframeShape method.
* 15Mar2013 15693 mgamazaychikov Made sure that magnification capability works.
* 06-11-2013 DR 16234 D. Friedman Fix pivot index when frames count is reduced.
* 06-24-2013 DR 16317 D. Friedman Handle "motionless" track.
* 01-28-2014 DR16465 mgamazaychikov Fixed the problem with anchor point when frame
* count changes; made line width configurable.
* 04-07-2014 DR 17232 D. Friedman Make sure pivot indexes are valid.
* 04-24-2014 DR 16356 Qinglu Lin Updated generateTrackInfo(), generateNewTrackInfo(),
* and createTrack().
* 06-03-14 3191 njensen Fix postData to not retrieve
* 06-17-2014 DR17409 mgamazaychikov Fix futurePoints calculation in generateNewTrackInfo()
* and generateExistingTrackInfo()
* 07-24-2014 3429 mapeters Updated deprecated drawLine() calls.
* 08-21-2014 DR 15700 Qinglu Lin handle the situation where frameTime is null in paintTrack().
* 09-09-2014 RM #657 Qinglu Lin handle StormTrackState.trackType is null.
* 09-25-2014 ASM #16773 D. Friedman Fix NPE.
* 10-10-2014 ASM #16844 D. Friedman Prevent some errors when moving track.
*
* Date Ticket# Engineer Description
* ------------- -------- ---------- -------------------------------------------
* May 28, 2010 6042 bkowal When an Impossible Track Exception Is
* Encountered, The Track Will Now Be Reverted
* Back To Its Previous State. Replaced
* Impossible Storm Exception With Impossible
* Track Exception.
* Jun 23, 2010 6468 bkowal The Tool Will No Longer Generate An
* Exception When It Is Initially Added To The
* Map While Looping Is Running.
* Jun 23, 2010 5925 bkowal The Tool Will No Longer Generate An
* Exception When The Polyline Mode Is Enabled
* Even When A Track Has Not Been Generated.
* Jul 14, 2010 6558 bkowal The tool will no longer generate an
* exception when it is moved from a pane with
* a larger frame count to a pane with a
* smaller frame count. The track will now
* always be centered around the initial
* location of the drag-me point when the
* track was created.
* Oct 27, 2010 6964 bkowal The LineStyle is now passed as a parameter
* to the IGraphicsTarget drawWireframeShape
* method.
* Mar 15, 2013 15693 mgamazay Made sure that magnification capability
* works.
* Jun 11, 2013 16234 dfriedman Fix pivot index when frames count is
* reduced.
* Jun 24, 2013 16317 dfriedman Handle "motionless" track.
* Jan 28, 2014 16465 mgamazay Fixed the problem with anchor point when
* frame count changes; made line width
* configurable.
* Apr 07, 2014 17232 dfriedman Make sure pivot indexes are valid.
* Apr 24, 2014 16356 qlin Updated generateTrackInfo(),
* generateNewTrackInfo(), and createTrack().
* Jun 03, 2014 3191 njensen Fix postData to not retrieve
* Jun 17, 2014 17409 mgamazay Fix futurePoints calculation in
* generateNewTrackInfo() and
* generateExistingTrackInfo()
* Jul 24, 2014 3429 mapeters Updated deprecated drawLine() calls.
* Aug 21, 2014 15700 qlin handle the situation where frameTime is
* null in paintTrack().
* Sep 09, 2014 657 qlin handle StormTrackState.trackType is null.
* Sep 25, 2014 16773 dfriedman Fix NPE.
* Oct 10, 2014 16844 dfriedman Prevent some errors when moving track.
* Dec 02, 2015 5150 bsteffen Add option to use constant end time.
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class StormTrackDisplay implements IRenderable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(StormTrackDisplay.class);
@ -408,7 +412,7 @@ public class StormTrackDisplay implements IRenderable {
coords = new Coordinate[] { c1,
new Coordinate(worldPixel[0], worldPixel[1]), c3 };
}
line = new GeometryFactory().createLineString(coords);
line = gf.createLineString(coords);
if (state.dragMePoint != null) {
state.dragMeLine = manager.figureLineFromPoint(line,
@ -518,7 +522,7 @@ public class StormTrackDisplay implements IRenderable {
double[] p = descriptor.pixelToWorld(paintProps.getView()
.getExtent().getCenter());
point = new Coordinate(p[0], p[1]);
state.dragMePoint = new GeometryFactory().createPoint(point);
state.dragMePoint = gf.createPoint(point);
}
}
@ -777,7 +781,7 @@ public class StormTrackDisplay implements IRenderable {
if (currentState.dragMePoint == null) {
double[] p = descriptor.pixelToWorld(paintProps
.getView().getExtent().getCenter());
currentState.dragMePoint = new GeometryFactory()
currentState.dragMePoint = gf
.createPoint(new Coordinate(p[0], p[1]));
}
theAnchorPoint = currentState.dragMePoint.getCoordinate();
@ -837,7 +841,7 @@ public class StormTrackDisplay implements IRenderable {
}
private void generateExistingTrackInfo(StormTrackState state,
PaintProperties paintProps) throws ImpossibleTrackException {
PaintProperties paintProps) {
int moveIndex = this.trackUtil.getCurrentFrame(paintProps
.getFramesInfo());
moveIndex = Math.min(moveIndex, state.timePoints.length - 1);
@ -995,7 +999,7 @@ public class StormTrackDisplay implements IRenderable {
}
private void generateNewTrackInfo(StormTrackState state, int anchorIndex,
PaintProperties paintProps) throws ImpossibleTrackException {
PaintProperties paintProps) {
double speed, angle, oppositeAngle;
int frameCount = trackUtil.getFrameCount(paintProps.getFramesInfo());
if (state.timePoints != null) {
@ -1194,7 +1198,7 @@ public class StormTrackDisplay implements IRenderable {
int shortestDistance = (int) Math.round(minIntervalInSeconds
* state.speed);
int tickLengthInMeters = (int) Math.round(shortestDistance) / 2;
int tickLengthInMeters = Math.round(shortestDistance) / 2;
// Create track
Coordinate[] coords = new Coordinate[state.timePoints.length
@ -1412,13 +1416,16 @@ public class StormTrackDisplay implements IRenderable {
state.color, radius, 180 + screenAngle, hMid, vMid, magnification);
// End time:
Calendar currentTime = Calendar.getInstance();
currentTime.setTime(SimulatedTime.getSystemTime().getTime());
long delta = state.futurePoints[state.futurePoints.length - 1].time
.getMatchValid()
- state.futurePoints[0].time.getMatchValid();
time = this.timeFormat.format(new Date(currentTime
.getTimeInMillis() + delta));
long endTime = state.futurePoints[state.futurePoints.length - 1].time
.getMatchValid();
if (state.liveOffsetEndTime) {
Calendar currentTime = Calendar.getInstance();
currentTime.setTime(SimulatedTime.getSystemTime().getTime());
long delta = endTime
- state.futurePoints[0].time.getMatchValid();
endTime = currentTime.getTimeInMillis() + delta;
}
time = this.timeFormat.format(new Date(endTime));
paintTextAtPoint(target, time,
state.futurePoints[state.futurePoints.length - 1].coord,
state.color, radius, -90 + screenAngle, hEnd, vEnd, magnification);

View file

@ -31,37 +31,38 @@ import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
/**
* TODO Add Description
* All of the state information needed to display and manipulate a storm track.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07-14-2010 #6558 bkowal Added a variable that will be used
* to indicate when the user manually
* moves the drag-me point. A new method
* has been created to calculate the pivot
* indexes.
* 10-27-2010 #6964 bkowal Added a public class member for the LineStyle.
* 11/29/2012 15571 Qinglu Lin Added compuateCurrentStormCenter();
* 15Mar2013 15693 mgamazaychikov Added magnification.
* 06-24-2013 DR 16317 D. Friedman Handle "motionless" track.
* 04-24-2014 DR 16356 Qinglu Lin Added newWarnGen, oneStormAngle, justSwitchedToLOS,
* justSwitchedToOS, and trackType.
* 06-24-2014 DR 17436 Qinglu Lin Assigned "unknown" to trackType.
*
* Date Ticket# Engineer Description
* ------------- -------- ---------- -------------------------------------------
* Jul 14, 2010 6558 bkowal Added a variable that will be used to
* indicate when the user manually moves the
* drag-me point. A new method has been
* created to calculate the pivot indexes.
* Oct 27, 2010 6964 bkowal Added a public class member for the
* LineStyle.
* Nov 29, 2012 15571 qlin Added compuateCurrentStormCenter();
* Mar 15, 2013 15693 mgamazay Added magnification.
* Jun 24, 2013 16317 dfriedman Handle "motionless" track.
* Apr 24, 2014 16356 qlin Added newWarnGen, oneStormAngle,
* justSwitchedToLOS, justSwitchedToOS, and
* trackType.
* Jun 24, 2014 17436 qlin Assigned "unknown" to trackType.
* Dec 02, 2015 5150 bsteffen Add option to use constant end time.
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class StormTrackState {
public enum Mode {
DRAG_ME, TRACK, NONE
};
}
public enum DisplayType {
POINT("me"), POLY("line"), CIRCULAR("me");
@ -209,6 +210,12 @@ public class StormTrackState {
public boolean justSwitchedToOS = false;
/*
* When true the end time will be adjusted on the display to be offset from
* the current time instead of the last frame.
*/
public boolean liveOffsetEndTime = true;
public static String trackType = "unknown";
/** Compute the coordinate of the storm center at the time defined by dataTime via interpolation. */

View file

@ -39,7 +39,6 @@ import org.opengis.coverage.grid.GridEnvelope;
import com.raytheon.uf.common.geospatial.LocalTimeZone;
import com.raytheon.uf.common.geospatial.SpatialException;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.DrawableCircle;
import com.raytheon.uf.viz.core.DrawableString;
import com.raytheon.uf.viz.core.IDisplayPane;
@ -75,39 +74,45 @@ import com.raytheon.viz.ui.input.EditableManager;
import com.raytheon.viz.ui.input.InputAdapter;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineSegment;
import com.vividsolutions.jts.geom.LineString;
/**
* TODO Add Description
* Layer which contains a configurable storm track as well as a Time Of
* Arrival/Lead Time point. The primary purpose is to display the distance and
* time it would take to reach the lead point following the storm track.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* June 28 2010 #6513 bkowal Switching the mode of the Time of Arrival /
* Lead time tool to Polyline before creating a
* a track will no longer cause the tool to
* crash.
* July 28 2010 #4518 bkowal CDT time will now be displayed in the Time of
* Arrival point label when the scale is
* WFO or State(s).
* Aug 19 2010 #4518 bkowal Instead of CDT time, the users local time
* will be displayed. Progressive Disclosure
* Properties are now used to determine whether
* local time should be displayed or not.
* Oct 19 2010 #6753 bkowal Added logic to change the text alignment from
* left-to-right if there is not enough room
* for the text to the left of the point.
* 15Mar2013 15693 mgamazaychikov Added magnification capability.
* Apr 12 2013 DR 16032 D. Friedman Make it work in multiple panes.
* Aug 14 2014 3523 mapeters Updated deprecated {@link DrawableString#textStyle}
* assignments.
*
* Date Ticket# Engineer Description
* ------------- -------- ---------- -------------------------------------------
* Jun 28, 2010 6513 bkowal Switching the mode of the Time of Arrival /
* Lead time tool to Polyline before creating
* a a track will no longer cause the tool to
* crash.
* Jul 28, 2010 4518 bkowal CDT time will now be displayed in the Time
* of Arrival point label when the scale is
* WFO or State(s).
* Aug 19, 2010 4518 bkowal Instead of CDT time, the users local time
* will be displayed. Progressive Disclosure
* Properties are now used to determine
* whether local time should be displayed or
* not.
* Oct 19, 2010 6753 bkowal Added logic to change the text alignment
* from left-to-right if there is not enough
* room for the text to the left of the point.
* Mar 15, 2013 15693 mgamazay Added magnification capability.
* Apr 12, 2013 16032 dfriedman Make it work in multiple panes.
* Aug 14, 2014 3523 mapeters Updated deprecated DrawableString.textStyle
* assignments.
* Dec 02, 2015 5150 bsteffen Calculate correct lead time for Polylines.
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class TimeOfArrivalLayer extends AbstractStormTrackResource {
public static class LeadTimeState {
@ -122,9 +127,15 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
public boolean changed;
}
/* Thread Dangerous: Must only be used on the "paint" thread. */
private final DateFormat timeFormat = new SimpleDateFormat("HH:mm");
// private DateFormat localTimeFormat = new SimpleDateFormat("HH:mmz");
/*
* Thread Dangerous: Must only be used on the "paint" thread.
*
* The time zone should be set based off the end time before each use.
*/
private final DateFormat localTimeFormat = new SimpleDateFormat("HH:mmz");
private static final String formatString = "%sZ (%s) %s miles";
@ -306,6 +317,8 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
if (displayState.mode == Mode.TRACK) {
if (displayState.displayType == DisplayType.CIRCULAR) {
constructCircularStuff(target);
} else if (displayState.displayType == DisplayType.POLY) {
constructPolyStuff(target);
}
}
}
@ -451,6 +464,44 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
}
}
/**
* Create lines in jazzyExtras that mirror the dragMeLine projected out to
* intersect the lead point. Should only be used when the display type is
* {@link DisplayType#POLY}.
*/
private void constructPolyStuff(IGraphicsTarget target) {
if (jazzyExtras != null) {
jazzyExtras.dispose();
}
jazzyExtras = target.createWireframeShape(false, descriptor);
Coordinate startLonLat = getLeadDragMePoint();
if(startLonLat == null){
return;
}
Coordinate endLonLat = leadState.loc;
double[] startPixel = descriptor.worldToPixel(new double[] {
startLonLat.x, startLonLat.y });
double[] endPixel = descriptor.worldToPixel(new double[] {
endLonLat.x, endLonLat.y });
double dx = endPixel[0] - startPixel[0];
double dy = endPixel[1] - startPixel[1];
LineString fullLine = displayState.dragMeLine;
double[][] pixels = new double[fullLine.getNumPoints()][];
for (int i = 0; i < fullLine.getNumPoints(); i += 1) {
Coordinate c = fullLine.getCoordinateN(i);
pixels[i] = descriptor.worldToPixel(new double[] {
c.x, c.y });
pixels[i][0] += dx;
pixels[i][1] += dy;
}
jazzyExtras.addLineSegment(pixels);
}
private void constructCircularStuff(IGraphicsTarget target)
throws VizException {
@ -550,6 +601,7 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
// Default angle for POINT
displayState.displayType = StormTrackState.DisplayType.POINT;
displayState.labelMode = LabelMode.TIME;
displayState.liveOffsetEndTime = false;
state.angle = 48;
state.dragMePoint = null;
state.dragMeLine = null;
@ -584,7 +636,135 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
});
}
/**
* Determine a point along the dragMeLine that can be combined with the lead
* point to create a line that is perpendicular to the storm track. This is
* the point that is used when determining the distance of the lead point.
* This method will return null if the lead point is too far from the storm
* track so no point exists. Should only be used when the display type is
* {@link DisplayType#POLY}.
*/
private Coordinate getLeadDragMePoint() {
/*
* The input and output points are all in Lon/Lat but all math is
* performed in the descriptor pixel space to minimize the potential for
* projection related problems.
*/
Coordinate startLonLat = displayState.timePoints[0].coord;
Coordinate endLonLat = displayState.timePoints[displayState.timePoints.length - 1].coord;
double[] startPixel = descriptor.worldToPixel(new double[] {
startLonLat.x, startLonLat.y });
double[] endPixel = descriptor.worldToPixel(new double[] { endLonLat.x,
endLonLat.y });
double[] leadPixel = descriptor.worldToPixel(new double[] {
leadState.loc.x, leadState.loc.y });
double dx = leadPixel[0] - endPixel[0];
double dy = leadPixel[1] - endPixel[1];
double[] leadStartPixel = { startPixel[0] + dx, startPixel[1] + dy };
/*
* This is a line that is parallel to the storm track and the same
* distance as the timePoints in the storm track.
*/
LineSegment leadLine = new LineSegment(leadStartPixel[0],
leadStartPixel[1], leadPixel[0], leadPixel[1]);
LineString fullLine = displayState.dragMeLine;
Coordinate c = fullLine.getCoordinateN(0);
double[] prevPixel = descriptor.worldToPixel(new double[] { c.x, c.y });
Coordinate bestIntersection = null;
for (int i = 1; i < fullLine.getNumPoints(); i += 1) {
c = fullLine.getCoordinateN(i);
double[] currPixel = descriptor.worldToPixel(new double[] { c.x,
c.y });
LineSegment segment = new LineSegment(prevPixel[0], prevPixel[1],
currPixel[0], currPixel[1]);
/*
* The leadLine may not be long enough to reach from the lead point
* to the dragMeLine so must use lineIntersection to extend both
* segments infinitely
*/
Coordinate intersection = segment.lineIntersection(leadLine);
/*
* lineIntersection may extends both lines but only an intersection
* that is actually on the segment is valid so ensure that the
* intersection point is reasonably close to the segment.
*/
if (segment.distance(intersection) < 0.0000001) {
/*
* If the dragMeLine is complex thre can be multiple
* intersections, only keep the closest one.
*/
if (bestIntersection == null) {
bestIntersection = intersection;
} else if (bestIntersection.distance(new Coordinate(
leadPixel[0], leadPixel[1])) > intersection
.distance(new Coordinate(leadPixel[0], leadPixel[1]))) {
bestIntersection = intersection;
}
}
prevPixel = currPixel;
}
if (bestIntersection != null) {
double[] intersectionLonLat = descriptor.pixelToWorld(new double[] {
bestIntersection.x, bestIntersection.y });
return new Coordinate(intersectionLonLat[0], intersectionLonLat[1]);
}
return bestIntersection;
}
/**
* Determine the distance(in meters) from the lead point to the current
* point, line, or front. This is the distance displayed in the lead time
* text. This method will return Double.NaN if the lead point is
* unrealistic.
*/
private double getLeadDistance() {
GeodeticCalculator gc = new GeodeticCalculator();
if (displayState.displayType == DisplayType.POLY) {
Coordinate dragMe = getLeadDragMePoint();
if (dragMe == null) {
return Double.NaN;
}
gc.setStartingGeographicPoint(dragMe.x, dragMe.y);
gc.setDestinationGeographicPoint(leadState.loc.x, leadState.loc.y);
double distance = gc.getOrthodromicDistance();
double angle = unadjustAngle(gc.getAzimuth());
double stateAngle = unadjustAngle(displayState.angle);
if(Math.abs(angle - stateAngle) > 180){
distance = -1*distance;
}
return distance;
}else{
StormCoord start = displayState.timePoints[0];
Coordinate end = displayState.timePoints[displayState.timePoints.length - 1].coord;
gc.setStartingGeographicPoint(start.coord.x, start.coord.y);
gc.setDestinationGeographicPoint(end.x, end.y);
double distFromStartEnd = gc.getOrthodromicDistance();
end = leadState.loc;
gc.setDestinationGeographicPoint(end.x, end.y);
double angle = unadjustAngle(gc.getAzimuth());
double stateAngle = unadjustAngle(displayState.angle);
double distance = gc.getOrthodromicDistance();
if (Math.abs(angle - stateAngle) >= 22.5) {
return Double.NaN;
}else{
return distance
- distFromStartEnd;
}
}
}
private void updateLeadTimeState() {
leadState.changed = false;
// based on display state and lead time location, figure out distance,
// duration, and time
@ -592,94 +772,69 @@ public class TimeOfArrivalLayer extends AbstractStormTrackResource {
return;
}
// First get Time from start point
StormCoord start = displayState.timePoints[0];
Coordinate end = displayState.timePoints[displayState.timePoints.length - 1].coord;
GeodeticCalculator gc = new GeodeticCalculator();
gc.setStartingGeographicPoint(start.coord.x, start.coord.y);
gc.setDestinationGeographicPoint(end.x, end.y);
double distFromStartEnd = gc.getOrthodromicDistance();
end = leadState.loc;
gc.setDestinationGeographicPoint(end.x, end.y);
double angle = unadjustAngle(gc.getAzimuth());
double stateAngle = unadjustAngle(displayState.angle);
double distance = gc.getOrthodromicDistance();
leadState.distance = distance;
// TODO: Figure out point on line and distance to line if in POLY mode
// and set distance accordingly, then uncomment TODO in constructLines
if (Math.abs(angle - stateAngle) >= 22.5) {
double distance = getLeadDistance();
if (Double.isNaN(distance)) {
leadState.text = "Unrealistic Point of Arrival";
} else {
long timeInSec = (long) (distance / displayState.speed);
DataTime toa = new DataTime(new Date(start.time.getMatchValid()
+ (timeInSec * 1000)));
Date date = new Date(toa.getMatchValid());
Date refDate = new Date(
displayState.timePoints[displayState.timePoints.length - 1].time
.getMatchValid());
boolean negative = date.getTime() < refDate.getTime();
String miles = "";
String hoursMinutesFormat = "";
if (negative) {
hoursMinutesFormat += "-";
miles += "-";
}
long timeDiffInMinutes = Math.abs(date.getTime()
- refDate.getTime())
/ (60 * 1000);
long hours = timeDiffInMinutes / 60;
long minutes = timeDiffInMinutes % 60;
Object[] args = new Object[2];
if (hours > 0) {
hoursMinutesFormat += "%02d hours ";
args[0] = hours;
args[1] = minutes;
} else {
args[0] = minutes;
}
hoursMinutesFormat += "%02d minutes";
miles += (int) metersToMiles.convert(Math.abs(distance
- distFromStartEnd));
String time = this.timeFormat.format(date);
int currentDisplayWidth = ((IMapDescriptor) this.descriptor)
.getMapWidth();
if (!this.pdProps.isDisclosed(currentDisplayWidth)) {
// Do not include Local time
leadState.text = String.format(formatString, time,
String.format(hoursMinutesFormat, args), miles);
} else {
// Include Local time
String localTime = ""; // this.localTimeFormat.format(date);
try {
DateFormat df = new SimpleDateFormat("HH:mmz");
// System.err.println(end.x + " " + end.y);
df.setTimeZone(LocalTimeZone.getLocalTimeZone(end));
localTime = df.format(date);
} catch (SpatialException e) {
e.printStackTrace();
}
leadState.text = String.format(
TimeOfArrivalLayer.formatStringIncludeLocal, time,
localTime, String.format(hoursMinutesFormat, args),
miles);
}
return;
}
StormCoord endStormCoord = displayState.timePoints[displayState.timePoints.length - 1];
Date refDate = endStormCoord.time.getValidTimeAsDate();
long timeInSec = (long) (distance / displayState.speed);
Date date = new Date(refDate.getTime() + (timeInSec * 1000));
boolean negative = date.getTime() < refDate.getTime();
String miles = "";
String hoursMinutesFormat = "";
if (negative) {
hoursMinutesFormat += "-";
miles += "-";
}
long timeDiffInMinutes = Math.abs(date.getTime() - refDate.getTime())
/ (60 * 1000);
long hours = timeDiffInMinutes / 60;
long minutes = timeDiffInMinutes % 60;
Object[] args = new Object[2];
if (hours > 0) {
hoursMinutesFormat += "%02d hours ";
args[0] = hours;
args[1] = minutes;
} else {
args[0] = minutes;
}
hoursMinutesFormat += "%02d minutes";
miles += (int) metersToMiles.convert(Math.abs(distance));
String time = this.timeFormat.format(date);
int currentDisplayWidth = ((IMapDescriptor) this.descriptor)
.getMapWidth();
if (!this.pdProps.isDisclosed(currentDisplayWidth)) {
// Do not include Local time
leadState.text = String.format(formatString, time,
String.format(hoursMinutesFormat, args), miles);
} else {
// Include Local time
String localTime = "";
try {
Coordinate end = endStormCoord.coord;
localTimeFormat
.setTimeZone(LocalTimeZone.getLocalTimeZone(end));
localTime = localTimeFormat.format(date);
} catch (SpatialException e) {
e.printStackTrace();
}
leadState.text = String.format(
TimeOfArrivalLayer.formatStringIncludeLocal, time,
localTime, String.format(hoursMinutesFormat, args), miles);
}
leadState.changed = false;
}
public void makeEditableAndReopenDialog() {