mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-15 16:51:07 +00:00
Merge remote-tracking branch 'origin/simulator_dev' into simulator_dev
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorMap.java
This commit is contained in:
commit
ab13e3602e
6 files changed
+328
-129
No files matched your search
+11
-11
@@ -38,9 +38,9 @@ import com.sap.sailing.gwt.ui.shared.RequestPolarDiagramDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SimulatedPathsEvenTimedResultDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SimulatorResultsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SimulatorResultsDTOAndNotificationMessage;
|
||||
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SpeedBearingPositionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SimulatorWindDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindFieldDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindFieldGenParamsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindLatticeDTO;
|
||||
@@ -327,14 +327,14 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
|
||||
|
||||
windFieldDTO.setMatrix(wList);
|
||||
if (isShowLines) {
|
||||
|
||||
|
||||
if (seedLines == 'f') {
|
||||
getWindLinesFromStartLine(wf, windFieldDTO, startTime, endTime, timeStep);
|
||||
}
|
||||
if (seedLines == 'b') {
|
||||
getWindLinesFromEndLine(wf, windFieldDTO, startTime, endTime, timeStep);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return windFieldDTO;
|
||||
}
|
||||
@@ -352,9 +352,9 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
|
||||
for (int j = 1; j < positionGrid[0].length - 1; ++j) {
|
||||
// for (int j = 0; j < positionGrid[0].length; ++j) {
|
||||
TimePoint t = startTime;
|
||||
Position p0 = positionGrid[0][j];
|
||||
Position p1 = positionGrid[1][j];
|
||||
Position seed = new DegreePosition(p0.getLatDeg() + 0.5*(p0.getLatDeg()-p1.getLatDeg()), p0.getLngDeg() + 0.5*(p0.getLngDeg()-p1.getLngDeg()));
|
||||
final Position p0 = positionGrid[0][j];
|
||||
final Position p1 = positionGrid[1][j];
|
||||
final Position seed = new DegreePosition(p0.getLatDeg() + 0.5*(p0.getLatDeg()-p1.getLatDeg()), p0.getLngDeg() + 0.5*(p0.getLngDeg()-p1.getLngDeg()));
|
||||
final PositionDTO startPosition = new PositionDTO(seed.getLatDeg(), seed.getLngDeg());
|
||||
while (t.compareTo(endTime) <= 0) {
|
||||
final TimedPosition tp = new TimedPositionImpl(t, seed);
|
||||
@@ -392,9 +392,9 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
|
||||
for (int j = 1; j < positionGrid[lastRowIndex].length - 1; ++j) {
|
||||
|
||||
TimePoint t = startTime;
|
||||
Position p0 = positionGrid[lastRowIndex][j];
|
||||
Position p1 = positionGrid[lastRowIndex-1][j];
|
||||
Position seed = new DegreePosition(p0.getLatDeg() + 0.5*(p0.getLatDeg()-p1.getLatDeg()), p0.getLngDeg() + 0.5*(p0.getLngDeg()-p1.getLngDeg()));
|
||||
final Position p0 = positionGrid[lastRowIndex][j];
|
||||
final Position p1 = positionGrid[lastRowIndex-1][j];
|
||||
final Position seed = new DegreePosition(p0.getLatDeg() + 0.5*(p0.getLatDeg()-p1.getLatDeg()), p0.getLngDeg() + 0.5*(p0.getLngDeg()-p1.getLngDeg()));
|
||||
final PositionDTO startPosition = new PositionDTO(seed.getLatDeg(), seed.getLngDeg());
|
||||
while (t.compareTo(endTime) <= 0) {
|
||||
final TimedPosition tp = new TimedPositionImpl(t, seed);
|
||||
@@ -466,7 +466,7 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
|
||||
final List<TimedPositionWithSpeed> path = paths.get(pathName);
|
||||
|
||||
// TODO: cleanup getAllPathsEvenTimed to return Paths instead of PathPoints
|
||||
if (pathName.equals("6#GPS Poly")) {
|
||||
if (pathName.equals("6#GPS Poly") || pathName.equals("7#GPS Track")) {
|
||||
// special initialization for polyline
|
||||
pathDTO[pathIndex] = this.convertToPathDTOAndMarkTurns(new PathImpl(paths.get(pathName), null), pathName.split("#")[1]);
|
||||
|
||||
@@ -784,7 +784,7 @@ public class SimulatorServiceImpl extends RemoteServiceServlet implements Simula
|
||||
|
||||
speeds.add(new SpeedBearingPositionDTO(positionDTO,
|
||||
new SpeedWithBearingDTO(speedWithBearing.getKnots(),
|
||||
speedWithBearing.getBearing().getDegrees())));
|
||||
speedWithBearing.getBearing().getDegrees())));
|
||||
}
|
||||
|
||||
return new ReceivePolarDiagramDataDTO(speeds, polarDiagramAndNotificationMessage.getNotificationMesssage());
|
||||
|
||||
+38
-8
@@ -4,19 +4,49 @@ import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class SimulatorWindDTO implements IsSerializable {
|
||||
public boolean isTurn;
|
||||
//public Double trueWindSpeedInMetersPerSecond;
|
||||
public Double trueWindSpeedInKnots;
|
||||
public Double trueWindBearingDeg;
|
||||
//public Double trueWindFromDeg;
|
||||
//public Double dampenedTrueWindSpeedInMetersPerSecond;
|
||||
//public Double dampenedTrueWindSpeedInKnots;
|
||||
//public Double dampenedTrueWindBearingDeg;
|
||||
//public Double dampenedTrueWindFromDeg;
|
||||
public PositionDTO position;
|
||||
public Long timepoint;
|
||||
//public Long originTimepoint;
|
||||
//public Double confidence;
|
||||
|
||||
public SimulatorWindDTO() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
|
||||
long temp = 0;
|
||||
|
||||
temp = this.trueWindSpeedInKnots.intValue();
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
|
||||
temp = this.trueWindBearingDeg.intValue();
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
|
||||
temp = this.timepoint.intValue();
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
|
||||
temp = this.position.hashCode();
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
} else {
|
||||
if (o instanceof SimulatorWindDTO) {
|
||||
final SimulatorWindDTO other = (SimulatorWindDTO) o;
|
||||
|
||||
return this.position.equals(other.position) && (Math.abs(this.timepoint - other.timepoint) < 9999);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+90
-60
@@ -3,7 +3,6 @@ package com.sap.sailing.gwt.ui.simulator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.gwt.canvas.dom.client.Context2d;
|
||||
import com.google.gwt.i18n.client.DateTimeFormat;
|
||||
@@ -33,13 +32,15 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
*/
|
||||
private static final long serialVersionUID = -6284996043723173190L;
|
||||
|
||||
private static Logger logger = Logger.getLogger(PathCanvasOverlay.class.getName());
|
||||
|
||||
// private static Logger logger = Logger.getLogger(PathCanvasOverlay.class.getName());
|
||||
|
||||
private static final int MinimumPxDistanceBetweenArrows = 60;
|
||||
|
||||
|
||||
private LatLng startPoint;
|
||||
private LatLng endPoint;
|
||||
|
||||
private boolean totalTimeIsGiven = false;
|
||||
private long totalTimeMilliseconds = 0;
|
||||
|
||||
protected String name;
|
||||
|
||||
public String pathColor = "Green";
|
||||
@@ -48,21 +49,44 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
*/
|
||||
public boolean displayWindAlongPath = true;
|
||||
|
||||
public PathCanvasOverlay(String name) {
|
||||
public PathCanvasOverlay(final String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public PathCanvasOverlay(String name, Timer timer) {
|
||||
|
||||
public PathCanvasOverlay(final String name, final Timer timer) {
|
||||
super(timer);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setRaceCourse(LatLng startPoint, LatLng endPoint) {
|
||||
this.startPoint = startPoint;
|
||||
this.endPoint = endPoint;
|
||||
|
||||
public PathCanvasOverlay(final String name, final long totalTimeMilliseconds) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.totalTimeIsGiven = true;
|
||||
this.totalTimeMilliseconds = totalTimeMilliseconds;
|
||||
}
|
||||
|
||||
|
||||
public PathCanvasOverlay(final String name, final Timer timer, final long totalTimeMilliseconds) {
|
||||
super(timer);
|
||||
this.name = name;
|
||||
this.totalTimeIsGiven = true;
|
||||
this.totalTimeMilliseconds = totalTimeMilliseconds;
|
||||
}
|
||||
|
||||
public void setTotalTimeMilliseconds(final long totalTimeMilliseconds) {
|
||||
this.totalTimeIsGiven = true;
|
||||
this.totalTimeMilliseconds = totalTimeMilliseconds;
|
||||
}
|
||||
|
||||
public long getTotalTimeMilliseconds() {
|
||||
return this.totalTimeMilliseconds;
|
||||
}
|
||||
|
||||
public void setRaceCourse(final LatLng startPoint, final LatLng endPoint) {
|
||||
this.startPoint = startPoint;
|
||||
this.endPoint = endPoint;
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
protected void drawWindField() {
|
||||
@@ -71,41 +95,43 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
drawWindField(windDTOList);
|
||||
}
|
||||
*/
|
||||
@Override
|
||||
protected void drawWindField(final List<SimulatorWindDTO> windDTOList) {
|
||||
|
||||
WindFieldGenParamsDTO windParams = new WindFieldGenParamsDTO();
|
||||
final WindFieldGenParamsDTO windParams = new WindFieldGenParamsDTO();
|
||||
|
||||
int numPoints = windDTOList.size();
|
||||
final int numPoints = windDTOList.size();
|
||||
if (numPoints < 1) {
|
||||
return;
|
||||
}
|
||||
String title = "Path at " + numPoints + " points.";
|
||||
long totalTime = windDTOList.get(numPoints - 1).timepoint - windDTOList.get(0).timepoint;
|
||||
final long totalTime = windDTOList.get(numPoints - 1).timepoint - windDTOList.get(0).timepoint;
|
||||
|
||||
//LatLng start = LatLng.newInstance(windDTOList.get(0).position.latDeg, windDTOList.get(0).position.latDeg);
|
||||
//LatLng end = LatLng.newInstance(windDTOList.get(numPoints - 1).position.latDeg, windDTOList.get(numPoints - 1).position.latDeg);
|
||||
|
||||
double distance = startPoint.distanceFrom(endPoint) / Mile.METERS_PER_NAUTICAL_MILE;
|
||||
final double distance = startPoint.distanceFrom(endPoint) / Mile.METERS_PER_NAUTICAL_MILE;
|
||||
|
||||
Point startPx = getMap().convertLatLngToDivPixel(startPoint);
|
||||
Point endPx = getMap().convertLatLngToDivPixel(endPoint);
|
||||
double rcLengthPx = Math.sqrt(Math.pow(startPx.getX() - endPx.getX(), 2) + Math.pow(startPx.getY() - endPx.getY(), 2));
|
||||
//System.out.println("Race Course Pixel Length: "+rcLengthPx);
|
||||
// final Point startPx = getMap().convertLatLngToDivPixel(startPoint);
|
||||
// final Point endPx = getMap().convertLatLngToDivPixel(endPoint);
|
||||
// final double rcLengthPx = Math.sqrt(Math.pow(startPx.getX() - endPx.getX(), 2) + Math.pow(startPx.getY() -
|
||||
// endPx.getY(), 2));
|
||||
// System.out.println("Race Course Pixel Length: "+rcLengthPx);
|
||||
|
||||
double arrowDistPx = 60;
|
||||
long arrowInterleave = Math.max(1, Math.round(arrowDistPx * numPoints / rcLengthPx));
|
||||
// final double arrowDistPx = 60;
|
||||
// final long arrowInterleave = Math.max(1, Math.round(arrowDistPx * numPoints / rcLengthPx));
|
||||
// System.out.print("Arrow Interleave: "+arrowInterleave+"\n");
|
||||
//arrowInterleave = 3;
|
||||
|
||||
// arrowInterleave = 3;
|
||||
|
||||
if (windDTOList != null && windDTOList.size() > 0) {
|
||||
|
||||
Context2d context2d = canvas.getContext2d();
|
||||
final Context2d context2d = canvas.getContext2d();
|
||||
context2d.setGlobalAlpha(0.8);
|
||||
|
||||
Iterator<SimulatorWindDTO> windDTOIter = windDTOList.iterator();
|
||||
SimulatorWindDTO prevWindDTO = null;
|
||||
while (windDTOIter.hasNext()) {
|
||||
SimulatorWindDTO windDTO = windDTOIter.next();
|
||||
final SimulatorWindDTO windDTO = windDTOIter.next();
|
||||
if (prevWindDTO != null) {
|
||||
drawLine(prevWindDTO, windDTO);
|
||||
}
|
||||
@@ -114,24 +140,24 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
|
||||
windDTOIter = windDTOList.iterator();
|
||||
int index = 0;
|
||||
long startTime = windDTOList.get(0).timepoint;
|
||||
final long startTime = windDTOList.get(0).timepoint;
|
||||
prevWindDTO = null; //For the last time arrow was displayed
|
||||
while (windDTOIter.hasNext()) {
|
||||
SimulatorWindDTO windDTO = windDTOIter.next();
|
||||
final SimulatorWindDTO windDTO = windDTOIter.next();
|
||||
|
||||
//if ((displayWindAlongPath) && ((index % arrowInterleave) == 0)) {
|
||||
if (displayWindAlongPath) {
|
||||
if (checkPointsAreFarEnough(windDTO,prevWindDTO)) {
|
||||
DegreeBearingImpl dbi = new DegreeBearingImpl(windDTO.trueWindBearingDeg);
|
||||
// System.out.print("index: "+index+"\n");
|
||||
|
||||
final DegreeBearingImpl dbi = new DegreeBearingImpl(windDTO.trueWindBearingDeg);
|
||||
// System.out.print("index: "+index+"\n");
|
||||
|
||||
drawScaledArrow(windDTO, dbi.getRadians(), index, true);
|
||||
prevWindDTO = windDTO;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
|
||||
long timeStep = windParams.getTimeStep().getTime();
|
||||
final long timeStep = windParams.getTimeStep().getTime();
|
||||
if ((windDTO.timepoint - startTime) % (timeStep) == 0) {
|
||||
drawPoint(windDTO);
|
||||
}
|
||||
@@ -141,8 +167,8 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
context2d.setGlobalAlpha(1.0);
|
||||
|
||||
// MeterDistance meterDistance = new MeterDistance(distance);
|
||||
Date timeDiffDate = new Date(totalTime);
|
||||
TimeZone gmt = TimeZone.createTimeZone(0);
|
||||
final Date timeDiffDate = new Date(totalTime);
|
||||
final TimeZone gmt = TimeZone.createTimeZone(0);
|
||||
title += " " + NumberFormat.getFormat("0.00").format(distance) + " nmi";
|
||||
title += " in " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.HOUR24_MINUTE_SECOND).format(timeDiffDate, gmt);
|
||||
|
||||
@@ -151,23 +177,23 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawLine(SimulatorWindDTO p1, SimulatorWindDTO p2) {
|
||||
private void drawLine(final SimulatorWindDTO p1, final SimulatorWindDTO p2) {
|
||||
|
||||
double weight = 3.0;
|
||||
final double weight = 3.0;
|
||||
|
||||
PositionDTO position = p1.position;
|
||||
|
||||
LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
Point canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
|
||||
int x1 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
int y1 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
final int x1 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
final int y1 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
|
||||
position = p2.position;
|
||||
positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
int x2 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
int y2 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
final int x2 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
final int y2 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
|
||||
// Context2d context2d = canvas.getContext2d();
|
||||
// context2d.setShadowBlur(weight);
|
||||
@@ -176,17 +202,17 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
// System.out.print("x1:"+x1+" y1:"+y1+" x2:"+x2+" y2:"+y2+"\n");
|
||||
}
|
||||
|
||||
private void drawPoint(SimulatorWindDTO p) {
|
||||
private void drawPoint(final SimulatorWindDTO p) {
|
||||
|
||||
double weight = 3.0;
|
||||
final double weight = 3.0;
|
||||
|
||||
PositionDTO position = p.position;
|
||||
final PositionDTO position = p.position;
|
||||
|
||||
LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
Point canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
final LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
final Point canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
|
||||
int x1 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
int y1 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
final int x1 = canvasPositionInPx.getX() - this.getWidgetPosLeft();
|
||||
final int y1 = canvasPositionInPx.getY() - this.getWidgetPosTop();
|
||||
|
||||
drawCircle(x1, y1, weight / 2., pathColor);
|
||||
}
|
||||
@@ -196,7 +222,7 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
* @return true if the pixel distance between the two points is greater than
|
||||
* a threshold. returns true if either of the points is null
|
||||
*/
|
||||
private boolean checkPointsAreFarEnough(SimulatorWindDTO p1, SimulatorWindDTO p2) {
|
||||
private boolean checkPointsAreFarEnough(final SimulatorWindDTO p1, final SimulatorWindDTO p2) {
|
||||
if (p1 == null || p2 == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -205,32 +231,36 @@ public class PathCanvasOverlay extends WindFieldCanvasOverlay implements Named {
|
||||
LatLng positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
Point canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
|
||||
int x1 = canvasPositionInPx.getX();
|
||||
int y1 = canvasPositionInPx.getY();
|
||||
final int x1 = canvasPositionInPx.getX();
|
||||
final int y1 = canvasPositionInPx.getY();
|
||||
|
||||
position = p2.position;
|
||||
positionLatLng = LatLng.newInstance(position.latDeg, position.lngDeg);
|
||||
canvasPositionInPx = getMap().convertLatLngToDivPixel(positionLatLng);
|
||||
int x2 = canvasPositionInPx.getX();
|
||||
int y2 = canvasPositionInPx.getY();
|
||||
final int x2 = canvasPositionInPx.getX();
|
||||
final int y2 = canvasPositionInPx.getY();
|
||||
|
||||
double pxDistance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
||||
final double pxDistance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
||||
if (pxDistance >= MinimumPxDistanceBetweenArrows) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getPathTime() {
|
||||
List<SimulatorWindDTO> windDTOList = wl.getMatrix();
|
||||
int numPoints = windDTOList.size();
|
||||
long totalTime = windDTOList.get(numPoints - 1).timepoint - windDTOList.get(0).timepoint;
|
||||
return totalTime;
|
||||
if (this.totalTimeIsGiven) {
|
||||
return this.totalTimeMilliseconds;
|
||||
} else {
|
||||
final List<SimulatorWindDTO> windDTOList = wl.getMatrix();
|
||||
final int numPoints = windDTOList.size();
|
||||
final long totalTime = windDTOList.get(numPoints - 1).timepoint - windDTOList.get(0).timepoint;
|
||||
return totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
-28
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.gwt.ui.simulator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -38,7 +39,7 @@ public class PathLegendCanvasOverlay extends CanvasOverlay {
|
||||
|
||||
public String textColor = "Black";
|
||||
public String textFont = "normal 10pt UbuntuRegular";
|
||||
|
||||
|
||||
public PathLegendCanvasOverlay() {
|
||||
this.setPathOverlays(null);
|
||||
}
|
||||
@@ -49,46 +50,46 @@ public class PathLegendCanvasOverlay extends CanvasOverlay {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void redraw(boolean force) {
|
||||
|
||||
protected void redraw(final boolean force) {
|
||||
|
||||
if (pathOverlays == null || pathOverlays.size() < 1) {
|
||||
return;
|
||||
}
|
||||
setCanvasSettings();
|
||||
int index = 0;
|
||||
Context2d context2d = canvas.getContext2d();
|
||||
final Context2d context2d = canvas.getContext2d();
|
||||
context2d.setFont(textFont);
|
||||
TextMetrics txtmet;
|
||||
txtmet = context2d.measureText("00:00:00");
|
||||
double timewidth = txtmet.getWidth();
|
||||
final double timewidth = txtmet.getWidth();
|
||||
double txtmaxwidth = 0.0;
|
||||
for (PathCanvasOverlay path : pathOverlays) {
|
||||
txtmet = context2d.measureText(path.name);
|
||||
txtmaxwidth = Math.max(txtmaxwidth, txtmet.getWidth());
|
||||
for (final PathCanvasOverlay path : pathOverlays) {
|
||||
txtmet = context2d.measureText(path.name);
|
||||
txtmaxwidth = Math.max(txtmaxwidth, txtmet.getWidth());
|
||||
}
|
||||
for (PathCanvasOverlay path : pathOverlays) {
|
||||
drawRectangleWithText(xOffset, yOffset + (pathOverlays.size()-1-index) * rectHeight, path.pathColor,
|
||||
for (final PathCanvasOverlay path : pathOverlays) {
|
||||
drawRectangleWithText(xOffset, yOffset + (pathOverlays.size()-1-index) * rectHeight, path.pathColor,
|
||||
path.name, getFormattedTime(path.getPathTime()),txtmaxwidth,timewidth);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setCanvasSettings() {
|
||||
int canvasWidth = (int) rectWidth + 200;
|
||||
int canvasHeight = getMap().getSize().getHeight();
|
||||
final int canvasWidth = (int) rectWidth + 200;
|
||||
final int canvasHeight = getMap().getSize().getHeight();
|
||||
|
||||
canvas.setWidth(String.valueOf(canvasWidth));
|
||||
canvas.setHeight(String.valueOf(canvasHeight));
|
||||
canvas.setCoordinateSpaceWidth(canvasWidth);
|
||||
canvas.setCoordinateSpaceHeight(canvasHeight);
|
||||
|
||||
Point sw = getMap().convertLatLngToDivPixel(getMap().getBounds().getSouthWest());
|
||||
Point ne = getMap().convertLatLngToDivPixel(getMap().getBounds().getNorthEast());
|
||||
final Point sw = getMap().convertLatLngToDivPixel(getMap().getBounds().getSouthWest());
|
||||
final Point ne = getMap().convertLatLngToDivPixel(getMap().getBounds().getNorthEast());
|
||||
setWidgetPosLeft(Math.min(sw.getX(), ne.getX()));
|
||||
setWidgetPosTop(Math.min(sw.getY(), ne.getY()));
|
||||
//setWidgetPosLeft(xOffset);
|
||||
//setWidgetPosTop(yOffset);
|
||||
|
||||
|
||||
getPane().setWidgetPosition(getCanvas(), getWidgetPosLeft(), getWidgetPosTop());
|
||||
|
||||
}
|
||||
@@ -97,15 +98,39 @@ public class PathLegendCanvasOverlay extends CanvasOverlay {
|
||||
return pathOverlays;
|
||||
}
|
||||
|
||||
public void setPathOverlays(List<PathCanvasOverlay> pathOverlays) {
|
||||
public void setPathOverlays(final List<PathCanvasOverlay> pathOverlays) {
|
||||
|
||||
this.pathOverlays = pathOverlays;
|
||||
}
|
||||
|
||||
public void addPathOverlay(final PathCanvasOverlay pathOverlay) {
|
||||
|
||||
if (this.pathOverlays == null) {
|
||||
this.pathOverlays = new ArrayList<PathCanvasOverlay>();
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
if (pathOverlay.name.equals("Polyline")) {
|
||||
for (final PathCanvasOverlay overlay : this.pathOverlays) {
|
||||
if (overlay.name.equals("Polyline")) {
|
||||
overlay.setTotalTimeMilliseconds(pathOverlay.getTotalTimeMilliseconds());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false) {
|
||||
this.pathOverlays.add(pathOverlay);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidgetPosLeft() {
|
||||
return widgetPosLeft;
|
||||
}
|
||||
|
||||
public void setWidgetPosLeft(int widgetPosLeft) {
|
||||
public void setWidgetPosLeft(final int widgetPosLeft) {
|
||||
this.widgetPosLeft = widgetPosLeft;
|
||||
}
|
||||
|
||||
@@ -113,23 +138,23 @@ public class PathLegendCanvasOverlay extends CanvasOverlay {
|
||||
return widgetPosTop;
|
||||
}
|
||||
|
||||
public void setWidgetPosTop(int widgetPosTop) {
|
||||
public void setWidgetPosTop(final int widgetPosTop) {
|
||||
this.widgetPosTop = widgetPosTop;
|
||||
}
|
||||
|
||||
protected void drawRectangle(double x, double y, String color) {
|
||||
Context2d context2d = canvas.getContext2d();
|
||||
protected void drawRectangle(final double x, final double y, final String color) {
|
||||
final Context2d context2d = canvas.getContext2d();
|
||||
context2d.setFillStyle(color);
|
||||
context2d.setLineWidth(3);
|
||||
context2d.fillRect(x, y, rectWidth, rectHeight);
|
||||
|
||||
}
|
||||
|
||||
protected void drawRectangleWithText(double x, double y, String color, String text, String time, double textmaxwidth, double timewidth) {
|
||||
protected void drawRectangleWithText(final double x, final double y, final String color, final String text, final String time, final double textmaxwidth, final double timewidth) {
|
||||
|
||||
double offset = 3.0;
|
||||
|
||||
Context2d context2d = canvas.getContext2d();
|
||||
final double offset = 3.0;
|
||||
|
||||
final Context2d context2d = canvas.getContext2d();
|
||||
context2d.setFont(textFont);
|
||||
drawRectangle(x, y, color);
|
||||
context2d.setGlobalAlpha(0.80);
|
||||
@@ -141,10 +166,10 @@ public class PathLegendCanvasOverlay extends CanvasOverlay {
|
||||
context2d.fillText(time, x + rectWidth + textmaxwidth + 10.0, y + 12.0 + offset);
|
||||
}
|
||||
|
||||
protected String getFormattedTime(long pathTime) {
|
||||
TimeZone gmt = TimeZone.createTimeZone(0);
|
||||
Date timeDiffDate = new Date(pathTime);
|
||||
String pathTimeStr = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.HOUR24_MINUTE_SECOND).format(
|
||||
protected String getFormattedTime(final long pathTime) {
|
||||
final TimeZone gmt = TimeZone.createTimeZone(0);
|
||||
final Date timeDiffDate = new Date(pathTime);
|
||||
final String pathTimeStr = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.HOUR24_MINUTE_SECOND).format(
|
||||
timeDiffDate, gmt);
|
||||
return pathTimeStr;
|
||||
}
|
||||
|
||||
+19
-12
@@ -16,7 +16,6 @@ import com.google.gwt.maps.client.overlay.Polyline;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SimulatorServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.PathDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.PositionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.ReceivePolarDiagramDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RequestPolarDiagramDataDTO;
|
||||
@@ -33,7 +32,7 @@ public class PathPolyline {
|
||||
private static final boolean SHOULD_DRAW_VERTICAL_DASHLINES = true;
|
||||
private static final boolean SHOULD_DRAW_SHADOW_DASHLINES = false;
|
||||
|
||||
private static final String DEFAULT_COLOR = "#8B0000";
|
||||
public static final String DEFAULT_COLOR = "#8B0000";
|
||||
private static final int DEFAULT_WEIGHT = 3;
|
||||
private static final double DEFAULT_OPACITY = 1.0;
|
||||
private static final double DEFAULT_DISTANCE_PX = 25;
|
||||
@@ -61,7 +60,7 @@ public class PathPolyline {
|
||||
private SpeedWithBearingDTO averageWindSpeed;
|
||||
|
||||
private final int boatClassID;
|
||||
private final PathDTO pathDTO;
|
||||
private final List<SimulatorWindDTO> pathPoints;
|
||||
private final SimulatorServiceAsync simulatorService;
|
||||
private final MapWidget map;
|
||||
private final ErrorReporter errorReporter;
|
||||
@@ -69,17 +68,20 @@ public class PathPolyline {
|
||||
|
||||
private boolean firstTime = true;
|
||||
|
||||
private SimulatorMap simulatorMap = null;
|
||||
|
||||
// private double stepSizeMeters = 5.0;
|
||||
|
||||
// private static Logger logger = Logger.getLogger(PathPolyline.class.getName());
|
||||
|
||||
public PathPolyline(final LatLng[] points, final int boatClassID, final ErrorReporter errorReporter, final PathDTO pathDTO,
|
||||
final SimulatorServiceAsync simulatorService, final MapWidget map) {
|
||||
this(points, DEFAULT_COLOR, DEFAULT_WEIGHT, DEFAULT_OPACITY, boatClassID, errorReporter, pathDTO, simulatorService, map);
|
||||
public PathPolyline(final LatLng[] points, final int boatClassID, final ErrorReporter errorReporter, final List<SimulatorWindDTO> pathPoints,
|
||||
final SimulatorServiceAsync simulatorService, final MapWidget map, final SimulatorMap simulatorMap) {
|
||||
this(points, DEFAULT_COLOR, DEFAULT_WEIGHT, DEFAULT_OPACITY, boatClassID, errorReporter, pathPoints, simulatorService, map, simulatorMap);
|
||||
}
|
||||
|
||||
public PathPolyline(final LatLng[] points, final String color, final int weight, final double opacity, final int boatClassID,
|
||||
final ErrorReporter errorReporter, final PathDTO pathDTO, final SimulatorServiceAsync simulatorService, final MapWidget map) {
|
||||
final ErrorReporter errorReporter, final List<SimulatorWindDTO> pathPoints, final SimulatorServiceAsync simulatorService, final MapWidget map,
|
||||
final SimulatorMap simulatorMap) {
|
||||
this.points = points;
|
||||
this.color = color;
|
||||
this.weight = weight;
|
||||
@@ -89,13 +91,15 @@ public class PathPolyline {
|
||||
this.originAndHeads = new HashMap<TwoDPoint, List<TwoDPoint>>();
|
||||
this.shadowPoints = new ArrayList<LatLng>();
|
||||
|
||||
this.pathDTO = pathDTO;
|
||||
this.pathPoints = pathPoints;
|
||||
this.simulatorService = simulatorService;
|
||||
this.map = map;
|
||||
this.averageWindSpeed = new SpeedWithBearingDTO();
|
||||
this.boatClassID = boatClassID;
|
||||
this.errorReporter = errorReporter;
|
||||
|
||||
this.simulatorMap = simulatorMap;
|
||||
|
||||
this.drawPolylineOnMap();
|
||||
this.drawDashLinesOnMap(this.map.getZoomLevel());
|
||||
|
||||
@@ -388,19 +392,22 @@ public class PathPolyline {
|
||||
System.err.println("==================================================");
|
||||
System.err.println("total distance = " + PathPolylineUtils.getTotalDistanceMeters(points) + " meters");
|
||||
System.err.println("step size = " + STEP_SIZE_METERS + " meters");
|
||||
System.err.println("average wind speed = " + PathPolylineUtils.knotsToMetersPerSecond(averageWindSpeed.speedInKnots) + " meters/second");
|
||||
System.err.println("total time = " + totalTime + " seconds!");
|
||||
System.err.println("average wind speed = " + PathPolylineUtils.knotsToMetersPerSecond(averageWindSpeed.speedInKnots)
|
||||
+ " meters/second, with bearing of " + averageWindSpeed.bearingInDegrees + " degrees");
|
||||
System.err.println("total time = " + (long) totalTime + " seconds!");
|
||||
System.err.println("==================================================");
|
||||
|
||||
|
||||
simulatorMap.addLegendOverlayForPathPolyline(((long) totalTime) * 1000);
|
||||
simulatorMap.redrawLegendCanvasOverlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private SpeedWithBearingDTO getAverageWindSpeed() {
|
||||
|
||||
final List<SimulatorWindDTO> windDTOs = this.pathDTO.getMatrix();
|
||||
// PathPolylineUtils.computeMinMaxAverageWindSpeed(windDTOs)
|
||||
return PathPolylineUtils.computeAverageWindSpeed(windDTOs);
|
||||
return PathPolylineUtils.computeAverageWindSpeed(this.pathPoints);
|
||||
}
|
||||
|
||||
private RequestPolarDiagramDataDTO createRequestPolarDiagramDataDTO() {
|
||||
|
||||
+117
-10
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.gwt.ui.simulator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -68,8 +69,11 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
|
||||
private final int xRes;
|
||||
private final int yRes;
|
||||
|
||||
// private PathPolyline pathPolyline;
|
||||
private boolean warningAlreadyShown = false;
|
||||
private boolean firstTime = true;
|
||||
|
||||
private PathDTO gpsPoly = null;
|
||||
private PathDTO gpsTrack = null;
|
||||
|
||||
public enum ViewName {
|
||||
SUMMARY, REPLAY, WINDDISPLAY
|
||||
@@ -136,11 +140,18 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
|
||||
pathName = paths[index].name;
|
||||
color = colorPalette.getColor(paths.length - 1 - index);
|
||||
|
||||
// TODO: "GPS Poly" has wrong wind information => fix douglas-peucker "approximate", or refer to "GPS Track"
|
||||
if (pathName.equals("GPS Poly")) {
|
||||
// pathPolyline = createPathPolyline(currentPath, simulatorSvc, mapw);
|
||||
createPathPolyline(currentPath, errorReporter, simulatorSvc, mapw);
|
||||
if (pathName.equals("GPS Track")) {
|
||||
gpsTrack = currentPath;
|
||||
}
|
||||
else if (pathName.equals("GPS Poly")) {
|
||||
gpsPoly = currentPath;
|
||||
}
|
||||
|
||||
if (firstTime && gpsTrack != null && gpsPoly != null) {
|
||||
createPathPolyline(identifyPath(gpsTrack, gpsPoly));
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
|
||||
/* TODO Revisit for now creating a WindFieldDTO from the path */
|
||||
final WindFieldDTO pathWindDTO = new WindFieldDTO();
|
||||
@@ -204,7 +215,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
|
||||
if (windParams.isShowGrid()) {
|
||||
timeListeners.add(windGridCanvasOverlay);
|
||||
}
|
||||
if (windParams.isShowLines()) {
|
||||
if (windParams.isShowLines()) {
|
||||
timeListeners.add(windLineCanvasOverlay);
|
||||
}
|
||||
for (int i = 0; i < replayPathCanvasOverlays.size(); ++i) {
|
||||
@@ -687,9 +698,85 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
|
||||
return value;
|
||||
}
|
||||
|
||||
private static PathPolyline createPathPolyline(final PathDTO pathDTO, final ErrorReporter errorReporter, final SimulatorServiceAsync simulatorService,
|
||||
final MapWidget map) {
|
||||
final List<SimulatorWindDTO> pathPoints = pathDTO.getMatrix();
|
||||
private static List<SimulatorWindDTO> identifyPath(final PathDTO gpsTrack, final PathDTO gpsPoly) {
|
||||
|
||||
final List<SimulatorWindDTO> windDTOs = new ArrayList<SimulatorWindDTO>();
|
||||
|
||||
final List<SimulatorWindDTO> gpsTrackWindDTOs = gpsTrack.getMatrix();
|
||||
final List<SimulatorWindDTO> gpsPolyWindDTOs = gpsPoly.getMatrix();
|
||||
|
||||
final int countOfGpsPolyWindDTOs = gpsPolyWindDTOs.size();
|
||||
if (countOfGpsPolyWindDTOs == 0 || countOfGpsPolyWindDTOs == 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final SimulatorWindDTO startWindDTO = gpsPolyWindDTOs.get(0);
|
||||
final SimulatorWindDTO endWindDTO = gpsPolyWindDTOs.get(countOfGpsPolyWindDTOs - 1);
|
||||
|
||||
final int startIndex = getIndexOfClosest(gpsTrackWindDTOs, startWindDTO);
|
||||
// System.err.println("BBBB: startIndex = " + startIndex);
|
||||
final int endIndex = getIndexOfClosest(gpsTrackWindDTOs, endWindDTO);
|
||||
// System.err.println("BBBB: endIndex = " + endIndex);
|
||||
|
||||
for (int index = startIndex; index <= endIndex; index++) {
|
||||
windDTOs.add(gpsTrackWindDTOs.get(index));
|
||||
}
|
||||
|
||||
return windDTOs;
|
||||
}
|
||||
|
||||
private static int getIndexOfClosest(final List<SimulatorWindDTO> items, final SimulatorWindDTO item) {
|
||||
final int count = items.size();
|
||||
|
||||
final List<Double> diff_lat = new ArrayList<Double>();
|
||||
final List<Double> diff_lng = new ArrayList<Double>();
|
||||
final List<Long> diff_timepoint = new ArrayList<Long>();
|
||||
|
||||
for (int index = 0; index < count; index++) {
|
||||
diff_lat.add(Math.abs(items.get(index).position.latDeg - item.position.latDeg));
|
||||
diff_lng.add(Math.abs(items.get(index).position.lngDeg - item.position.lngDeg));
|
||||
diff_timepoint.add(Math.abs(items.get(index).timepoint - item.timepoint));
|
||||
}
|
||||
|
||||
final double min_diff_lat = Collections.min(diff_lat);
|
||||
final double min_max_diff_lat = min_diff_lat + Collections.max(diff_lat);
|
||||
|
||||
final double min_diff_lng = Collections.min(diff_lng);
|
||||
final double min_max_diff_lng = min_diff_lng + Collections.max(diff_lng);
|
||||
|
||||
final long min_diff_timepoint = Collections.min(diff_timepoint);
|
||||
final double min_max_diff_timepoint = min_diff_timepoint + Collections.max(diff_timepoint);
|
||||
|
||||
final List<Double> norm_diff_lat = new ArrayList<Double>();
|
||||
final List<Double> norm_diff_lng = new ArrayList<Double>();
|
||||
final List<Double> norm_diff_timepoint = new ArrayList<Double>();
|
||||
|
||||
for (int index = 0; index < count; index++) {
|
||||
norm_diff_lat.add((diff_lat.get(index) - min_diff_lat) / min_max_diff_lat);
|
||||
norm_diff_lng.add((diff_lng.get(index) - min_diff_lng) / min_max_diff_lng);
|
||||
norm_diff_timepoint.add((diff_timepoint.get(index) - min_diff_timepoint) / min_max_diff_timepoint);
|
||||
}
|
||||
|
||||
final List<Double> deltas = new ArrayList<Double>();
|
||||
|
||||
for (int index = 0; index < count; index++) {
|
||||
deltas.add(Math.sqrt(Math.pow(norm_diff_lat.get(index), 2) + Math.pow(norm_diff_lng.get(index), 2) + Math.pow(norm_diff_timepoint.get(index), 2)));
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
double min = deltas.get(0);
|
||||
|
||||
for (int index = 0; index < count; index++) {
|
||||
if (deltas.get(index) < min) {
|
||||
result = index;
|
||||
min = deltas.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private PathPolyline createPathPolyline(final List<SimulatorWindDTO> pathPoints) {
|
||||
|
||||
final int noOfPathPoints = pathPoints.size();
|
||||
SimulatorWindDTO currentPathPoint = null;
|
||||
@@ -704,6 +791,26 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
|
||||
|
||||
final int boatClassID = 3; // 49er STG
|
||||
|
||||
return new PathPolyline(points.toArray(new LatLng[0]), boatClassID, errorReporter, pathDTO, simulatorService, map);
|
||||
return new PathPolyline(points.toArray(new LatLng[0]), boatClassID, this.errorReporter, pathPoints, this.simulatorSvc, this.mapw, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private PathPolyline createPathPolyline(final PathDTO pathDTO) {
|
||||
|
||||
return this.createPathPolyline(pathDTO.getMatrix());
|
||||
}
|
||||
|
||||
public void addLegendOverlayForPathPolyline(final long totalTimeMilliseconds) {
|
||||
|
||||
final PathCanvasOverlay overlay = new PathCanvasOverlay("Polyline", totalTimeMilliseconds);
|
||||
overlay.pathColor = PathPolyline.DEFAULT_COLOR;
|
||||
|
||||
this.legendCanvasOverlay.addPathOverlay(overlay);
|
||||
}
|
||||
|
||||
public void redrawLegendCanvasOverlay() {
|
||||
this.legendCanvasOverlay.setVisible(true);
|
||||
this.legendCanvasOverlay.redraw(true);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user