From 46dd886200ca85bbee7b85847893d7a1bb53a83c Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 20 Jul 2018 16:33:11 +0200 Subject: [PATCH 01/32] bug4134_2: A working version of colored windstreamlets according to minmax speed. --- .../SwarmMinMaxSpeedChangedListener.java | 5 + .../WindStreamletsRaceboardOverlay.java | 113 +++++++++++------- .../simulator/streamlets/SchmittTrigger.java | 38 ++++++ .../gwt/ui/simulator/streamlets/Swarm.java | 90 +++++++++++++- 4 files changed, 200 insertions(+), 46 deletions(-) create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java new file mode 100755 index 00000000000..5bb53f1ffc6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java @@ -0,0 +1,5 @@ +package com.sap.sailing.gwt.ui.shared.racemap; + +public interface SwarmMinMaxSpeedChangedListener { + void onSwarmMinMaxSpeedChanged(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index 454418dda8f..059453c0a83 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -11,6 +11,7 @@ import com.google.gwt.canvas.dom.client.Context2d; import com.google.gwt.canvas.dom.client.TextMetrics; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; +import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.maps.client.MapWidget; import com.google.gwt.maps.client.controls.ControlPosition; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -18,6 +19,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.gwt.ui.actions.GetWindInfoAction; +import com.sap.sailing.gwt.ui.client.NumberFormatterFactory; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem; @@ -44,7 +46,7 @@ import com.sap.sse.gwt.client.player.Timer; * @author Axel Uhl (D043530) * */ -public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { +public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implements SwarmMinMaxSpeedChangedListener{ public static final String LOAD_WIND_STREAMLET_DATA_CATEGORY = "loadWindStreamletData"; private static final int animationIntervalMillis = 40; private static final long RESOLUTION_IN_MILLIS = 5000; @@ -66,6 +68,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { private long latitudeCount; private double latitudeSum; + + private final NumberFormat numberFormatOneDecimal = NumberFormatterFactory.getDecimalFormat(1); public WindStreamletsRaceboardOverlay(MapWidget map, int zIndex, final Timer timer, RegattaAndRaceIdentifier raceIdentifier, SailingServiceAsync sailingService, @@ -130,45 +134,62 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { streamletLegend.setCoordinateSpaceWidth(canvasWidth); streamletLegend.setCoordinateSpaceHeight(canvasHeight); } - private void drawLegend() { - double x, y; - x=100; - y=16; - double w = 1; - double h = 20; - int maxIdx = 300; - Context2d context2d = streamletLegend.getContext2d(); - context2d.setFillStyle("rgba(0,0,0,.3)"); - context2d.setLineWidth(1.0); - context2d.beginPath(); - context2d.fillRect(x-7.0, y-16.0, w*maxIdx+15.0, 56.0); - context2d.closePath(); - context2d.stroke(); - context2d.setFillStyle("white"); - String label = stringMessages.windSpeedInKnots(); - TextMetrics txtmet; - txtmet = context2d.measureText(label); - context2d.fillText(label, x + (w*maxIdx - txtmet.getWidth())/2.0, y - 5.0); - for(int idx=0; idx <= maxIdx; idx++) { - //double speed = idx * 24.0 / maxIdx; - double speed = 4.0 + idx * 16.0 / maxIdx; - context2d.setFillStyle(windField.getColor(speed)); - context2d.beginPath(); - context2d.fillRect(x + idx*w, y, w, h); - context2d.closePath(); - context2d.stroke(); - if (Math.abs(speed % 2.0) < (12.0/maxIdx)) { - context2d.setStrokeStyle("white"); + public void drawLegend() { + if (streamletLegend.isVisible()) { + streamletLegend.getContext2d().clearRect(0, 0, streamletLegend.getCoordinateSpaceWidth(), + streamletLegend.getCoordinateSpaceHeight()); + if (swarm != null && swarm.isColored()) { + final double x = 100; + final double y = 16; + final double w = 1; + final double h = 20; + final double speed_max = swarm.getMaxParticleSpeedInKnots(); + final double speed_min = swarm.getMinParticleSpeedInKnots(); + final double speed_spread = speed_max - speed_min; + final int scale_spread; + if (speed_spread < 0.5) { + scale_spread = 300; + } + else if (speed_spread < 1) { + scale_spread = 100; + } + else { + scale_spread = 50; + } + final int maxIdx = 300; + Context2d context2d = streamletLegend.getContext2d(); + context2d.setFillStyle("rgba(0,0,0,.3)"); context2d.setLineWidth(1.0); context2d.beginPath(); - context2d.moveTo(x + idx*w, y + h); - context2d.lineTo(x + idx*w, y + h + 7.0); + context2d.fillRect(x - 10.0, y - 16.0, w * maxIdx + 20.0, 56.0); context2d.closePath(); context2d.stroke(); context2d.setFillStyle("white"); - label = ""+Math.round(speed); + String label = stringMessages.windSpeedInKnots(); + TextMetrics txtmet; txtmet = context2d.measureText(label); - context2d.fillText(label, x + idx*w - txtmet.getWidth()/2.0, y + h + 8.0 + 8.0); + context2d.fillText(label, x + (w * maxIdx - txtmet.getWidth()) / 2.0, y - 5.0); + for (int idx = 0; idx <= maxIdx; idx++) { + final double speedSteps = speed_min + idx * (speed_max - speed_min) / maxIdx; + context2d.setFillStyle(swarm.getColorWithSpectrumBoundaries(speedSteps)); + context2d.beginPath(); + context2d.fillRect(x + idx * w, y, w, h); + context2d.closePath(); + context2d.stroke(); + if (idx % scale_spread == 0) { + context2d.setStrokeStyle("white"); + context2d.setLineWidth(1.0); + context2d.beginPath(); + context2d.moveTo(x + idx * w, y + h); + context2d.lineTo(x + idx * w, y + h + 7.0); + context2d.closePath(); + context2d.stroke(); + context2d.setFillStyle("white"); + label = numberFormatOneDecimal.format(speedSteps); + txtmet = context2d.measureText(label); + context2d.fillText(label, x + idx * w - txtmet.getWidth() / 2.0, y + h + 8.0 + 8.0); + } + } } } } @@ -180,7 +201,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { this.swarm = new Swarm(this, map, timer, windField, new StreamletParameters()); } initCanvasOrigin(); + this.swarm.setColors(colored); this.swarm.start(animationIntervalMillis); + this.swarm.addSwarmMinMaxSpeedChangedListener(this); } private void scheduleWindDataRefresh() { @@ -203,8 +226,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { } private void stopStreamlets() { - if (swarm != null) { + if (this.swarm != null) { this.swarm.stop(); + this.swarm.removeSwarmMinMaxSpeedChangedListener(this); } } @@ -298,13 +322,13 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { public void setVisible(boolean isVisible) { if (getCanvas() != null) { if (isVisible) { - if (this.windField.getColors()) { - this.streamletLegend.setVisible(true); - } this.startStreamlets(); this.visible = isVisible; + if (this.swarm.isColored()) { + this.streamletLegend.setVisible(true); + } } else { - if (this.windField.getColors()) { + if (this.swarm.isColored()) { this.streamletLegend.setVisible(false); } this.stopStreamlets(); @@ -312,14 +336,15 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { } } } - +private boolean colored; public void setColors(boolean isColored) { - this.windField.setColors(isColored); + this.colored = isColored; if ((isColored) && (firstColoring)) { firstColoring = false; - this.drawLegend(); } this.streamletLegend.setVisible(isColored); + if (swarm != null) { + swarm.setColors(isColored);} } @Override @@ -337,4 +362,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay { swarm.onBoundsChanged(zoomChanged, swarmPause); } } + + public void onSwarmMinMaxSpeedChanged() { + drawLegend(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java new file mode 100755 index 00000000000..d6e2d158167 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java @@ -0,0 +1,38 @@ +package com.sap.sailing.gwt.ui.simulator.streamlets; + +public class SchmittTrigger { + private double percentage; + + public SchmittTrigger() {} + public SchmittTrigger(double percentageTriggerThreeshold) { + this.percentage = percentageTriggerThreeshold; + } + + public boolean isGreaterThanThreeshold(double input,double threesholdValue) { + if (input * (1 + percentage/100) > threesholdValue) { + return true; + } + else { + return false; + } + } + public boolean isLesserThanThreeshold(double input,double threesholdValue) { + if (input * (1 - percentage/100) < threesholdValue) { + return true; + } + else { + return false; + } + } + public boolean isValueChangeTriggered(double input, double threesholdValue) { + if (isGreaterThanThreeshold(input, threesholdValue) || isLesserThanThreeshold(input, threesholdValue)) { + return true; + } + else { + return false; + } + } + public double getTriggerPercentage() { + return percentage; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 5278452dd46..47bea5ab3fa 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.ui.simulator.streamlets; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.canvas.dom.client.Context2d; @@ -13,6 +15,7 @@ import com.google.gwt.maps.client.events.bounds.BoundsChangeMapHandler; import com.google.gwt.user.client.Timer; import com.sap.sailing.gwt.ui.client.shared.racemap.BoundsUtil; import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem; +import com.sap.sailing.gwt.ui.shared.racemap.SwarmMinMaxSpeedChangedListener; import com.sap.sailing.gwt.ui.simulator.StreamletParameters; import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay; import com.sap.sse.gwt.client.player.TimeListener; @@ -74,6 +77,8 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); + swarmMinMaxSpeedChangedListeners = new HashSet<>(); + schmittTrigger = new SchmittTrigger(/*percent*/ 25); } public void start(final int animationIntervalMillis) { @@ -113,7 +118,9 @@ public class Swarm implements TimeListener { while (!done && attempts-- > 0) { particle = new Particle(); particle.currentPosition = getRandomPosition(); - if (field.inBounds(particle.currentPosition)) { + // Is the if check really needed? getRandomPosition() returns always a position that is within the + // visibleBoundsOfField. visibleBoundsOfField is always within fieldBounds. See updateBounds(). + if(field.inBounds(particle.currentPosition)) { Vector v = field.getVector(particle.currentPosition, timePoint); double weight = field.getParticleWeight(particle.currentPosition, v); if (weight >= Math.random()) { @@ -145,7 +152,6 @@ public class Swarm implements TimeListener { result = LatLng.newInstance(latDeg, lngDeg); return result; } - private Particle[] createParticles() { Particle[] newParticles = new Particle[nParticles]; for (int idx = 0; idx < newParticles.length; idx++) { @@ -234,7 +240,7 @@ public class Swarm implements TimeListener { } double particleSpeed = particle.v == null ? 0 : particle.v.length(); ctxt.setLineWidth(field.getLineWidth(particleSpeed)); - ctxt.setStrokeStyle(field.getColor(particleSpeed)); + ctxt.setStrokeStyle(getColorWithSpectrumBoundaries(particleSpeed)); ctxt.beginPath(); ctxt.moveTo(particle.previousPixelCoordinate.x, particle.previousPixelCoordinate.y); ctxt.lineTo(particle.currentPixelCoordinate.x, particle.currentPixelCoordinate.y); @@ -242,11 +248,61 @@ public class Swarm implements TimeListener { } } + private boolean colored = false; + public String getColorWithSpectrumBoundaries(double speed) { + if (colored) { + double h = (1 - (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) * 240; + return "hsl(" + Math.round(h) + ", 100%, 50%)"; + } else { + return "rgba(255,255,255," + Math.min(1.0, speed / 40) + ")"; + } + } + public void setColors(boolean isColored) { + this.colored = isColored; + } + + public boolean isColored() { + return colored; + } + + private double maxParticleSpeedInKnots = 0.0; + /** + * @return the maxParticleSpeedInKnots + */ + public double getMaxParticleSpeedInKnots() { + return maxParticleSpeedInKnots; + } + + /** + * @return the minParticleSpeedInKnots + */ + public double getMinParticleSpeedInKnots() { + return minParticleSpeedInKnots; + } + + private double minParticleSpeedInKnots = 120.0; + + private boolean isNotifyListeners = true; + + private void notifyListeners() { + if (isNotifyListeners) { + for (SwarmMinMaxSpeedChangedListener listener : swarmMinMaxSpeedChangedListeners) { + listener.onSwarmMinMaxSpeedChanged(); + } + } + } + + private final SchmittTrigger schmittTrigger; + /** * Moves each particle by its vector {@link Particle#v} multiplied by the speed which is 0.01 times the - * {@link VectorField#getMotionScale(int)} at the map's current zoom level. + * {@link VectorField#getMotionScale(int)} at the map's current zoom level. Also the max and min speed fields of the + * swarm get updated and the listeners get notified. */ private boolean execute(Vector diffPx) { + boolean isUpdateListeners = false; + double minSpeed = 120.0; + double maxSpeed = 0.0; double speed = field.getMotionScale(map.getZoom()); for (int idx = 0; idx < particles.length; idx++) { Particle particle = particles[idx]; @@ -268,6 +324,12 @@ public class Swarm implements TimeListener { particle.stepsToLive--; if ((particle.stepsToLive > 0) && (this.field.inBounds(particle.currentPosition))) { particle.v = field.getVector(particle.currentPosition, timePoint); + if (particle.v.length() > maxSpeed) { + maxSpeed = particle.v.length(); + } + if (particle.v.length() < minSpeed) { + minSpeed = particle.v.length(); + } } else { particle.v = null; } @@ -276,7 +338,17 @@ public class Swarm implements TimeListener { particles[idx] = this.createParticle(); } } + if (schmittTrigger.isValueChangeTriggered(maxSpeed, maxParticleSpeedInKnots)) { + maxParticleSpeedInKnots = maxSpeed; + isUpdateListeners = true; + } + if (schmittTrigger.isValueChangeTriggered(minSpeed, minParticleSpeedInKnots)) { + minParticleSpeedInKnots = minSpeed; + isUpdateListeners = true; + } + this.isNotifyListeners = isUpdateListeners; drawSwarm(); + notifyListeners(); return true; } @@ -288,4 +360,14 @@ public class Swarm implements TimeListener { public void timeChanged(Date newTime, Date oldTime) { timePoint = newTime; } + + private final Set swarmMinMaxSpeedChangedListeners; + public void addSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) { + swarmMinMaxSpeedChangedListeners.add(listener); + } + public void removeSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) { + swarmMinMaxSpeedChangedListeners.remove(listener); + } + + } From aecf28f9729e81ddf9c53a7d30e9cbb8e22b72af Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 20 Jul 2018 16:51:25 +0200 Subject: [PATCH 02/32] bug4134_2: Added spectrum spread for non-colored streamlets. --- .../com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 47bea5ab3fa..3233c6f51fa 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -254,7 +254,7 @@ public class Swarm implements TimeListener { double h = (1 - (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) * 240; return "hsl(" + Math.round(h) + ", 100%, 50%)"; } else { - return "rgba(255,255,255," + Math.min(1.0, speed / 40) + ")"; + return "rgba(255,255,255," + Math.min(1.0, (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) + ")"; } } public void setColors(boolean isColored) { @@ -346,7 +346,7 @@ public class Swarm implements TimeListener { minParticleSpeedInKnots = minSpeed; isUpdateListeners = true; } - this.isNotifyListeners = isUpdateListeners; + isNotifyListeners = isUpdateListeners; drawSwarm(); notifyListeners(); return true; From aa1d8cc793cf2eeaa425d365b8fae589b983dfb2 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 20 Jul 2018 17:56:46 +0200 Subject: [PATCH 03/32] bug4134_2: commentbug4134_2: commentss --- .../gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java | 1 + .../java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 1 + 2 files changed, 2 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index 059453c0a83..5b51f21b779 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -157,6 +157,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen scale_spread = 50; } final int maxIdx = 300; +// final colors[] = swarm.getColorsForSteps(maxIdx); Context2d context2d = streamletLegend.getContext2d(); context2d.setFillStyle("rgba(0,0,0,.3)"); context2d.setLineWidth(1.0); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 3233c6f51fa..e1e4729315c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -368,6 +368,7 @@ public class Swarm implements TimeListener { public void removeSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) { swarmMinMaxSpeedChangedListeners.remove(listener); } + } From c065864a306224f4c92f11424831c6c7144a68b7 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Tue, 14 Aug 2018 18:37:49 +0200 Subject: [PATCH 04/32] bug4134_2: Added ColorMapper and ValueRangeBoundaries Class and Listeners. --- .../SwarmMinMaxSpeedChangedListener.java | 5 - .../WindStreamletsRaceboardOverlay.java | 20 ++-- .../ui/simulator/streamlets/ColorMapper.java | 66 ++++++++++++ .../ColorMapperChangedListener.java | 5 + .../simulator/streamlets/SchmittTrigger.java | 38 ------- .../gwt/ui/simulator/streamlets/Swarm.java | 89 +++------------- .../streamlets/ValueRangeBoundaries.java | 100 ++++++++++++++++++ .../ValueRangeBoundariesChangedListener.java | 5 + 8 files changed, 202 insertions(+), 126 deletions(-) delete mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java delete mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java deleted file mode 100755 index 5bb53f1ffc6..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/SwarmMinMaxSpeedChangedListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.racemap; - -public interface SwarmMinMaxSpeedChangedListener { - void onSwarmMinMaxSpeedChanged(); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index 5b51f21b779..c69806e48a8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -28,6 +28,7 @@ import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO; import com.sap.sailing.gwt.ui.simulator.StreamletParameters; import com.sap.sailing.gwt.ui.simulator.racemap.MovingCanvasOverlay; +import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapperChangedListener; import com.sap.sailing.gwt.ui.simulator.streamlets.Swarm; import com.sap.sailing.gwt.ui.simulator.streamlets.VectorField; import com.sap.sailing.gwt.ui.simulator.streamlets.WindInfoForRaceVectorField; @@ -46,7 +47,7 @@ import com.sap.sse.gwt.client.player.Timer; * @author Axel Uhl (D043530) * */ -public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implements SwarmMinMaxSpeedChangedListener{ +public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implements ColorMapperChangedListener{ public static final String LOAD_WIND_STREAMLET_DATA_CATEGORY = "loadWindStreamletData"; private static final int animationIntervalMillis = 40; private static final long RESOLUTION_IN_MILLIS = 5000; @@ -143,8 +144,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen final double y = 16; final double w = 1; final double h = 20; - final double speed_max = swarm.getMaxParticleSpeedInKnots(); - final double speed_min = swarm.getMinParticleSpeedInKnots(); + final double speed_max = swarm.getValueRange().getMaxRight(); + final double speed_min = swarm.getValueRange().getMinLeft(); final double speed_spread = speed_max - speed_min; final int scale_spread; if (speed_spread < 0.5) { @@ -157,7 +158,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen scale_spread = 50; } final int maxIdx = 300; -// final colors[] = swarm.getColorsForSteps(maxIdx); Context2d context2d = streamletLegend.getContext2d(); context2d.setFillStyle("rgba(0,0,0,.3)"); context2d.setLineWidth(1.0); @@ -172,7 +172,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen context2d.fillText(label, x + (w * maxIdx - txtmet.getWidth()) / 2.0, y - 5.0); for (int idx = 0; idx <= maxIdx; idx++) { final double speedSteps = speed_min + idx * (speed_max - speed_min) / maxIdx; - context2d.setFillStyle(swarm.getColorWithSpectrumBoundaries(speedSteps)); + context2d.setFillStyle(swarm.getColorMapper().getColor(speedSteps)); context2d.beginPath(); context2d.fillRect(x + idx * w, y, w, h); context2d.closePath(); @@ -204,7 +204,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen initCanvasOrigin(); this.swarm.setColors(colored); this.swarm.start(animationIntervalMillis); - this.swarm.addSwarmMinMaxSpeedChangedListener(this); + this.swarm.getColorMapper().addListener(this); } private void scheduleWindDataRefresh() { @@ -229,7 +229,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen private void stopStreamlets() { if (this.swarm != null) { this.swarm.stop(); - this.swarm.removeSwarmMinMaxSpeedChangedListener(this); + this.swarm.getColorMapper().removeListener(this); } } @@ -363,8 +363,10 @@ private boolean colored; swarm.onBoundsChanged(zoomChanged, swarmPause); } } - - public void onSwarmMinMaxSpeedChanged() { + + @Override + public void onColorMappingChanged() { drawLegend(); } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java new file mode 100755 index 00000000000..b2344ee214a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -0,0 +1,66 @@ +package com.sap.sailing.gwt.ui.simulator.streamlets; + +import java.util.HashSet; +import java.util.Set; + +/** + * This class maps a given range of values to a full color spectrum. The color spectrum could also be a gray scale. + * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeBoundaries} to get those. + * The ColorMapper has listeners that will be notified if the colormapping has been changed. + * + * @author D073259 + * + */ +public class ColorMapper implements ValueRangeBoundariesChangedListener { + private final ValueRangeBoundaries valueRange; + private double minValue; + private double maxValue; + private boolean isGrey; + private final Set colorMapperChangedListeners; + + public ColorMapper(ValueRangeBoundaries valueRange, boolean isGrey) { + this.valueRange = valueRange; + this.valueRange.addListener(this); + minValue = this.valueRange.getMinLeft(); + maxValue = this.valueRange.getMaxRight(); + this.isGrey = isGrey; + valueRange.addListener(this); + colorMapperChangedListeners = new HashSet<>(); + } + + public void setGrey(boolean isGrey) { + this.isGrey = isGrey; + notifyListeners(); + } + + public String getColor(double value) { + if (isGrey) { + return "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + } else { + double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; + return "hsl(" + Math.round(h) + ", 100%, 50%)"; + } + } + + private void updateMinMax() { + minValue = valueRange.getMinLeft(); + maxValue = valueRange.getMaxRight(); + } + + @Override + public void onValueRangeBoundariesChanged() { + updateMinMax(); + notifyListeners(); + } + public void addListener(ColorMapperChangedListener listener) { + colorMapperChangedListeners.add(listener); + } + public void removeListener(ColorMapperChangedListener listener) { + colorMapperChangedListeners.remove(listener); + } + public void notifyListeners() { + for (ColorMapperChangedListener listener : colorMapperChangedListeners) { + listener.onColorMappingChanged(); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java new file mode 100755 index 00000000000..f5cb90277a2 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java @@ -0,0 +1,5 @@ +package com.sap.sailing.gwt.ui.simulator.streamlets; + +public interface ColorMapperChangedListener { + void onColorMappingChanged(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java deleted file mode 100755 index d6e2d158167..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SchmittTrigger.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sap.sailing.gwt.ui.simulator.streamlets; - -public class SchmittTrigger { - private double percentage; - - public SchmittTrigger() {} - public SchmittTrigger(double percentageTriggerThreeshold) { - this.percentage = percentageTriggerThreeshold; - } - - public boolean isGreaterThanThreeshold(double input,double threesholdValue) { - if (input * (1 + percentage/100) > threesholdValue) { - return true; - } - else { - return false; - } - } - public boolean isLesserThanThreeshold(double input,double threesholdValue) { - if (input * (1 - percentage/100) < threesholdValue) { - return true; - } - else { - return false; - } - } - public boolean isValueChangeTriggered(double input, double threesholdValue) { - if (isGreaterThanThreeshold(input, threesholdValue) || isLesserThanThreeshold(input, threesholdValue)) { - return true; - } - else { - return false; - } - } - public double getTriggerPercentage() { - return percentage; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index e1e4729315c..a8ce76b580e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -1,8 +1,6 @@ package com.sap.sailing.gwt.ui.simulator.streamlets; import java.util.Date; -import java.util.HashSet; -import java.util.Set; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.canvas.dom.client.Context2d; @@ -15,7 +13,6 @@ import com.google.gwt.maps.client.events.bounds.BoundsChangeMapHandler; import com.google.gwt.user.client.Timer; import com.sap.sailing.gwt.ui.client.shared.racemap.BoundsUtil; import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem; -import com.sap.sailing.gwt.ui.shared.racemap.SwarmMinMaxSpeedChangedListener; import com.sap.sailing.gwt.ui.simulator.StreamletParameters; import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay; import com.sap.sse.gwt.client.player.TimeListener; @@ -65,6 +62,9 @@ public class Swarm implements TimeListener { private double cosineOfAverageLatitude; private HandlerRegistration handlerRegistration; + + private final ValueRangeBoundaries valueRange; + private final ColorMapper colorMapper; public Swarm(FullCanvasOverlay fullcanvas, MapWidget map, com.sap.sse.gwt.client.player.Timer timer, VectorField vectorField, StreamletParameters streamletPars) { @@ -77,8 +77,8 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); - swarmMinMaxSpeedChangedListeners = new HashSet<>(); - schmittTrigger = new SchmittTrigger(/*percent*/ 25); + valueRange = new ValueRangeBoundaries(0.0, 120.0, /*percentage*/ 0.1); + colorMapper = new ColorMapper(valueRange, !colored); } public void start(final int animationIntervalMillis) { @@ -118,8 +118,6 @@ public class Swarm implements TimeListener { while (!done && attempts-- > 0) { particle = new Particle(); particle.currentPosition = getRandomPosition(); - // Is the if check really needed? getRandomPosition() returns always a position that is within the - // visibleBoundsOfField. visibleBoundsOfField is always within fieldBounds. See updateBounds(). if(field.inBounds(particle.currentPosition)) { Vector v = field.getVector(particle.currentPosition, timePoint); double weight = field.getParticleWeight(particle.currentPosition, v); @@ -240,7 +238,7 @@ public class Swarm implements TimeListener { } double particleSpeed = particle.v == null ? 0 : particle.v.length(); ctxt.setLineWidth(field.getLineWidth(particleSpeed)); - ctxt.setStrokeStyle(getColorWithSpectrumBoundaries(particleSpeed)); + ctxt.setStrokeStyle(colorMapper.getColor(particleSpeed)); ctxt.beginPath(); ctxt.moveTo(particle.previousPixelCoordinate.x, particle.previousPixelCoordinate.y); ctxt.lineTo(particle.currentPixelCoordinate.x, particle.currentPixelCoordinate.y); @@ -249,58 +247,18 @@ public class Swarm implements TimeListener { } private boolean colored = false; - public String getColorWithSpectrumBoundaries(double speed) { - if (colored) { - double h = (1 - (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) * 240; - return "hsl(" + Math.round(h) + ", 100%, 50%)"; - } else { - return "rgba(255,255,255," + Math.min(1.0, (speed - minParticleSpeedInKnots)/(maxParticleSpeedInKnots - minParticleSpeedInKnots)) + ")"; - } - } public void setColors(boolean isColored) { this.colored = isColored; + colorMapper.setGrey(!isColored); } - public boolean isColored() { return colored; } - - private double maxParticleSpeedInKnots = 0.0; - /** - * @return the maxParticleSpeedInKnots - */ - public double getMaxParticleSpeedInKnots() { - return maxParticleSpeedInKnots; - } - - /** - * @return the minParticleSpeedInKnots - */ - public double getMinParticleSpeedInKnots() { - return minParticleSpeedInKnots; - } - - private double minParticleSpeedInKnots = 120.0; - - private boolean isNotifyListeners = true; - - private void notifyListeners() { - if (isNotifyListeners) { - for (SwarmMinMaxSpeedChangedListener listener : swarmMinMaxSpeedChangedListeners) { - listener.onSwarmMinMaxSpeedChanged(); - } - } - } - - private final SchmittTrigger schmittTrigger; - /** * Moves each particle by its vector {@link Particle#v} multiplied by the speed which is 0.01 times the - * {@link VectorField#getMotionScale(int)} at the map's current zoom level. Also the max and min speed fields of the - * swarm get updated and the listeners get notified. + * {@link VectorField#getMotionScale(int)} at the map's current zoom level. */ private boolean execute(Vector diffPx) { - boolean isUpdateListeners = false; double minSpeed = 120.0; double maxSpeed = 0.0; double speed = field.getMotionScale(map.getZoom()); @@ -338,37 +296,20 @@ public class Swarm implements TimeListener { particles[idx] = this.createParticle(); } } - if (schmittTrigger.isValueChangeTriggered(maxSpeed, maxParticleSpeedInKnots)) { - maxParticleSpeedInKnots = maxSpeed; - isUpdateListeners = true; - } - if (schmittTrigger.isValueChangeTriggered(minSpeed, minParticleSpeedInKnots)) { - minParticleSpeedInKnots = minSpeed; - isUpdateListeners = true; - } - isNotifyListeners = isUpdateListeners; + valueRange.checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(minSpeed); + valueRange.checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(maxSpeed); drawSwarm(); - notifyListeners(); return true; } - public VectorField getField() { - return field; + public ValueRangeBoundaries getValueRange() { + return valueRange; + } + public ColorMapper getColorMapper() { + return colorMapper; } - @Override public void timeChanged(Date newTime, Date oldTime) { timePoint = newTime; } - - private final Set swarmMinMaxSpeedChangedListeners; - public void addSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) { - swarmMinMaxSpeedChangedListeners.add(listener); - } - public void removeSwarmMinMaxSpeedChangedListener(SwarmMinMaxSpeedChangedListener listener) { - swarmMinMaxSpeedChangedListeners.remove(listener); - } - - - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java new file mode 100755 index 00000000000..b9693481f2e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java @@ -0,0 +1,100 @@ +package com.sap.sailing.gwt.ui.simulator.streamlets; + +import java.util.HashSet; +import java.util.Set; + +/** + * This class defines if a given value is within boundaries that are flexible by a given rangeWidth. The rangeWidth is + * defined by a percentage of the minimum value, otherwise the adjustment of the boundaries will be biased and the max + * boundaries are always much bigger then the minimum boundaries. It needs four types of boundaries: + * a) minLeftBoundary + * b) maxLeftBoundary + * c) minRightBoundary + * d) maxRightBoundary + * (a)<--value->(b)..........(c)<--value->(d) + * If a value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the + * one or the other. Also there should be the possibility to add listeners that will notify on a boundary change. + * + * A ValueRangeBoundaries needs an initialMin, a initialMax and a percentage that indicates the width of the value range + * surrounding initialMin and Max. + * + * @author D073259 + * + */ +public class ValueRangeBoundaries { + private double minLeft; + private double maxLeft; + private double minRight; + private double maxRight; + private final double percentage; + private double halfRangeWidth; + private final Set valueRangeChangedListeners; + + public ValueRangeBoundaries(double initialMin, double initialMax, double percentage) { + this.percentage = percentage; + updateLeft(initialMin); + updateRight(initialMax); + valueRangeChangedListeners = new HashSet<>(); + this.halfRangeWidth = ((initialMin * (1 + percentage)) - (initialMin * (1 - percentage)))/2; + } + private void updateLeft(double value) { + minLeft = value - halfRangeWidth; + maxLeft = value + halfRangeWidth; + } + private void updateRight() { + minRight =- halfRangeWidth; + maxRight =+ halfRangeWidth; + } + private void updateRight(double value) { + minRight = value - halfRangeWidth; + maxRight = value + halfRangeWidth; + } + private void updateRangeWidth(double newMinValue) { + halfRangeWidth = ((newMinValue * (1 + percentage)) - (newMinValue * (1 - percentage)))/2; + updateRight(); + } + public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double value) { + if (!isValueInRightRange(value)) { + updateRight(value); + notifyListeners(); + } + } + public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double value) { + if (!isValueInLeftRange(value)) { + updateRangeWidth(value); + updateLeft(value); + notifyListeners(); + } + } + private boolean isValueInLeftRange(double value) { + if (value >= minLeft && value <= maxLeft) { + return true; + } else { + return false; + } + } + private boolean isValueInRightRange(double value) { + if (value >= minRight && value <= maxRight) { + return true; + } else { + return false; + } + } + public double getMinLeft() { + return minLeft; + } + public double getMaxRight() { + return maxRight; + } + public void addListener(ValueRangeBoundariesChangedListener listener) { + valueRangeChangedListeners.add(listener); + } + public void removeListener(ValueRangeBoundariesChangedListener listener) { + valueRangeChangedListeners.remove(listener); + } + public void notifyListeners() { + for (ValueRangeBoundariesChangedListener listener : valueRangeChangedListeners) { + listener.onValueRangeBoundariesChanged(); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java new file mode 100755 index 00000000000..68b1414a748 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java @@ -0,0 +1,5 @@ +package com.sap.sailing.gwt.ui.simulator.streamlets; + +public interface ValueRangeBoundariesChangedListener { + void onValueRangeBoundariesChanged(); +} From f2d2cfa471a0d3fae105af44e0711c378799ea01 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 09:58:18 +0200 Subject: [PATCH 05/32] bug4134_2: small changes to colormapper and valuerangeboundaries. --- .../gwt/ui/simulator/streamlets/ColorMapper.java | 3 +-- .../ui/simulator/streamlets/ValueRangeBoundaries.java | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index b2344ee214a..41d2703e908 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -4,7 +4,7 @@ import java.util.HashSet; import java.util.Set; /** - * This class maps a given range of values to a full color spectrum. The color spectrum could also be a gray scale. + * This class maps a given range of values to a full color spectrum. The color spectrum could also be a grey scale. * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeBoundaries} to get those. * The ColorMapper has listeners that will be notified if the colormapping has been changed. * @@ -24,7 +24,6 @@ public class ColorMapper implements ValueRangeBoundariesChangedListener { minValue = this.valueRange.getMinLeft(); maxValue = this.valueRange.getMaxRight(); this.isGrey = isGrey; - valueRange.addListener(this); colorMapperChangedListeners = new HashSet<>(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java index b9693481f2e..af83741c94a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java @@ -7,10 +7,10 @@ import java.util.Set; * This class defines if a given value is within boundaries that are flexible by a given rangeWidth. The rangeWidth is * defined by a percentage of the minimum value, otherwise the adjustment of the boundaries will be biased and the max * boundaries are always much bigger then the minimum boundaries. It needs four types of boundaries: - * a) minLeftBoundary - * b) maxLeftBoundary - * c) minRightBoundary - * d) maxRightBoundary + * a) minLeft + * b) maxLeft + * c) minRight + * d) maxRight * (a)<--value->(b)..........(c)<--value->(d) * If a value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the * one or the other. Also there should be the possibility to add listeners that will notify on a boundary change. @@ -51,7 +51,6 @@ public class ValueRangeBoundaries { } private void updateRangeWidth(double newMinValue) { halfRangeWidth = ((newMinValue * (1 + percentage)) - (newMinValue * (1 - percentage)))/2; - updateRight(); } public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double value) { if (!isValueInRightRange(value)) { @@ -62,6 +61,7 @@ public class ValueRangeBoundaries { public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double value) { if (!isValueInLeftRange(value)) { updateRangeWidth(value); + updateRight(); updateLeft(value); notifyListeners(); } From 92baee59d868c5c3b6a4e2efe450946763af251c Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 10:28:15 +0200 Subject: [PATCH 06/32] bug4134_2: clean up of WindStreamletsRaceboardOverlay. --- .../ui/shared/racemap/WindStreamletsRaceboardOverlay.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index c69806e48a8..d155c1dcae7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -53,7 +53,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen private static final long RESOLUTION_IN_MILLIS = 5000; private static final int WIND_FETCH_INTERVAL_IN_MILLIS = 10000; private static final int CHECK_WIND_SOURCE_INTERVAL_IN_MILLIS = 60000; - private boolean visible = false; private final Timer timer; private Swarm swarm; @@ -66,10 +65,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen private final Scheduler scheduler; private Canvas streamletLegend; private boolean firstColoring = true; - + private boolean colored; private long latitudeCount; private double latitudeSum; - private final NumberFormat numberFormatOneDecimal = NumberFormatterFactory.getDecimalFormat(1); public WindStreamletsRaceboardOverlay(MapWidget map, int zIndex, final Timer timer, @@ -337,7 +335,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } } } -private boolean colored; + public void setColors(boolean isColored) { this.colored = isColored; if ((isColored) && (firstColoring)) { From dc90431a4a164cc95cd4ac5cbd00c6acc9fd93b9 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 11:44:27 +0200 Subject: [PATCH 07/32] bug4134_2: Removed colors from VectorField and sublcasses and some code formatting. --- .../WindStreamletsRaceboardOverlay.java | 18 ---------- .../WindStreamletsCanvasOverlay.java | 16 --------- .../ui/simulator/streamlets/RectField.java | 22 ------------ .../simulator/streamlets/SimulatorField.java | 34 ------------------- .../gwt/ui/simulator/streamlets/Swarm.java | 14 +------- .../ui/simulator/streamlets/VectorField.java | 13 ------- .../WindInfoForRaceVectorField.java | 32 ----------------- 7 files changed, 1 insertion(+), 148 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index d155c1dcae7..544853a719c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -89,11 +89,9 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen getCanvas().getElement().setId("swarm-display"); createStreamletLegend(map); } - public double getAverageLatitudeDeg() { return latitudeCount > 0 ? latitudeSum/latitudeCount : 0; } - private void updateAverageLatitudeDeg(WindInfoForRaceDTO windInfoForRace) { for (Entry windSourceAndTrack : windInfoForRace.windTrackInfoByWindSource.entrySet()) { for (WindDTO wind : windSourceAndTrack.getValue().windFixes) { @@ -107,7 +105,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen windField.setAverageLatitudeDeg(latitudeSum/latitudeCount); } } - private void createStreamletLegend(MapWidget map) { streamletLegend = Canvas.createIfSupported(); streamletLegend.addStyleName("MapStreamletLegend"); @@ -192,7 +189,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } } } - public void startStreamlets() { scheduleWindDataRefresh(); if (swarm == null) { @@ -204,7 +200,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen this.swarm.start(animationIntervalMillis); this.swarm.getColorMapper().addListener(this); } - private void scheduleWindDataRefresh() { scheduler.scheduleFixedPeriod(new RepeatingCommand() { @Override @@ -223,14 +218,12 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen // Now run things once, first updating the wind sources, then grabbing the wind from those sources: updateWindSourcesToObserve(new Runnable() { @Override public void run() { updateWindField(); } }); } - private void stopStreamlets() { if (this.swarm != null) { this.swarm.stop(); this.swarm.getColorMapper().removeListener(this); } } - /** * Check which wind sources are available for the race identified by {@link #raceIdentifier}. For any wind source * not yet observed (contained in the keys of {@link #windInfoForRace}'s @@ -244,7 +237,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()), NotificationType.WARNING); } - @Override public void onSuccess(WindInfoForRaceDTO result) { windInfoForRace.raceIsKnownToStartUpwind = result.raceIsKnownToStartUpwind; @@ -261,7 +253,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } })); } - private void updateWindField() { Date timeOfLastFixOfSource = null; Set windSourceTypeNames = new HashSet<>(); @@ -284,7 +275,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()), NotificationType.WARNING); } - @Override public void onSuccess(WindInfoForRaceDTO result) { updateAverageLatitudeDeg(result); @@ -311,12 +301,10 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } })); } - @Override public boolean isVisible() { return this.visible; } - @Override public void setVisible(boolean isVisible) { if (getCanvas() != null) { @@ -335,7 +323,6 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } } } - public void setColors(boolean isColored) { this.colored = isColored; if ((isColored) && (firstColoring)) { @@ -345,26 +332,21 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen if (swarm != null) { swarm.setColors(isColored);} } - @Override public void removeFromMap() { this.setVisible(false); } - @Override protected void drawCenterChanged() { } - public void onBoundsChanged(boolean zoomChanged) { if (swarm != null) { int swarmPause = (zoomChanged ? 5 : 1); swarm.onBoundsChanged(zoomChanged, swarmPause); } } - @Override public void onColorMappingChanged() { drawLegend(); } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/WindStreamletsCanvasOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/WindStreamletsCanvasOverlay.java index 9e0884443e7..90dc4b2923a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/WindStreamletsCanvasOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/WindStreamletsCanvasOverlay.java @@ -45,16 +45,12 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti windFieldDTO = null; getCanvas().getElement().setId("swarm-display"); } - public WindFieldDTO getWindFieldDTO() { return this.windFieldDTO; } - public WindFieldGenParamsDTO getWindParams() { return this.windParams; } - - public void startStreamlets() { if (swarm == null) { final SimulatorField field = new SimulatorField(getWindFieldDTO(), getWindParams(), streamletPars, coordinateSystem); @@ -63,27 +59,22 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti } this.swarm.start(40); } - public void stopStreamlets() { if (swarm != null) { this.swarm.stop(); } } - public void setEndDate(Date endDate) { this.endDate = endDate; } - public void setWindField(final WindFieldDTO windFieldDTO) { this.windFieldDTO = windFieldDTO; this.swarm = null; } - @Override public boolean isVisible() { return this.visible; } - @Override public void setVisible(boolean isVisible) { if (getCanvas() != null) { @@ -99,14 +90,12 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti } } } - @Override public void addToMap() { if (timer != null) { timer.addTimeListener(this); } } - @Override public void removeFromMap() { if (timer != null) { @@ -114,11 +103,9 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti } this.setVisible(false); } - @Override protected void drawCenterChanged() { } - @Override protected void draw() { super.draw(); @@ -135,15 +122,12 @@ public class WindStreamletsCanvasOverlay extends FullCanvasOverlay implements Ti } } } - public Swarm getSwarm() { return this.swarm; } - @Override public void timeChanged(final Date newDate, Date oldDate) { } - @Override public boolean shallStop() { if (timer.getTime().getTime() >= this.endDate.getTime()) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/RectField.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/RectField.java index 10d84306259..a352e1220e7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/RectField.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/RectField.java @@ -29,13 +29,11 @@ public class RectField implements VectorField { private final double maxLength; private final double particleFactor; - private final String[] colorsForSpeeds; private final CoordinateSystem coordinateSystem; public RectField(Vector[][] field, double x0, double y0, double x1, double y1, StreamletParameters parameters, CoordinateSystem coordinateSystem) { this.coordinateSystem = coordinateSystem; - colorsForSpeeds = createColorsForSpeeds(); this.x0 = x0; this.x1 = x1; this.y0 = y0; @@ -147,26 +145,6 @@ public class RectField implements VectorField { public double getParticleWeight(LatLng p, Vector v) { return v == null ? 0 : (1.0 - v.length() / this.maxLength); } - - @Override - public String getColor(double speed) { - return colorsForSpeeds[getIntensity(speed)]; - } - - private String[] createColorsForSpeeds() { - String[] colors = new String[256]; - double alpha = 1.0; - int greyValue = 255; - for (int i = 0; i < 256; i++) { - colors[i] = "rgba(" + (greyValue) + "," + (greyValue) + "," + (greyValue) + "," + (alpha * i / 255.0) + ")"; - } - return colors; - } - - private int getIntensity(double speed) { - double s = speed / maxLength; - return (int) Math.min(255, 90 + Math.round(350 * s)); - } @Override public double getLineWidth(double speed) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SimulatorField.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SimulatorField.java index 1890a8d0426..e6e1da78e37 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SimulatorField.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/SimulatorField.java @@ -49,7 +49,6 @@ public class SimulatorField implements VectorField { private final Position nvX; private final double[][][] data; - private final String[] colorsForSpeeds; private final Date startTime; private final Duration timeStep; private final CoordinateSystem coordinateSystem; @@ -58,7 +57,6 @@ public class SimulatorField implements VectorField { this.coordinateSystem = coordinateSystem; this.startTime = windParams.getStartTime(); this.timeStep = windParams.getTimeStep(); - this.colorsForSpeeds = createColorsForSpeeds(); this.rcStart = new DegreePosition(windData.windData.rcStart.getLatDeg(), windData.windData.rcStart.getLngDeg()); this.rcEnd = new DegreePosition(windData.windData.rcEnd.getLatDeg(), windData.windData.rcEnd.getLngDeg()); this.resX = windData.windData.resX; @@ -228,38 +226,6 @@ public class SimulatorField implements VectorField { return v == null ? 0 : (v.length() / this.maxLength + 0.1); } - private String[] createColorsForSpeeds() { - String[] colors = new String[256]; - double alphaMin = 0.0; - double alphaMax = 0.9; - int greyValue = 255; - for (int i = 0; i < 256; i++) { - colors[i] = "rgba(" + (greyValue) + "," + (greyValue) + "," + (greyValue) + "," - + (alphaMin + (alphaMax - alphaMin) * i / 255.0) + ")"; - } - return colors; - } - - @Override - public String getColor(double speed) { - return colorsForSpeeds[getIntensity(speed)]; - } - - private int getIntensity(double speed) { - /* - * normalized intensity: speed == average wind speed => intensity 0.5 speed <= minimum wind speed => intensity - * 0.0 speed between 0.0 and 1.0 double s; if (minLength == maxLength) { s = 0.5; } else if (speed <= minLength) - * { s = 0.0; } else { s = (speed - minLength) / (maxLength - minLength); } - */ - - /* - * absolute intensity speed == 12kn => intensity 0.7 speed == 20kn => intensity 1.0 speed == 0kn => intensity - * 0.25 - */ - double s = 0.7 + 0.0375 * (speed - 12.0); - return (int) Math.max(0, Math.min(255, Math.round(255 * s))); - } - @Override public double getLineWidth(double speed) { /* diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index a8ce76b580e..32f8d1871f5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -63,6 +63,7 @@ public class Swarm implements TimeListener { private HandlerRegistration handlerRegistration; + private boolean colored = false; private final ValueRangeBoundaries valueRange; private final ColorMapper colorMapper; @@ -80,7 +81,6 @@ public class Swarm implements TimeListener { valueRange = new ValueRangeBoundaries(0.0, 120.0, /*percentage*/ 0.1); colorMapper = new ColorMapper(valueRange, !colored); } - public void start(final int animationIntervalMillis) { fullcanvas.setCanvasSettings(); // if map is not yet loaded, wait for it @@ -96,7 +96,6 @@ public class Swarm implements TimeListener { }); } } - private void startWithMap(int animationIntervalMillis) { projection = new Mercator(fullcanvas, map); projection.calibrate(); @@ -105,11 +104,9 @@ public class Swarm implements TimeListener { swarmContinue = true; startLoop(animationIntervalMillis); } - public void stop() { swarmContinue = false; } - private Particle createParticle() { Particle particle = null; boolean done = false; @@ -140,7 +137,6 @@ public class Swarm implements TimeListener { } return particle; } - private LatLng getRandomPosition() { final LatLng result; double rndY = Math.random(); @@ -157,7 +153,6 @@ public class Swarm implements TimeListener { } return newParticles; } - public void onBoundsChanged(boolean zoomChanged, int swarmPause) { this.zoomChanged |= zoomChanged; if (this.zoomChanged) { @@ -165,7 +160,6 @@ public class Swarm implements TimeListener { } this.swarmPause = swarmPause; } - private void updateBounds() { LatLngBounds fieldBounds = this.field.getFieldCorners(); final LatLngBounds mapBounds = map.getBounds(); @@ -179,11 +173,9 @@ public class Swarm implements TimeListener { cosineOfAverageLatitude = Math.cos((visibleBoundsOfField.getSouthWest().getLatitude()/180.*Math.PI+ visibleBoundsOfField.getNorthEast().getLatitude()/180.*Math.PI)/2); }; - //native void log(String message) /*-{ // console.log( message ); //}-*/; - private void startLoop(final int animationIntervalMillis) { // Create animation-loop based on timer timeout loopTimer = new com.google.gwt.user.client.Timer() { @@ -221,7 +213,6 @@ public class Swarm implements TimeListener { }; loopTimer.schedule(animationIntervalMillis); } - private void drawSwarm() { Context2d ctxt = canvas.getContext2d(); ctxt.setGlobalAlpha(0.08); @@ -245,8 +236,6 @@ public class Swarm implements TimeListener { ctxt.stroke(); } } - - private boolean colored = false; public void setColors(boolean isColored) { this.colored = isColored; colorMapper.setGrey(!isColored); @@ -301,7 +290,6 @@ public class Swarm implements TimeListener { drawSwarm(); return true; } - public ValueRangeBoundaries getValueRange() { return valueRange; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/VectorField.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/VectorField.java index ccc3a0db553..3d3cf6fccee 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/VectorField.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/VectorField.java @@ -12,9 +12,6 @@ import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem; * A field of vectors to display in a streamlet {@link Swarm}. The {@link Vector}s returned by {@link #getVector(Position, Date)} * are used to initialize {@link Particle}s. Their "speed" is the {@link Vector#length() length} of the vector.

* - * This field provides color strings for each possible speed which are then used to style the particles as they fly through - * the swarm. - * * @author Christopher Ronnewinkel (D036654) * @author Axel Uhl (D043530) * @@ -83,14 +80,4 @@ public interface VectorField { LatLngBounds getFieldCorners(); double getParticleFactor(); - - /** - * Computes a color for a particle flying at a certain speed. - * - * @param speed - * a speed as obtained by computing a {@link Vector}'s {@link Vector#length() length}. - * @return an RGB color with optional transparency that is a legal color in CSS. Example: - * "rgba(1, 2, 3, 0.4)" - */ - String getColor(double speed); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java index 84266276d22..10969bf6e18 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java @@ -48,7 +48,6 @@ public class WindInfoForRaceVectorField implements VectorField, AverageLatitudeP private double averageLatitudeCosine; private double knotsInDegreePerFrame; private final CoordinateSystem coordinateSystem; - private boolean colored = false; private final Comparator windByRequestTimePointComparator = new Comparator() { @Override @@ -215,35 +214,4 @@ public class WindInfoForRaceVectorField implements VectorField, AverageLatitudeP public double getParticleFactor() { return 0.5; } - - public void setColors(boolean isColored) { - this.colored = isColored; - } - - public boolean getColors() { - return this.colored; - } - - /** - * {@link #MAX_WIND_SPEED_IN_KNOTS maximum wind speed} is fully opaque; zero speed is fully transparent - */ - @Override - public String getColor(double speed) { - if (this.colored) { - double h; - if (speed <= 4.0) { - h = 240.0; - } else if (speed <= 12.0) { - h = 120.0 + (12.0 - speed) / (12.0 - 4.0) * (240.0 - 120.0); - } else if (speed <= 20.0) { - h = 0.0 + (20.0 - speed) / (20.0 - 12.0) * (120.0 - 0.0); - } else { - h = 0.0; - } - return "hsl(" + Math.round(h) + ", 100%, 50%)"; - } else { - return "rgba(255,255,255," + Math.min(1.0, 0.5 + 0.6 * speed / MAX_WIND_SPEED_IN_KNOTS) + ")"; - } - } - } From 255f8b7dfcdf678f457bcb0493c849de84a67db3 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 14:31:28 +0200 Subject: [PATCH 08/32] bug4134_2: Changed behaviour of ValueRangeFlexibleBoundaries. --- .../ui/simulator/streamlets/ColorMapper.java | 18 ++++-- .../gwt/ui/simulator/streamlets/Swarm.java | 6 +- ...java => ValueRangeFlexibleBoundaries.java} | 57 ++++++++----------- ...ngeFlexibleBoundariesChangedListener.java} | 2 +- 4 files changed, 42 insertions(+), 41 deletions(-) rename java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/{ValueRangeBoundaries.java => ValueRangeFlexibleBoundaries.java} (53%) rename java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/{ValueRangeBoundariesChangedListener.java => ValueRangeFlexibleBoundariesChangedListener.java} (60%) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 41d2703e908..76cbf8d5f11 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -5,20 +5,22 @@ import java.util.Set; /** * This class maps a given range of values to a full color spectrum. The color spectrum could also be a grey scale. - * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeBoundaries} to get those. - * The ColorMapper has listeners that will be notified if the colormapping has been changed. + * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeFlexibleBoundaries} to get those. The + * ColorMapper has listeners that will be notified if the colormapping has been changed. The ColorMapper accepts value + * ranges that are negative, negative numbers will display as blue (hsl(240, 100%, 50%)) or fully transparent grey + * (rgba(255,255,255,1.0)). * * @author D073259 * */ -public class ColorMapper implements ValueRangeBoundariesChangedListener { - private final ValueRangeBoundaries valueRange; +public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener { + private final ValueRangeFlexibleBoundaries valueRange; private double minValue; private double maxValue; private boolean isGrey; private final Set colorMapperChangedListeners; - public ColorMapper(ValueRangeBoundaries valueRange, boolean isGrey) { + public ColorMapper(ValueRangeFlexibleBoundaries valueRange, boolean isGrey) { this.valueRange = valueRange; this.valueRange.addListener(this); minValue = this.valueRange.getMinLeft(); @@ -34,8 +36,14 @@ public class ColorMapper implements ValueRangeBoundariesChangedListener { public String getColor(double value) { if (isGrey) { + if (value < 0) { + return "rgba(255,255,255, 1.0)"; + } return "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; } else { + if (value < 0) { + return "hsl(240, 100%, 50%)"; + } double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; return "hsl(" + Math.round(h) + ", 100%, 50%)"; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 32f8d1871f5..81c6053320a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -64,7 +64,7 @@ public class Swarm implements TimeListener { private HandlerRegistration handlerRegistration; private boolean colored = false; - private final ValueRangeBoundaries valueRange; + private final ValueRangeFlexibleBoundaries valueRange; private final ColorMapper colorMapper; public Swarm(FullCanvasOverlay fullcanvas, MapWidget map, com.sap.sse.gwt.client.player.Timer timer, @@ -78,7 +78,7 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); - valueRange = new ValueRangeBoundaries(0.0, 120.0, /*percentage*/ 0.1); + valueRange = new ValueRangeFlexibleBoundaries(0.0, 120.0, /*percentage*/ 0.15); colorMapper = new ColorMapper(valueRange, !colored); } public void start(final int animationIntervalMillis) { @@ -290,7 +290,7 @@ public class Swarm implements TimeListener { drawSwarm(); return true; } - public ValueRangeBoundaries getValueRange() { + public ValueRangeFlexibleBoundaries getValueRange() { return valueRange; } public ColorMapper getColorMapper() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java similarity index 53% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java index af83741c94a..994722118a2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundaries.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java @@ -4,9 +4,8 @@ import java.util.HashSet; import java.util.Set; /** - * This class defines if a given value is within boundaries that are flexible by a given rangeWidth. The rangeWidth is - * defined by a percentage of the minimum value, otherwise the adjustment of the boundaries will be biased and the max - * boundaries are always much bigger then the minimum boundaries. It needs four types of boundaries: + * This class defines if a given value is within boundaries that are flexible by a given halfBoundaryWidth. The halfBoundaryWidth is + * defined by a percentage of the difference between max and min of a value range. It needs four types of boundaries: * a) minLeft * b) maxLeft * c) minRight @@ -15,54 +14,48 @@ import java.util.Set; * If a value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the * one or the other. Also there should be the possibility to add listeners that will notify on a boundary change. * - * A ValueRangeBoundaries needs an initialMin, a initialMax and a percentage that indicates the width of the value range + * A ValueRangeFlexibleBoundaries needs an initialMin, a initialMax and a percentage that indicates the width of the value range * surrounding initialMin and Max. * * @author D073259 * */ -public class ValueRangeBoundaries { +public class ValueRangeFlexibleBoundaries { private double minLeft; private double maxLeft; private double minRight; private double maxRight; + private double min; + private double max; private final double percentage; - private double halfRangeWidth; - private final Set valueRangeChangedListeners; + private double halfBoundaryWidth; + private final Set valueRangeChangedListeners; - public ValueRangeBoundaries(double initialMin, double initialMax, double percentage) { + public ValueRangeFlexibleBoundaries(double initialMin, double initialMax, double percentage) { this.percentage = percentage; - updateLeft(initialMin); - updateRight(initialMax); valueRangeChangedListeners = new HashSet<>(); - this.halfRangeWidth = ((initialMin * (1 + percentage)) - (initialMin * (1 - percentage)))/2; + min = initialMin; + max = initialMax; + update(); } - private void updateLeft(double value) { - minLeft = value - halfRangeWidth; - maxLeft = value + halfRangeWidth; - } - private void updateRight() { - minRight =- halfRangeWidth; - maxRight =+ halfRangeWidth; - } - private void updateRight(double value) { - minRight = value - halfRangeWidth; - maxRight = value + halfRangeWidth; - } - private void updateRangeWidth(double newMinValue) { - halfRangeWidth = ((newMinValue * (1 + percentage)) - (newMinValue * (1 - percentage)))/2; + private void update() { + halfBoundaryWidth = (max - min) * (percentage); + minLeft = min - halfBoundaryWidth; + maxLeft = min + halfBoundaryWidth; + minRight = max - halfBoundaryWidth; + maxRight = max + halfBoundaryWidth; } public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double value) { if (!isValueInRightRange(value)) { - updateRight(value); + max = value; + update(); notifyListeners(); } } public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double value) { if (!isValueInLeftRange(value)) { - updateRangeWidth(value); - updateRight(); - updateLeft(value); + min = value; + update(); notifyListeners(); } } @@ -86,14 +79,14 @@ public class ValueRangeBoundaries { public double getMaxRight() { return maxRight; } - public void addListener(ValueRangeBoundariesChangedListener listener) { + public void addListener(ValueRangeFlexibleBoundariesChangedListener listener) { valueRangeChangedListeners.add(listener); } - public void removeListener(ValueRangeBoundariesChangedListener listener) { + public void removeListener(ValueRangeFlexibleBoundariesChangedListener listener) { valueRangeChangedListeners.remove(listener); } public void notifyListeners() { - for (ValueRangeBoundariesChangedListener listener : valueRangeChangedListeners) { + for (ValueRangeFlexibleBoundariesChangedListener listener : valueRangeChangedListeners) { listener.onValueRangeBoundariesChanged(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java similarity index 60% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java index 68b1414a748..ff3f0f45f8b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeBoundariesChangedListener.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java @@ -1,5 +1,5 @@ package com.sap.sailing.gwt.ui.simulator.streamlets; -public interface ValueRangeBoundariesChangedListener { +public interface ValueRangeFlexibleBoundariesChangedListener { void onValueRangeBoundariesChanged(); } From c51fbb82d55dfb70e713ec7193b2aca843c924fb Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 14:45:45 +0200 Subject: [PATCH 09/32] bug4134_2: Changed ColorMapper. Removed unnecessary check for negative values. --- .../gwt/ui/simulator/streamlets/ColorMapper.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 76cbf8d5f11..e766adddcfb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -6,9 +6,7 @@ import java.util.Set; /** * This class maps a given range of values to a full color spectrum. The color spectrum could also be a grey scale. * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeFlexibleBoundaries} to get those. The - * ColorMapper has listeners that will be notified if the colormapping has been changed. The ColorMapper accepts value - * ranges that are negative, negative numbers will display as blue (hsl(240, 100%, 50%)) or fully transparent grey - * (rgba(255,255,255,1.0)). + * ColorMapper has listeners that will be notified if the colormapping has been changed. * * @author D073259 * @@ -36,14 +34,8 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener public String getColor(double value) { if (isGrey) { - if (value < 0) { - return "rgba(255,255,255, 1.0)"; - } return "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; } else { - if (value < 0) { - return "hsl(240, 100%, 50%)"; - } double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; return "hsl(" + Math.round(h) + ", 100%, 50%)"; } From ce9139f813bc61dcbbf6a302d6e3ec487fbcf49d Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 16:53:32 +0200 Subject: [PATCH 10/32] bug4134_2: Added tests for ColorMapper and ValueRangeFlexibleBoundaries. --- .../sailing/gwt/ui/test/ColorMapperTest.java | 24 ++++++++++++ .../ValueRangeFlexibleBoundariesTest.java | 37 +++++++++++++++++++ .../ValueRangeFlexibleBoundaries.java | 21 +++++------ 3 files changed, 71 insertions(+), 11 deletions(-) create mode 100755 java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java create mode 100755 java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java new file mode 100755 index 00000000000..1720fb29c7d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -0,0 +1,24 @@ +package com.sap.sailing.gwt.ui.test; +import static org.junit.Assert.*; +import org.junit.Test; +import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapper; +import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; + +public class ColorMapperTest { + ValueRangeFlexibleBoundaries valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.0); + ColorMapper colorMapperTestColored = new ColorMapper(valueRange, false); + ColorMapper colorMapperTestGrey = new ColorMapper(valueRange, true); + double testValue1 = -5.0; + String expectedResult1colored = "hsl(240, 100%, 50%)"; + String expectedResult1grey = "rgba(255,255,255,0.0)"; + double testValue2 = 5.0; + String expectedResult2colored = "hsl(0, 100%, 50%)"; + String expectedResult2grey = "rgba(255,255,255,1.0)"; + @Test + public void testGetColor() { + assertEquals(expectedResult1colored, colorMapperTestColored.getColor(testValue1)); + assertEquals(expectedResult1grey, colorMapperTestGrey.getColor(testValue1)); + assertEquals(expectedResult2colored, colorMapperTestColored.getColor(testValue2)); + assertEquals(expectedResult2grey, colorMapperTestGrey.getColor(testValue2)); + } +} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java new file mode 100755 index 00000000000..b574d187910 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.ui.test; +import static org.junit.Assert.*; +import org.junit.Test; +import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; + +public class ValueRangeFlexibleBoundariesTest { + //Create new valueRange, boundaries should be [-6,-4] and [4,6]. + ValueRangeFlexibleBoundaries valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.10); + Double minLeft = -6.0; + Double maxRight = 6.0; + @Test + public void testCheckIfValueIsInRightBoundaryRangeAndUpdateIfNecessary() { + //update left border to 0.0, that means boundaries now should be [-0.5,0.5] and [4.5,5.5] + valueRange.checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(0.0); + Double newMinLeft = -0.5; + Double newMaxRight = 5.5; + assertEquals(newMinLeft, (Double) valueRange.getMinLeft()); + assertEquals(newMaxRight, (Double) valueRange.getMaxRight()); + } + @Test + public void testCheckIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary() { + //update right border to 20, that means the boundaries now should be [-7.5,-2.5] and [17.5,22.5] + valueRange.checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(20.0); + Double newMaxRight = 22.5; + Double newMinLeft = -7.5; + assertEquals(newMaxRight, (Double) valueRange.getMaxRight()); + assertEquals(newMinLeft, (Double) valueRange.getMinLeft()); + } + @Test + public void testGetMinLeft() { + assertEquals(minLeft, (Double) valueRange.getMinLeft()); + } + @Test + public void testGetMaxRight() { + assertEquals(maxRight, (Double) valueRange.getMaxRight()); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java index 994722118a2..91f2355485d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java @@ -4,14 +4,14 @@ import java.util.HashSet; import java.util.Set; /** - * This class defines if a given value is within boundaries that are flexible by a given halfBoundaryWidth. The halfBoundaryWidth is + * This class defines if a given extremal value is within boundaries that are flexible by a given halfBoundaryWidth. The halfBoundaryWidth is * defined by a percentage of the difference between max and min of a value range. It needs four types of boundaries: * a) minLeft * b) maxLeft * c) minRight * d) maxRight - * (a)<--value->(b)..........(c)<--value->(d) - * If a value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the + * (a)<--minValue->(b)..........(c)<--maxValue->(d) + * If an extremal value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the * one or the other. Also there should be the possibility to add listeners that will notify on a boundary change. * * A ValueRangeFlexibleBoundaries needs an initialMin, a initialMax and a percentage that indicates the width of the value range @@ -44,19 +44,18 @@ public class ValueRangeFlexibleBoundaries { maxLeft = min + halfBoundaryWidth; minRight = max - halfBoundaryWidth; maxRight = max + halfBoundaryWidth; + notifyListeners(); } - public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double value) { - if (!isValueInRightRange(value)) { - max = value; + public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double maxValue) { + if (!isValueInRightRange(maxValue)) { + max = maxValue; update(); - notifyListeners(); } } - public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double value) { - if (!isValueInLeftRange(value)) { - min = value; + public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double minValue) { + if (!isValueInLeftRange(minValue)) { + min = minValue; update(); - notifyListeners(); } } private boolean isValueInLeftRange(double value) { From a41ae5785495638e470e33a7877339998f32caca Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 16:55:39 +0200 Subject: [PATCH 11/32] bug4134_2: Modified ValueRangeFlexibleBoundariesTest. --- .../sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java index b574d187910..988d9c038e4 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java @@ -9,7 +9,7 @@ public class ValueRangeFlexibleBoundariesTest { Double minLeft = -6.0; Double maxRight = 6.0; @Test - public void testCheckIfValueIsInRightBoundaryRangeAndUpdateIfNecessary() { + public void testCheckIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary() { //update left border to 0.0, that means boundaries now should be [-0.5,0.5] and [4.5,5.5] valueRange.checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(0.0); Double newMinLeft = -0.5; @@ -18,7 +18,7 @@ public class ValueRangeFlexibleBoundariesTest { assertEquals(newMaxRight, (Double) valueRange.getMaxRight()); } @Test - public void testCheckIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary() { + public void testCheckIfValueIsInRightBoundaryRangeAndUpdateIfNecessary() { //update right border to 20, that means the boundaries now should be [-7.5,-2.5] and [17.5,22.5] valueRange.checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(20.0); Double newMaxRight = 22.5; From 366f903aefcce60d334f2a9e2b5ce235bb149486 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Wed, 15 Aug 2018 17:18:00 +0200 Subject: [PATCH 12/32] bug4134_2: white space changes only. --- .../sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index e766adddcfb..470ce17c649 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -26,12 +26,10 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener this.isGrey = isGrey; colorMapperChangedListeners = new HashSet<>(); } - public void setGrey(boolean isGrey) { this.isGrey = isGrey; notifyListeners(); } - public String getColor(double value) { if (isGrey) { return "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; @@ -40,12 +38,10 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener return "hsl(" + Math.round(h) + ", 100%, 50%)"; } } - private void updateMinMax() { minValue = valueRange.getMinLeft(); maxValue = valueRange.getMaxRight(); } - @Override public void onValueRangeBoundariesChanged() { updateMinMax(); From 97ecdd01aaed98db7050bf3be9065524c2f15178 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 16 Aug 2018 18:46:57 +0200 Subject: [PATCH 13/32] update range bounds in single call; added tests; Javadoc, code formatting and conventions Change-Id: Iefa8e9e0cebbf2a41987f34c55f9a97590113cdd --- .../ValueRangeFlexibleBoundariesTest.java | 89 +++++++++++++++--- .../WindStreamletsRaceboardOverlay.java | 37 ++++---- .../ui/simulator/streamlets/ColorMapper.java | 19 +++- .../gwt/ui/simulator/streamlets/Swarm.java | 3 +- .../ValueRangeFlexibleBoundaries.java | 94 +++++++++++++------ 5 files changed, 174 insertions(+), 68 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java index 988d9c038e4..1b545cc473e 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java @@ -1,37 +1,98 @@ package com.sap.sailing.gwt.ui.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.*; + +import org.junit.Before; import org.junit.Test; + import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; +import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundariesChangedListener; public class ValueRangeFlexibleBoundariesTest { + private static final double EPSILON = 0.00000001; //Create new valueRange, boundaries should be [-6,-4] and [4,6]. - ValueRangeFlexibleBoundaries valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.10); - Double minLeft = -6.0; - Double maxRight = 6.0; + private ValueRangeFlexibleBoundaries valueRange; + private double minLeft; + private double maxRight; + private ValueRangeFlexibleBoundariesChangedListener listener; + + @Before + public void setUp() { + // a ten percent range at each end of an original range of length 10, so length 1 at each end, + // spread symmetrically around the min/max value + valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.10); + minLeft = -6.0; + maxRight = 6.0; + listener = mock(ValueRangeFlexibleBoundariesChangedListener.class); + valueRange.addListener(listener); + verify(listener, times(0)).onValueRangeBoundariesChanged(); + } + + @Test + public void testExceptionForGreaterMinThanMax() { + try { + valueRange.setMinMax(6, 5); + fail("Excpected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + @Test public void testCheckIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary() { - //update left border to 0.0, that means boundaries now should be [-0.5,0.5] and [4.5,5.5] - valueRange.checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(0.0); - Double newMinLeft = -0.5; - Double newMaxRight = 5.5; - assertEquals(newMinLeft, (Double) valueRange.getMinLeft()); - assertEquals(newMaxRight, (Double) valueRange.getMaxRight()); + // update left border to 0.0, that means boundaries now should be [-0.5,0.5] and [4.5,5.5] + // because the new range has length 5, so 10% of that is .5, so the left range is -0.5..0.5 + // and the right range is 4.5..5.5. We expect the update to be delivered by exactly one + // call to the listener + valueRange.setMinMax(0.0, 5.0); + double newMinLeft = -0.5; + double newMaxRight = 5.5; + assertEquals(newMinLeft, valueRange.getMinLeft(), EPSILON); + assertEquals(newMaxRight, valueRange.getMaxRight(), EPSILON); + verify(listener, times(1)).onValueRangeBoundariesChanged(); } + + @Test + public void testUpdateWithinBoundaries() { + valueRange.setMinMax(-5.5, 5.5); + verify(listener, times(0)).onValueRangeBoundariesChanged(); + valueRange.setMinMax(-4.5, 4.5); + verify(listener, times(0)).onValueRangeBoundariesChanged(); + } + + @Test + public void testGradualUpdateCrossingBoundariesEventuallyTriggerUpdate() { + valueRange.setMinMax(-5.5, 5.0); + verify(listener, times(0)).onValueRangeBoundariesChanged(); + valueRange.setMinMax(-6-EPSILON, 5.0); // just barely cross the *original* range boundary to the left, + // thus asserting that it wasn't expanded earlier by coming closer (from -5.0 to -5.5) to its end + verify(listener, times(1)).onValueRangeBoundariesChanged(); + verify(listener, times(1)).onValueRangeBoundariesChanged(); // ensure that calling verify doesn't clean counter + // and now it *was* expanded to cover -6..5, so the tolerance has become slightly greater, and 6+EPSILON + // should fit into the new bounds easily + valueRange.setMinMax(-6-EPSILON, 6+EPSILON); + verify(listener, times(1)).onValueRangeBoundariesChanged(); + } + @Test public void testCheckIfValueIsInRightBoundaryRangeAndUpdateIfNecessary() { - //update right border to 20, that means the boundaries now should be [-7.5,-2.5] and [17.5,22.5] - valueRange.checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(20.0); + // update right border to 20, that means the boundaries now should be [-7.5,-2.5] and [17.5,22.5] + valueRange.setMinMax(-5.0, 20.0); Double newMaxRight = 22.5; Double newMinLeft = -7.5; assertEquals(newMaxRight, (Double) valueRange.getMaxRight()); assertEquals(newMinLeft, (Double) valueRange.getMinLeft()); + verify(listener, times(1)).onValueRangeBoundariesChanged(); } + @Test public void testGetMinLeft() { - assertEquals(minLeft, (Double) valueRange.getMinLeft()); + assertEquals(minLeft, valueRange.getMinLeft(), EPSILON); } + @Test public void testGetMaxRight() { - assertEquals(maxRight, (Double) valueRange.getMaxRight()); + assertEquals(maxRight, valueRange.getMaxRight(), EPSILON); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index 544853a719c..c27e1105c60 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -89,9 +89,11 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen getCanvas().getElement().setId("swarm-display"); createStreamletLegend(map); } + public double getAverageLatitudeDeg() { return latitudeCount > 0 ? latitudeSum/latitudeCount : 0; } + private void updateAverageLatitudeDeg(WindInfoForRaceDTO windInfoForRace) { for (Entry windSourceAndTrack : windInfoForRace.windTrackInfoByWindSource.entrySet()) { for (WindDTO wind : windSourceAndTrack.getValue().windFixes) { @@ -105,22 +107,10 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen windField.setAverageLatitudeDeg(latitudeSum/latitudeCount); } } + private void createStreamletLegend(MapWidget map) { streamletLegend = Canvas.createIfSupported(); streamletLegend.addStyleName("MapStreamletLegend"); - //streamletLegend.setTitle(stringMessages.simulationLegendTooltip()); - /*streamletLegend.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - int clickPixelY = event.getRelativeY(streamletLegend.getElement()); - int legendRow = clickPixelY / ((int) rectHeight); - int pathRow = legendRow - (racePath!=null ? 1 : 0); - //Window.alert("clickPixelY: " + clickPixelY + "\nlegendRow: " + legendRow); - visiblePaths[pathRow] = !visiblePaths[pathRow]; - clearCanvas(); - drawPaths(); - } - });*/ map.setControls(ControlPosition.LEFT_BOTTOM, streamletLegend); int canvasWidth = 500; int canvasHeight = 60; @@ -128,7 +118,8 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen streamletLegend.setWidth(String.valueOf(canvasWidth)); streamletLegend.setHeight(String.valueOf(canvasHeight)); streamletLegend.setCoordinateSpaceWidth(canvasWidth); - streamletLegend.setCoordinateSpaceHeight(canvasHeight); } + streamletLegend.setCoordinateSpaceHeight(canvasHeight); + } public void drawLegend() { if (streamletLegend.isVisible()) { @@ -189,6 +180,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } } } + public void startStreamlets() { scheduleWindDataRefresh(); if (swarm == null) { @@ -200,6 +192,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen this.swarm.start(animationIntervalMillis); this.swarm.getColorMapper().addListener(this); } + private void scheduleWindDataRefresh() { scheduler.scheduleFixedPeriod(new RepeatingCommand() { @Override @@ -218,12 +211,14 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen // Now run things once, first updating the wind sources, then grabbing the wind from those sources: updateWindSourcesToObserve(new Runnable() { @Override public void run() { updateWindField(); } }); } + private void stopStreamlets() { if (this.swarm != null) { this.swarm.stop(); this.swarm.getColorMapper().removeListener(this); } } + /** * Check which wind sources are available for the race identified by {@link #raceIdentifier}. For any wind source * not yet observed (contained in the keys of {@link #windInfoForRace}'s @@ -234,8 +229,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen sailingService.getWindSourcesInfo(raceIdentifier, new MarkedAsyncCallback<>(new AsyncCallback() { @Override public void onFailure(Throwable caught) { - Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()), - NotificationType.WARNING); + Notification.notify(stringMessages.errorFetchingWindStreamletData(caught.getMessage()), NotificationType.WARNING); } @Override public void onSuccess(WindInfoForRaceDTO result) { @@ -253,6 +247,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } })); } + private void updateWindField() { Date timeOfLastFixOfSource = null; Set windSourceTypeNames = new HashSet<>(); @@ -301,10 +296,12 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } })); } + @Override public boolean isVisible() { return this.visible; } + @Override public void setVisible(boolean isVisible) { if (getCanvas() != null) { @@ -323,6 +320,7 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } } } + public void setColors(boolean isColored) { this.colored = isColored; if ((isColored) && (firstColoring)) { @@ -330,21 +328,26 @@ public class WindStreamletsRaceboardOverlay extends MovingCanvasOverlay implemen } this.streamletLegend.setVisible(isColored); if (swarm != null) { - swarm.setColors(isColored);} + swarm.setColors(isColored); + } } + @Override public void removeFromMap() { this.setVisible(false); } + @Override protected void drawCenterChanged() { } + public void onBoundsChanged(boolean zoomChanged) { if (swarm != null) { int swarmPause = (zoomChanged ? 5 : 1); swarm.onBoundsChanged(zoomChanged, swarmPause); } } + @Override public void onColorMappingChanged() { drawLegend(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 470ce17c649..1be0391c3ee 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -4,11 +4,11 @@ import java.util.HashSet; import java.util.Set; /** - * This class maps a given range of values to a full color spectrum. The color spectrum could also be a grey scale. - * Therefore it needs the max and the min value to be mapped. It uses a {@link ValueRangeFlexibleBoundaries} to get those. The + * Maps a given range of values to a full color spectrum. The color spectrum could also be a grey scale. Therefore it + * needs the max and the min value to be mapped. It uses a {@link ValueRangeFlexibleBoundaries} to get those. The * ColorMapper has listeners that will be notified if the colormapping has been changed. * - * @author D073259 + * @author D073259 (Alessandro Stoltenberg) * */ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener { @@ -26,33 +26,42 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener this.isGrey = isGrey; colorMapperChangedListeners = new HashSet<>(); } + public void setGrey(boolean isGrey) { this.isGrey = isGrey; notifyListeners(); } + public String getColor(double value) { + final String result; if (isGrey) { - return "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; } else { double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; - return "hsl(" + Math.round(h) + ", 100%, 50%)"; + result = "hsl(" + Math.round(h) + ", 100%, 50%)"; } + return result; } + private void updateMinMax() { minValue = valueRange.getMinLeft(); maxValue = valueRange.getMaxRight(); } + @Override public void onValueRangeBoundariesChanged() { updateMinMax(); notifyListeners(); } + public void addListener(ColorMapperChangedListener listener) { colorMapperChangedListeners.add(listener); } + public void removeListener(ColorMapperChangedListener listener) { colorMapperChangedListeners.remove(listener); } + public void notifyListeners() { for (ColorMapperChangedListener listener : colorMapperChangedListeners) { listener.onColorMappingChanged(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 81c6053320a..3ed92002c45 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -285,8 +285,7 @@ public class Swarm implements TimeListener { particles[idx] = this.createParticle(); } } - valueRange.checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(minSpeed); - valueRange.checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(maxSpeed); + valueRange.setMinMax(minSpeed, maxSpeed); drawSwarm(); return true; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java index 91f2355485d..37c07089915 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java @@ -4,20 +4,45 @@ import java.util.HashSet; import java.util.Set; /** - * This class defines if a given extremal value is within boundaries that are flexible by a given halfBoundaryWidth. The halfBoundaryWidth is - * defined by a percentage of the difference between max and min of a value range. It needs four types of boundaries: - * a) minLeft - * b) maxLeft - * c) minRight - * d) maxRight - * (a)<--minValue->(b)..........(c)<--maxValue->(d) - * If an extremal value is not within the left or the right boundaries the boundaries should be adjusted in a way that the value will fit in the - * one or the other. Also there should be the possibility to add listeners that will notify on a boundary change. + * Manages a number range that contains a minimum and a maximum value. Those minimum and maximum values can be updated. + * If at least one of the two new values is outside of the range, the range is adjusted to ensure it again contains both + * values. The range will also shrink if the new minimum/maximum values are too far away from the range boundaries. This + * compares to a "Schmitt Trigger" for each end of the range, such that for the minimum and the maximum value there is + * each a value range at the respective end of the overall range, and when the minimum/maximum value is outside of its + * range the overall range will be adjusted. + *

* - * A ValueRangeFlexibleBoundaries needs an initialMin, a initialMax and a percentage that indicates the width of the value range - * surrounding initialMin and Max. + * When the range is initialized or updated, the ranges for the minimum and the maximum value at each end of the overall + * range are determined symmetrically around the minimum/maximum value, with a given {@link #percentage} of the absolute + * difference between the minimum and maximum value as leeway either way. This percentage is provided to this class's + * constructor. For example, if the overall range is -5..5, its length is 10. If a 10% (0.1) leeway is configured, this + * means that 10% of the length of 10 which equals 1 is provided around each extremal value, yielding a range from + * -6..-4 around the minimum value -5, and a range from 4..6 around the maximum value 5. + *

* - * @author D073259 + * Visually, if we have: + *

+ * + * a) minLeft
+ * b) maxLeft
+ * c) minRight
+ * d) maxRight + *

+ * then the range can be imagined like this: + *

+ * + * (a)<--minValue-->(b)..........(c)<--maxValue-->(d) + *

+ * + * If an extremal value is not within the left or the right boundaries the boundaries will be adjusted as described + * above, and all {@link ValueRangeFlexibleBoundariesChangedListener listeners} that were + * {@link #addListener(ValueRangeFlexibleBoundariesChangedListener) added} will be notified. + *

+ * + * A ValueRangeFlexibleBoundaries needs an initialMin, an initialMax and a percentage that indicates the width of the + * value range surrounding initialMin and Max. + * + * @author D073259 (Alessandro Stoltenberg) * */ public class ValueRangeFlexibleBoundaries { @@ -38,6 +63,7 @@ public class ValueRangeFlexibleBoundaries { max = initialMax; update(); } + private void update() { halfBoundaryWidth = (max - min) * (percentage); minLeft = min - halfBoundaryWidth; @@ -46,44 +72,52 @@ public class ValueRangeFlexibleBoundaries { maxRight = max + halfBoundaryWidth; notifyListeners(); } - public void checkIfValueIsInRightBoundaryRangeAndUpdateIfNecessary(double maxValue) { - if (!isValueInRightRange(maxValue)) { - max = maxValue; - update(); + + /** + * Updates the minimum and maximum value. If {@code minValue} is greater than {@code maxValue}, + * an {@link IllegalArgumentException} will be thrown. If any of the values exceeds its range at + * its respective end of this overall range then the overall range will be adjusted, and the + * listeners will be notified. + */ + public void setMinMax(double minValue, double maxValue) { + if (minValue > maxValue) { + throw new IllegalArgumentException("minValue "+minValue+" is greater than maxValue "+maxValue); } - } - public void checkIfValueIsInLeftBoundaryRangeAndUpdateIfNecessary(double minValue) { - if (!isValueInLeftRange(minValue)) { - min = minValue; + min = minValue; + max = maxValue; + if (!isValueInRightRange(maxValue) || !isValueInLeftRange(minValue)) { update(); } + assert minLeft <= minValue; + assert minValue <= maxLeft; + assert minRight <= maxValue; + assert maxValue <= maxRight; } + private boolean isValueInLeftRange(double value) { - if (value >= minLeft && value <= maxLeft) { - return true; - } else { - return false; - } + return value >= minLeft && value <= maxLeft; } + private boolean isValueInRightRange(double value) { - if (value >= minRight && value <= maxRight) { - return true; - } else { - return false; - } + return value >= minRight && value <= maxRight; } + public double getMinLeft() { return minLeft; } + public double getMaxRight() { return maxRight; } + public void addListener(ValueRangeFlexibleBoundariesChangedListener listener) { valueRangeChangedListeners.add(listener); } + public void removeListener(ValueRangeFlexibleBoundariesChangedListener listener) { valueRangeChangedListeners.remove(listener); } + public void notifyListeners() { for (ValueRangeFlexibleBoundariesChangedListener listener : valueRangeChangedListeners) { listener.onValueRangeBoundariesChanged(); From ae31d5ead4422b4ced153a4c716776aec7a8c1a9 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 16 Aug 2018 19:07:25 +0200 Subject: [PATCH 14/32] formatting and removal of obsolete comments Change-Id: I332654666ca85e4fec8569d4e326d74566992f2f --- .../gwt/ui/simulator/streamlets/Swarm.java | 20 +++++++++++++++---- .../WindInfoForRaceVectorField.java | 3 --- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 3ed92002c45..615f17acc75 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -81,6 +81,7 @@ public class Swarm implements TimeListener { valueRange = new ValueRangeFlexibleBoundaries(0.0, 120.0, /*percentage*/ 0.15); colorMapper = new ColorMapper(valueRange, !colored); } + public void start(final int animationIntervalMillis) { fullcanvas.setCanvasSettings(); // if map is not yet loaded, wait for it @@ -96,6 +97,7 @@ public class Swarm implements TimeListener { }); } } + private void startWithMap(int animationIntervalMillis) { projection = new Mercator(fullcanvas, map); projection.calibrate(); @@ -104,6 +106,7 @@ public class Swarm implements TimeListener { swarmContinue = true; startLoop(animationIntervalMillis); } + public void stop() { swarmContinue = false; } @@ -137,6 +140,7 @@ public class Swarm implements TimeListener { } return particle; } + private LatLng getRandomPosition() { final LatLng result; double rndY = Math.random(); @@ -146,6 +150,7 @@ public class Swarm implements TimeListener { result = LatLng.newInstance(latDeg, lngDeg); return result; } + private Particle[] createParticles() { Particle[] newParticles = new Particle[nParticles]; for (int idx = 0; idx < newParticles.length; idx++) { @@ -153,6 +158,7 @@ public class Swarm implements TimeListener { } return newParticles; } + public void onBoundsChanged(boolean zoomChanged, int swarmPause) { this.zoomChanged |= zoomChanged; if (this.zoomChanged) { @@ -160,6 +166,7 @@ public class Swarm implements TimeListener { } this.swarmPause = swarmPause; } + private void updateBounds() { LatLngBounds fieldBounds = this.field.getFieldCorners(); final LatLngBounds mapBounds = map.getBounds(); @@ -172,10 +179,8 @@ public class Swarm implements TimeListener { this.nParticles = (int)Math.round(Math.sqrt(boundsWidthpx * boundsHeightpx) * this.field.getParticleFactor() * this.parameters.swarmScale); cosineOfAverageLatitude = Math.cos((visibleBoundsOfField.getSouthWest().getLatitude()/180.*Math.PI+ visibleBoundsOfField.getNorthEast().getLatitude()/180.*Math.PI)/2); - }; - //native void log(String message) /*-{ - // console.log( message ); - //}-*/; + } + private void startLoop(final int animationIntervalMillis) { // Create animation-loop based on timer timeout loopTimer = new com.google.gwt.user.client.Timer() { @@ -213,6 +218,7 @@ public class Swarm implements TimeListener { }; loopTimer.schedule(animationIntervalMillis); } + private void drawSwarm() { Context2d ctxt = canvas.getContext2d(); ctxt.setGlobalAlpha(0.08); @@ -236,13 +242,16 @@ public class Swarm implements TimeListener { ctxt.stroke(); } } + public void setColors(boolean isColored) { this.colored = isColored; colorMapper.setGrey(!isColored); } + public boolean isColored() { return colored; } + /** * Moves each particle by its vector {@link Particle#v} multiplied by the speed which is 0.01 times the * {@link VectorField#getMotionScale(int)} at the map's current zoom level. @@ -289,12 +298,15 @@ public class Swarm implements TimeListener { drawSwarm(); return true; } + public ValueRangeFlexibleBoundaries getValueRange() { return valueRange; } + public ColorMapper getColorMapper() { return colorMapper; } + @Override public void timeChanged(Date newTime, Date oldTime) { timePoint = newTime; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java index 10969bf6e18..268b5c99a5f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/WindInfoForRaceVectorField.java @@ -102,9 +102,6 @@ public class WindInfoForRaceVectorField implements VectorField, AverageLatitudeP double knotSpeedSumScaledByConfidence = 0; final BearingWithConfidenceCluster bearingCluster = new BearingWithConfidenceCluster<>(weigher); for (final Entry windSourceAndWindTrack : windInfoForRace.windTrackInfoByWindSource.entrySet()) { - /*if ((windSourceAndWindTrack.getKey().name().equals("RACECOMMITTEE"))||(windSourceAndWindTrack.getKey().name().equals("COURSE_BASED"))) { - continue; - }*/ if (!Util.contains(windInfoForRace.windSourcesToExclude, windSourceAndWindTrack.getKey())) { WindDTO timewiseClosestFixForWindSource = getTimewiseClosestFix(windSourceAndWindTrack.getValue(), at); if (timewiseClosestFixForWindSource != null) { From d533b5d7d2274a4d402fe2e1739e15c696b35e3b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 16 Aug 2018 19:27:37 +0200 Subject: [PATCH 15/32] avoid now illegal range updates with min>max; remember vector length to avoid redundant calculations Change-Id: Ie598bdfced20def20427d6e838c5369f00e61863 --- .../gwt/ui/simulator/streamlets/Swarm.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 615f17acc75..3ffb60ceacd 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -280,11 +280,12 @@ public class Swarm implements TimeListener { particle.stepsToLive--; if ((particle.stepsToLive > 0) && (this.field.inBounds(particle.currentPosition))) { particle.v = field.getVector(particle.currentPosition, timePoint); - if (particle.v.length() > maxSpeed) { - maxSpeed = particle.v.length(); + final double length = particle.v.length(); + if (length > maxSpeed) { + maxSpeed = length; } - if (particle.v.length() < minSpeed) { - minSpeed = particle.v.length(); + if (length < minSpeed) { + minSpeed = length; } } else { particle.v = null; @@ -294,8 +295,10 @@ public class Swarm implements TimeListener { particles[idx] = this.createParticle(); } } - valueRange.setMinMax(minSpeed, maxSpeed); - drawSwarm(); + if (minSpeed <= maxSpeed) { + valueRange.setMinMax(minSpeed, maxSpeed); + drawSwarm(); + } return true; } From 7762287e05cfcebda6bceaa43bfcee4a0f25d5c8 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 10:43:06 +0200 Subject: [PATCH 16/32] bug4134_2: In swarm.java emphasized that wind speed is in knots. Changed the intial values of the swarm ValueRangeWithFlexibleBoundaries to 0 and 60 (knots). --- .../gwt/ui/simulator/streamlets/Swarm.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 3ffb60ceacd..ac2b37584f1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -78,7 +78,7 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); - valueRange = new ValueRangeFlexibleBoundaries(0.0, 120.0, /*percentage*/ 0.15); + valueRange = new ValueRangeFlexibleBoundaries(/*wind speed in knots*/ 0.0,/*wind speed in knots*/ 60.0, /*percentage*/ 0.15); colorMapper = new ColorMapper(valueRange, !colored); } @@ -257,8 +257,8 @@ public class Swarm implements TimeListener { * {@link VectorField#getMotionScale(int)} at the map's current zoom level. */ private boolean execute(Vector diffPx) { - double minSpeed = 120.0; - double maxSpeed = 0.0; + double minSpeedInKnots = 120.0; + double maxSpeedInKnots = 0.0; double speed = field.getMotionScale(map.getZoom()); for (int idx = 0; idx < particles.length; idx++) { Particle particle = particles[idx]; @@ -281,11 +281,11 @@ public class Swarm implements TimeListener { if ((particle.stepsToLive > 0) && (this.field.inBounds(particle.currentPosition))) { particle.v = field.getVector(particle.currentPosition, timePoint); final double length = particle.v.length(); - if (length > maxSpeed) { - maxSpeed = length; + if (length > maxSpeedInKnots) { + maxSpeedInKnots = length; } - if (length < minSpeed) { - minSpeed = length; + if (length < minSpeedInKnots) { + minSpeedInKnots = length; } } else { particle.v = null; @@ -295,8 +295,8 @@ public class Swarm implements TimeListener { particles[idx] = this.createParticle(); } } - if (minSpeed <= maxSpeed) { - valueRange.setMinMax(minSpeed, maxSpeed); + if (minSpeedInKnots <= maxSpeedInKnots) { + valueRange.setMinMax(minSpeedInKnots, maxSpeedInKnots); drawSwarm(); } return true; From 16ccc3002c059531572436b92afb7b19ea1efcdc Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 11:24:50 +0200 Subject: [PATCH 17/32] bug4134_2: Added documentation to ColorMapper.getColor(), also the method throws an illegal argument exception if called with a value outside the corresponding valuerange. --- .../gwt/ui/simulator/streamlets/ColorMapper.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 1be0391c3ee..cb1acdb2b5c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -31,8 +31,16 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener this.isGrey = isGrey; notifyListeners(); } - + + /** + * Returns a string with a rgba representation of a the value mapped to the color spectrum in case {@link #isGrey} + * = true or the hsl representation of the color in case {@link #isGrey} = false . If called with a + * value outside the {@link #valueRange} an {@link IllegalArgumentException} will be thrown. + */ public String getColor(double value) { + if (value < minValue || value > maxValue) { + throw new IllegalArgumentException("The value "+value+" is out of the value range "+valueRange); + } final String result; if (isGrey) { result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; From 6b240dd215368c023c2d7ca76f254c35f7a8b6ec Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 12:30:32 +0200 Subject: [PATCH 18/32] bug4134_2: Added more testing to ColorMapperTest --- .../sailing/gwt/ui/test/ColorMapperTest.java | 87 +++++++++++++++---- 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 1720fb29c7d..2953cfe32e8 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -1,24 +1,81 @@ package com.sap.sailing.gwt.ui.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.*; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.Before; import org.junit.Test; + import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapper; +import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapperChangedListener; import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; public class ColorMapperTest { - ValueRangeFlexibleBoundaries valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.0); - ColorMapper colorMapperTestColored = new ColorMapper(valueRange, false); - ColorMapper colorMapperTestGrey = new ColorMapper(valueRange, true); - double testValue1 = -5.0; - String expectedResult1colored = "hsl(240, 100%, 50%)"; - String expectedResult1grey = "rgba(255,255,255,0.0)"; - double testValue2 = 5.0; - String expectedResult2colored = "hsl(0, 100%, 50%)"; - String expectedResult2grey = "rgba(255,255,255,1.0)"; + ColorMapper colorMapper; + ColorMapperChangedListener listener; + ValueRangeFlexibleBoundaries valueRange; + Set valueSet; + Set colorSet; + + @Before + public void setUp() { + valueRange = new ValueRangeFlexibleBoundaries(-5.0, 5.0, 0.0); + colorMapper = new ColorMapper(valueRange, false); + listener = mock(ColorMapperChangedListener.class); + colorMapper.addListener(listener); + valueSet = new HashSet<>(); + updateValueSet(valueSet); + colorSet = new HashSet<>(); + updateColorSet(colorSet); + } + + public void updateColorSet(Set colorSet) { + colorSet.clear(); + for (int i : valueSet) { + double h = (1 - (i - valueRange.getMinLeft()) / (valueRange.getMaxRight() - valueRange.getMinLeft())) * 240; + colorSet.add("hsl(" + Math.round(h) + ", 100%, 50%)"); + } + } + public void updateValueSet(Set valueSet) { + valueSet.clear(); + for (int i = (int) Math.round(valueRange.getMinLeft()); i <= (int) Math.round(valueRange.getMaxRight()); i++) { + valueSet.add(i); + } + } + @Test - public void testGetColor() { - assertEquals(expectedResult1colored, colorMapperTestColored.getColor(testValue1)); - assertEquals(expectedResult1grey, colorMapperTestGrey.getColor(testValue1)); - assertEquals(expectedResult2colored, colorMapperTestColored.getColor(testValue2)); - assertEquals(expectedResult2grey, colorMapperTestGrey.getColor(testValue2)); + public void testExceptionForValueOutOfBoundaries() { + try { + colorMapper.getColor(-10.0); + fail("Expected illegal argument exception"); + } catch (IllegalArgumentException e) { + // expected + } + } + + @Test + public void testGetColorColored() { + // first set the color and verify listener will be notified + colorMapper.setGrey(false); + verify(listener, times(1)).onColorMappingChanged(); + // Check for each value in valueSet that getColor() returns a color within the colorSet. + for (int i : valueSet) { + assertTrue(colorSet.contains(colorMapper.getColor(i))); + } + } + @Test + public void changeValueRangeAndTestGetColor() { + valueRange.setMinMax(12.0, 26.0); + //verify Listener + verify(listener, times(1)).onColorMappingChanged(); + updateValueSet(valueSet); + updateColorSet(colorSet); + //check if new values are within the colorSet + for (int i : valueSet) { + assertTrue(colorSet.contains(colorMapper.getColor(i))); + } } } From f001ad7296bdc4290856ed19c6513318c5d6c660 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 12:31:12 +0200 Subject: [PATCH 19/32] bug4134_2: Formatting --- .../src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 2953cfe32e8..3f93850a15c 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -1,4 +1,5 @@ package com.sap.sailing.gwt.ui.test; + import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; @@ -39,6 +40,7 @@ public class ColorMapperTest { colorSet.add("hsl(" + Math.round(h) + ", 100%, 50%)"); } } + public void updateValueSet(Set valueSet) { valueSet.clear(); for (int i = (int) Math.round(valueRange.getMinLeft()); i <= (int) Math.round(valueRange.getMaxRight()); i++) { @@ -66,14 +68,15 @@ public class ColorMapperTest { assertTrue(colorSet.contains(colorMapper.getColor(i))); } } + @Test public void changeValueRangeAndTestGetColor() { valueRange.setMinMax(12.0, 26.0); - //verify Listener + // verify Listener verify(listener, times(1)).onColorMappingChanged(); updateValueSet(valueSet); updateColorSet(colorSet); - //check if new values are within the colorSet + // check if new values are within the colorSet for (int i : valueSet) { assertTrue(colorSet.contains(colorMapper.getColor(i))); } From 8accbac5d4056fc19e1c8687fcab153239728321 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 13:34:23 +0200 Subject: [PATCH 20/32] bug4134_2: Removed unnecessary complicated creation of colorSet in ColorMapperTest --- .../sailing/gwt/ui/test/ColorMapperTest.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 3f93850a15c..05af9421b02 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -30,15 +30,7 @@ public class ColorMapperTest { valueSet = new HashSet<>(); updateValueSet(valueSet); colorSet = new HashSet<>(); - updateColorSet(colorSet); - } - - public void updateColorSet(Set colorSet) { - colorSet.clear(); - for (int i : valueSet) { - double h = (1 - (i - valueRange.getMinLeft()) / (valueRange.getMaxRight() - valueRange.getMinLeft())) * 240; - colorSet.add("hsl(" + Math.round(h) + ", 100%, 50%)"); - } + fillColorSet(); } public void updateValueSet(Set valueSet) { @@ -48,6 +40,12 @@ public class ColorMapperTest { } } + public void fillColorSet() { + for (int i = 0; i <= 240; i++) { + colorSet.add("hsl(" + i + ", 100%, 50%)"); + } + } + @Test public void testExceptionForValueOutOfBoundaries() { try { @@ -75,7 +73,6 @@ public class ColorMapperTest { // verify Listener verify(listener, times(1)).onColorMappingChanged(); updateValueSet(valueSet); - updateColorSet(colorSet); // check if new values are within the colorSet for (int i : valueSet) { assertTrue(colorSet.contains(colorMapper.getColor(i))); From 14a46aba4db280885ed00b6b3f111fe0eae7a624 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 14:31:27 +0200 Subject: [PATCH 21/32] bug4134_2: Improved ColorMapperTest --- .../src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 05af9421b02..4495900114d 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -45,7 +45,7 @@ public class ColorMapperTest { colorSet.add("hsl(" + i + ", 100%, 50%)"); } } - + @Test public void testExceptionForValueOutOfBoundaries() { try { From fb15a05c9941b51c86d00224a3282118955f7f39 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 14:36:40 +0200 Subject: [PATCH 22/32] bug4134_2: Renamed function in ColorMapperTest. --- .../src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 4495900114d..33daf27cf9e 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -68,7 +68,7 @@ public class ColorMapperTest { } @Test - public void changeValueRangeAndTestGetColor() { + public void changeValueRangeAndTestGetColorColored() { valueRange.setMinMax(12.0, 26.0); // verify Listener verify(listener, times(1)).onColorMappingChanged(); From cb8ba382bbc6e95783ba709a62461e9dfcda4b15 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Fri, 17 Aug 2018 14:39:38 +0200 Subject: [PATCH 23/32] bug4134_2: More specific on ColorMapper.getColor() illegal argument exception. --- .../sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index cb1acdb2b5c..a1bdd263d44 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -39,7 +39,7 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener */ public String getColor(double value) { if (value < minValue || value > maxValue) { - throw new IllegalArgumentException("The value "+value+" is out of the value range "+valueRange); + throw new IllegalArgumentException("The value "+value+" is out of the value range: "+valueRange.getMinLeft()+" - "+valueRange.getMaxRight()); } final String result; if (isGrey) { From cfc3c7ff91704bc6275885d34844c9803b71db88 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 11:58:51 +0200 Subject: [PATCH 24/32] bug4134_2: SailingAnalyticsNotes.html --- .../places/whatsnew/resources/SailingAnalyticsNotes.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html index aa3858de21b..0111b5dde64 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html @@ -4,6 +4,10 @@

What's New - SAP Sailing Analytics

+
August 2018
+
    +
  • The windstreamlets are now colored according to the maximum and minimum windspeed in the windfield. +
    July 2018
    • The Maneuver Table now uses the same color coding for competitors as the leaderboard to help From 3565ab0510e25e1fcf4b186cd749fc2d3555b06e Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 17:14:24 +0200 Subject: [PATCH 25/32] bug4134_2: Added try catch block to ColorMapper --- .../ui/simulator/streamlets/ColorMapper.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index a1bdd263d44..05fcf948197 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -38,15 +38,21 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener * value outside the {@link #valueRange} an {@link IllegalArgumentException} will be thrown. */ public String getColor(double value) { - if (value < minValue || value > maxValue) { - throw new IllegalArgumentException("The value "+value+" is out of the value range: "+valueRange.getMinLeft()+" - "+valueRange.getMaxRight()); - } final String result; - if (isGrey) { - result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; - } else { - double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; - result = "hsl(" + Math.round(h) + ", 100%, 50%)"; + try { + if (value < minValue || value > maxValue) { + throw new IllegalArgumentException("The value " + value + " is out of the value range: " + + valueRange.getMinLeft() + " - " + valueRange.getMaxRight()); + } + } catch (IllegalArgumentException e) { + + } finally { + if (isGrey) { + result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + } else { + double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; + result = "hsl(" + Math.round(h) + ", 100%, 50%)"; + } } return result; } From e4eefd55cdc56f703a93e4298daefe06ce20b1b9 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 18:45:46 +0200 Subject: [PATCH 26/32] bug4134_2: Swarm now updates also minMax for new particles. ColorMapper.getColor() returns null if value is outside valueRange. --- .../ui/simulator/streamlets/ColorMapper.java | 23 +++++++------------ .../gwt/ui/simulator/streamlets/Swarm.java | 20 ++++++++-------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 05fcf948197..794c4055187 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -35,24 +35,17 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener /** * Returns a string with a rgba representation of a the value mapped to the color spectrum in case {@link #isGrey} * = true or the hsl representation of the color in case {@link #isGrey} = false . If called with a - * value outside the {@link #valueRange} an {@link IllegalArgumentException} will be thrown. + * value outside the {@link #valueRange} the return will be null. */ public String getColor(double value) { final String result; - try { - if (value < minValue || value > maxValue) { - throw new IllegalArgumentException("The value " + value + " is out of the value range: " - + valueRange.getMinLeft() + " - " + valueRange.getMaxRight()); - } - } catch (IllegalArgumentException e) { - - } finally { - if (isGrey) { - result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; - } else { - double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; - result = "hsl(" + Math.round(h) + ", 100%, 50%)"; - } + if (value < minValue || value > maxValue) { + result = null; + } else if (isGrey) { + result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + } else { + double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; + result = "hsl(" + Math.round(h) + ", 100%, 50%)"; } return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index ac2b37584f1..337e309efc1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -78,7 +78,7 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); - valueRange = new ValueRangeFlexibleBoundaries(/*wind speed in knots*/ 0.0,/*wind speed in knots*/ 60.0, /*percentage*/ 0.15); + valueRange = new ValueRangeFlexibleBoundaries(/*wind speed in knots*/ 0.0,/*wind speed in knots*/ 60.0, /*percentage*/ 0.2); colorMapper = new ColorMapper(valueRange, !colored); } @@ -280,13 +280,6 @@ public class Swarm implements TimeListener { particle.stepsToLive--; if ((particle.stepsToLive > 0) && (this.field.inBounds(particle.currentPosition))) { particle.v = field.getVector(particle.currentPosition, timePoint); - final double length = particle.v.length(); - if (length > maxSpeedInKnots) { - maxSpeedInKnots = length; - } - if (length < minSpeedInKnots) { - minSpeedInKnots = length; - } } else { particle.v = null; } @@ -294,11 +287,20 @@ public class Swarm implements TimeListener { // particle timed out (age became 0) or was never created (e.g., weight too low); try to create a new one particles[idx] = this.createParticle(); } + if (particles[idx] != null && particles[idx].v != null) { + final double length = particles[idx].v.length(); + if (length > maxSpeedInKnots) { + maxSpeedInKnots = length; + } + if (length < minSpeedInKnots) { + minSpeedInKnots = length; + } + } } if (minSpeedInKnots <= maxSpeedInKnots) { valueRange.setMinMax(minSpeedInKnots, maxSpeedInKnots); - drawSwarm(); } + drawSwarm(); return true; } From 9c43f84ca3a9bc2de5ff7637d47770b0b42ca4b1 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 18:55:39 +0200 Subject: [PATCH 27/32] bug4134_2: Changed the threeshold value for Swarms ValueRange to 15%. --- .../java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 337e309efc1..1a7ce6d46c7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -78,7 +78,7 @@ public class Swarm implements TimeListener { timePoint = timer.getTime(); cosineOfAverageLatitude = 1.0; // default to equator diffPx = new Vector(0, 0); - valueRange = new ValueRangeFlexibleBoundaries(/*wind speed in knots*/ 0.0,/*wind speed in knots*/ 60.0, /*percentage*/ 0.2); + valueRange = new ValueRangeFlexibleBoundaries(/*wind speed in knots*/ 0.0,/*wind speed in knots*/ 60.0, /*percentage*/ 0.15); colorMapper = new ColorMapper(valueRange, !colored); } From 232fd836ab3dd8a3237283f5b2fa6b243eb47bb5 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 19:02:43 +0200 Subject: [PATCH 28/32] bug4134_2: ColorMapperTest tests null return for ColorMapper.getColor(). --- .../com/sap/sailing/gwt/ui/test/ColorMapperTest.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 33daf27cf9e..2754c7f90ca 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -1,7 +1,6 @@ package com.sap.sailing.gwt.ui.test; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.Mockito.*; import java.util.HashSet; @@ -47,13 +46,8 @@ public class ColorMapperTest { } @Test - public void testExceptionForValueOutOfBoundaries() { - try { - colorMapper.getColor(-10.0); - fail("Expected illegal argument exception"); - } catch (IllegalArgumentException e) { - // expected - } + public void testNullForValueOutOfBoundaries() { + assertTrue(colorMapper.getColor(-10.0) == null); } @Test From b7f7c934d9d971adf3db42eb85efd9e2a9109b99 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Mon, 20 Aug 2018 19:12:26 +0200 Subject: [PATCH 29/32] bug4134_2: added release notes. --- .../places/whatsnew/resources/SailingAnalyticsNotes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html index 0111b5dde64..2bf6bd29e38 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html @@ -6,7 +6,7 @@
      August 2018
        -
      • The windstreamlets are now colored according to the maximum and minimum windspeed in the windfield. +
      • The windstreamlets are now colored dynamically according to the wind fields maximum and minimum wind speed.
      • July 2018
          From dfe8c36dacab9124c6b8f00ed9eb7f430729c031 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Tue, 21 Aug 2018 11:13:07 +0200 Subject: [PATCH 30/32] bug4134_2: ColorMapper.getColor() returns minimum or maximum color if value is outside range. --- .../ui/simulator/streamlets/ColorMapper.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java index 794c4055187..af8f91002c8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java @@ -35,17 +35,28 @@ public class ColorMapper implements ValueRangeFlexibleBoundariesChangedListener /** * Returns a string with a rgba representation of a the value mapped to the color spectrum in case {@link #isGrey} * = true or the hsl representation of the color in case {@link #isGrey} = false . If called with a - * value outside the {@link #valueRange} the return will be null. + * value outside the {@link #valueRange} the return will be the minimum or the maximum of the spectrum, depending if + * the input value is smaller or greater then the {@link #minValue} or {@link #maxValue} of the {@link #valueRange}. */ public String getColor(double value) { final String result; - if (value < minValue || value > maxValue) { - result = null; - } else if (isGrey) { - result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + if (isGrey) { + if (value < minValue) { + result = "rgba(255,255,255,0.0)"; + } else if (value > maxValue) { + result = "rgba(255,255,255,1.0)"; + } else { + result = "rgba(255,255,255," + Math.min(1.0, (value - minValue) / (maxValue - minValue)) + ")"; + } } else { - double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; - result = "hsl(" + Math.round(h) + ", 100%, 50%)"; + if (value < minValue) { + result = "hsl(0, 100%, 50%)"; + } else if (value > maxValue) { + result = "hsl(240, 100%, 50%)"; + } else { + double h = (1 - (value - minValue) / (maxValue - minValue)) * 240; + result = "hsl(" + Math.round(h) + ", 100%, 50%)"; + } } return result; } From 1f5c5d1c53606633f2566dd82257c9cee63c485c Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Tue, 21 Aug 2018 11:23:37 +0200 Subject: [PATCH 31/32] bug4134_2: ColorMapperTest tests for value out of range. --- .../src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java index 2754c7f90ca..975b880cefe 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java @@ -14,6 +14,7 @@ import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapperChangedListener; import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; public class ColorMapperTest { + private static final double EPSILON = 0.00000001; ColorMapper colorMapper; ColorMapperChangedListener listener; ValueRangeFlexibleBoundaries valueRange; @@ -30,6 +31,7 @@ public class ColorMapperTest { updateValueSet(valueSet); colorSet = new HashSet<>(); fillColorSet(); + } public void updateValueSet(Set valueSet) { @@ -46,8 +48,9 @@ public class ColorMapperTest { } @Test - public void testNullForValueOutOfBoundaries() { - assertTrue(colorMapper.getColor(-10.0) == null); + public void testForValueOutOfBoundaries() { + assertTrue(colorMapper.getColor(valueRange.getMinLeft() - EPSILON) == "hsl(0, 100%, 50%)"); + assertTrue(colorMapper.getColor(valueRange.getMaxRight() + EPSILON) == "hsl(240, 100%, 50%)"); } @Test From fa49836b9582fd9213ecd16dedcc1d1b6026b9c8 Mon Sep 17 00:00:00 2001 From: Alessandro Stoltenberg Date: Tue, 21 Aug 2018 17:19:04 +0200 Subject: [PATCH 32/32] bug4134_2: Moved ColorMapper and ValueRangeFlexibleBoundaries to com.sap.sse.common and the tests to com.sap.sse.common.test --- .../ui/shared/racemap/WindStreamletsRaceboardOverlay.java | 2 +- .../sap/sailing/gwt/ui/simulator/streamlets/Swarm.java | 2 ++ .../src/com/sap/sse/common}/test/ColorMapperTest.java | 8 ++++---- .../common}/test/ValueRangeFlexibleBoundariesTest.java | 6 +++--- .../src/com/sap/sse/common}/ColorMapper.java | 2 +- .../com/sap/sse/common}/ColorMapperChangedListener.java | 2 +- .../com/sap/sse/common}/ValueRangeFlexibleBoundaries.java | 2 +- .../ValueRangeFlexibleBoundariesChangedListener.java | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-) rename java/{com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui => com.sap.sse.common.test/src/com/sap/sse/common}/test/ColorMapperTest.java (90%) rename java/{com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui => com.sap.sse.common.test/src/com/sap/sse/common}/test/ValueRangeFlexibleBoundariesTest.java (94%) rename java/{com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets => com.sap.sse.common/src/com/sap/sse/common}/ColorMapper.java (98%) rename java/{com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets => com.sap.sse.common/src/com/sap/sse/common}/ColorMapperChangedListener.java (61%) rename java/{com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets => com.sap.sse.common/src/com/sap/sse/common}/ValueRangeFlexibleBoundaries.java (98%) rename java/{com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets => com.sap.sse.common/src/com/sap/sse/common}/ValueRangeFlexibleBoundariesChangedListener.java (67%) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java index c27e1105c60..89ccb55a5ea 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/racemap/WindStreamletsRaceboardOverlay.java @@ -28,10 +28,10 @@ import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO; import com.sap.sailing.gwt.ui.simulator.StreamletParameters; import com.sap.sailing.gwt.ui.simulator.racemap.MovingCanvasOverlay; -import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapperChangedListener; import com.sap.sailing.gwt.ui.simulator.streamlets.Swarm; import com.sap.sailing.gwt.ui.simulator.streamlets.VectorField; import com.sap.sailing.gwt.ui.simulator.streamlets.WindInfoForRaceVectorField; +import com.sap.sse.common.ColorMapperChangedListener; import com.sap.sse.common.Util; import com.sap.sse.gwt.client.Notification; import com.sap.sse.gwt.client.Notification.NotificationType; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java index 1a7ce6d46c7..fb031139dcd 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/Swarm.java @@ -15,6 +15,8 @@ import com.sap.sailing.gwt.ui.client.shared.racemap.BoundsUtil; import com.sap.sailing.gwt.ui.client.shared.racemap.CoordinateSystem; import com.sap.sailing.gwt.ui.simulator.StreamletParameters; import com.sap.sailing.gwt.ui.simulator.racemap.FullCanvasOverlay; +import com.sap.sse.common.ColorMapper; +import com.sap.sse.common.ValueRangeFlexibleBoundaries; import com.sap.sse.gwt.client.player.TimeListener; public class Swarm implements TimeListener { diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/ColorMapperTest.java similarity index 90% rename from java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java rename to java/com.sap.sse.common.test/src/com/sap/sse/common/test/ColorMapperTest.java index 975b880cefe..57b32c76382 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ColorMapperTest.java +++ b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/ColorMapperTest.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.test; +package com.sap.sse.common.test; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; @@ -9,9 +9,9 @@ import java.util.Set; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapper; -import com.sap.sailing.gwt.ui.simulator.streamlets.ColorMapperChangedListener; -import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; +import com.sap.sse.common.ColorMapper; +import com.sap.sse.common.ColorMapperChangedListener; +import com.sap.sse.common.ValueRangeFlexibleBoundaries; public class ColorMapperTest { private static final double EPSILON = 0.00000001; diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/ValueRangeFlexibleBoundariesTest.java similarity index 94% rename from java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java rename to java/com.sap.sse.common.test/src/com/sap/sse/common/test/ValueRangeFlexibleBoundariesTest.java index 1b545cc473e..f68eff1d443 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/ValueRangeFlexibleBoundariesTest.java +++ b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/ValueRangeFlexibleBoundariesTest.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.test; +package com.sap.sse.common.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; @@ -6,8 +6,8 @@ import static org.mockito.Mockito.*; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundaries; -import com.sap.sailing.gwt.ui.simulator.streamlets.ValueRangeFlexibleBoundariesChangedListener; +import com.sap.sse.common.ValueRangeFlexibleBoundaries; +import com.sap.sse.common.ValueRangeFlexibleBoundariesChangedListener; public class ValueRangeFlexibleBoundariesTest { private static final double EPSILON = 0.00000001; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java b/java/com.sap.sse.common/src/com/sap/sse/common/ColorMapper.java similarity index 98% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java rename to java/com.sap.sse.common/src/com/sap/sse/common/ColorMapper.java index af8f91002c8..d6642be8fdc 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapper.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/ColorMapper.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.simulator.streamlets; +package com.sap.sse.common; import java.util.HashSet; import java.util.Set; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java b/java/com.sap.sse.common/src/com/sap/sse/common/ColorMapperChangedListener.java similarity index 61% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java rename to java/com.sap.sse.common/src/com/sap/sse/common/ColorMapperChangedListener.java index f5cb90277a2..d0c25c11113 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ColorMapperChangedListener.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/ColorMapperChangedListener.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.simulator.streamlets; +package com.sap.sse.common; public interface ColorMapperChangedListener { void onColorMappingChanged(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java b/java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundaries.java similarity index 98% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java rename to java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundaries.java index 37c07089915..4d42bac3c13 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundaries.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundaries.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.simulator.streamlets; +package com.sap.sse.common; import java.util.HashSet; import java.util.Set; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java b/java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundariesChangedListener.java similarity index 67% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java rename to java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundariesChangedListener.java index ff3f0f45f8b..5581b6b1e7e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/streamlets/ValueRangeFlexibleBoundariesChangedListener.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/ValueRangeFlexibleBoundariesChangedListener.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.simulator.streamlets; +package com.sap.sse.common; public interface ValueRangeFlexibleBoundariesChangedListener { void onValueRangeBoundariesChanged();