Ticket #14343: josm_ticket_1434_gps_heat_map _point_cloud_v1_by_kidelo.patch
File josm_ticket_1434_gps_heat_map _point_cloud_v1_by_kidelo.patch, 26.2 KB (added by , 8 years ago) |
---|
-
src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
27 27 import java.util.Collections; 28 28 import java.util.Date; 29 29 import java.util.List; 30 import java.util.Random; 30 31 31 32 import javax.swing.ImageIcon; 32 33 … … 95 96 private ColorMode computeCacheColored; 96 97 private int computeCacheColorTracksTune; 97 98 private int computeCacheHeatMapDrawColorTableIdx; 99 private boolean computeCacheHeatMapDrawPointMode; 100 private int computeCacheHeatMapDrawGain; 101 private int computeCacheHeatMapDrawLowerLimit; 98 102 99 103 //// Color-related fields 100 104 /** Mode of the line coloring **/ … … 134 138 private boolean heatMapDrawExtraLine; 135 139 // used index for color table (parameter) 136 140 private int heatMapDrawColorTableIdx; 141 // use point or line draw mode 142 private boolean heatMapDrawPointMode; 143 // extra gain > 0 or < 0 attenuation, 0 = default 144 private int heatMapDrawGain; 145 // do not draw elements with value lower than this limit 146 private int heatMapDrawLowerLimit; 137 147 138 148 // normal buffered image and draw object (cached) 139 149 private BufferedImage heatMapImgGray; … … 155 165 private static Color[] heatMapLutColorJosmRed2Blue = createColorFromResource("red2blue"); 156 166 157 167 // user defined heatmap color 158 private Color[] heatMapLutColor = createColorLut( Color.BLACK, Color.WHITE);168 private Color[] heatMapLutColor = createColorLut(0, Color.BLACK, Color.WHITE); 159 169 160 170 private void setupColors() { 161 171 hdopAlpha = Main.pref.getInteger("hdop.color.alpha", -1); … … 277 287 // get heatmap parameters 278 288 heatMapEnabled = Main.pref.getBoolean("draw.rawgps.heatmap.enabled", spec, false); 279 289 heatMapDrawExtraLine = Main.pref.getBoolean("draw.rawgps.heatmap.line-extra", spec, false); 280 heatMapDrawColorTableIdx = Main.pref.getInteger("draw.rawgps.heatmap.colormap", specName(layerName), 0); 290 heatMapDrawColorTableIdx = Main.pref.getInteger("draw.rawgps.heatmap.colormap", spec, 0); 291 heatMapDrawPointMode = Main.pref.getBoolean("draw.rawgps.heatmap.use-points", spec, false); 292 heatMapDrawGain = Main.pref.getInteger("draw.rawgps.heatmap.gain", spec, 0); 293 heatMapDrawLowerLimit = Main.pref.getInteger("draw.rawgps.heatmap.lower-limit", spec, 0); 281 294 295 // shrink to range 296 heatMapDrawGain = Math.min(Math.max(-10, heatMapDrawGain), 10); 297 282 298 neutralColor = getColor(layerName, true); 283 299 velocityScale.setNoDataColor(neutralColor); 284 300 dateScale.setNoDataColor(neutralColor); … … 513 529 // heat mode 514 530 if (ColorMode.HEATMAP == colored) { 515 531 516 // generate and get new user color map 517 heatMapLutColor = selectColorMap(neutralColor != null ? neutralColor : Color.WHITE, heatMapDrawColorTableIdx); 532 // get new user color map and refresh visibility level 533 heatMapLutColor = createColorLut(heatMapDrawLowerLimit, 534 selectColorMap(neutralColor != null ? neutralColor : Color.WHITE, heatMapDrawColorTableIdx)); 518 535 519 536 // force redraw of image 520 537 heatMapMapViewState = null; … … 794 811 } 795 812 796 813 /** 797 * Creates a linear distributed colormap by linear blending between colors 814 * Creates a distributed colormap by linear blending between colors 815 * @param lowerLimit lower limit for first visible color 798 816 * @param colors 1..n colors 799 817 * @return array of Color objects 800 818 */ 801 protected static Color[] createColorLut( Color... colors) {819 protected static Color[] createColorLut(int lowerLimit, Color... colors) { 802 820 803 821 // number of lookup entries 804 822 final int tableSize = 256; … … 824 842 Color c = new Color(pixel[0]); 825 843 826 844 // smooth alpha like sin curve 827 int alpha = (i nt) (Math.sin(i * mapTo90Deg) * 255);845 int alpha = (i > lowerLimit) ? (int) (Math.sin((i-lowerLimit) * mapTo90Deg) * 255) : 0; 828 846 829 847 // alpha with pre-offset, first color -> full transparent 830 alpha = i > 0 ? (10 + alpha) : 0;848 alpha = alpha > 0 ? (20 + alpha) : 0; 831 849 832 850 // shrink to maximum bound 833 851 if (alpha > 255) { … … 915 933 colorList.add(darkerColor(lastColor, 0.950f)); 916 934 } 917 935 918 return createColorLut( colorList.toArray(new Color[ colorList.size() ]));936 return createColorLut(0, colorList.toArray(new Color[ colorList.size() ])); 919 937 } 920 938 921 939 /** … … 927 945 */ 928 946 protected static Color[] selectColorMap(Color userColor, int tableIdx) { 929 947 948 // generate new user color map ( dark, user color, white ) 949 Color[] userColor1 = createColorLut(0, userColor.darker(), userColor, userColor.brighter(), Color.WHITE); 950 951 // generate new user color map ( white -> color ) 952 Color[] userColor2 = createColorLut(0, Color.WHITE, Color.WHITE, userColor); 953 930 954 // generate new user color map 931 Color[] nextUserColor = createColorLut(Color.BLACK, userColor.darker(), 932 userColor, userColor.brighter(), Color.WHITE); 955 Color[] ColorTrafficLights = createColorLut(0, Color.WHITE, Color.GREEN.darker(), Color.YELLOW, Color.RED); 933 956 934 957 // decide what, keep order is sync with setting on GUI 935 958 Color[][] lut = { 936 nextUserColor, 959 userColor1, 960 userColor2, 961 ColorTrafficLights, 937 962 heatMapLutColorJosmInferno, 938 963 heatMapLutColorJosmViridis, 939 964 heatMapLutColorJosmBrown2Green, … … 940 965 heatMapLutColorJosmRed2Blue 941 966 }; 942 967 968 // default case 969 Color[] nextUserColor = userColor1; 970 943 971 // select by index 944 972 if (tableIdx < lut.length) { 945 973 nextUserColor = lut[ tableIdx ]; 946 974 } 947 975 976 // adjust color map 948 977 return nextUserColor; 949 978 } 950 979 … … 970 999 * @param backComp composite use to draw background objects 971 1000 * @param backStroke stroke use to draw background objects 972 1001 */ 973 private void drawHeatGray Map(Graphics2D gB, MapView mv, List<WayPoint> listSegm,974 Composite foreComp, Stroke foreStroke,975 Composite backComp, Stroke backStroke) {1002 private void drawHeatGrayLineMap(Graphics2D gB, MapView mv, List<WayPoint> listSegm, 1003 Composite foreComp, Stroke foreStroke, 1004 Composite backComp, Stroke backStroke) { 976 1005 977 1006 // draw foreground 978 1007 boolean drawForeground = foreComp != null && foreStroke != null; … … 1036 1065 final int maxPixelY = imgGray.getHeight(); 1037 1066 1038 1067 // always full or outlines at big samples rasters 1039 final boolean drawOutlines = (outlineWidth > 0) && ((0 == sampleRaster) || (sampleRaster > 8));1068 final boolean drawOutlines = (outlineWidth > 0) && ((0 == sampleRaster) || (sampleRaster > 10)); 1040 1069 1041 1070 // backup stroke 1042 1071 final Stroke oldStroke = g.getStroke(); … … 1142 1171 heatMapGraph2d.setBackground(new Color(0, 0, 0, 255)); 1143 1172 heatMapGraph2d.setColor(Color.WHITE); 1144 1173 1174 // fast draw ( maybe help or not ) 1175 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 1176 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); 1177 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); 1178 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); 1179 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); 1180 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 1181 heatMapGraph2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); 1182 1145 1183 // cache it 1146 1184 heatMapCacheScreenBounds = screenBounds; 1147 1185 } … … 1149 1187 // 2nd. determine current scale factors ------------------------------- 1150 1188 1151 1189 // the line width (foreground: draw extra small footprint line of track) 1152 finalint lineWidthB = (int) Math.max(1.5f * (globalLineWidth / zoomScale) + 1, 2);1153 finalint lineWidthF = lineWidthB > 2 ? (globalLineWidth - 1) : 0;1190 int lineWidthB = (int) Math.max(1.5f * (globalLineWidth / zoomScale) + 1, 2); 1191 int lineWidthF = lineWidthB > 2 ? (globalLineWidth - 1) : 0; 1154 1192 1193 // global alpha adjustment 1194 float lineAlpha = Math.min(Math.max((0.40f/(float) zoomScale)/(globalLineWidth+1), 0.01f), 0.40f); 1195 1196 // adjust 0.15 .. 1.85 1197 float scaleAlpha = 1.0f + ((heatMapDrawGain/10.0f) * 0.85f); 1198 1199 // add to calculated values 1200 float lineAlphaBPoint = Math.max(Math.min(((lineAlpha * 0.65f) * scaleAlpha), 0.90f), 0.001f); 1201 float lineAlphaBLine = Math.max(Math.min(((lineAlpha * 1.00f) * scaleAlpha), 0.90f), 0.001f); 1202 float lineAlphaFLine = Math.max(Math.min(((lineAlpha / 1.50f) * scaleAlpha), 0.90f), 0.001f); 1203 1204 // 3rd Calculate the heat map data by draw GPX traces with alpha value ---------- 1205 1155 1206 // recalculation of image needed 1156 1207 final boolean imageRecalc = !mapViewState.equalsInWindow(heatMapMapViewState) || 1157 1208 heatMapCacheLineWith != globalLineWidth; 1158 1209 1159 // 3rd Calculate the heat map data by draw GPX traces with alpha value ----------1160 1161 1210 // need re-generation of gray image ? 1162 1211 if (imageSetup || imageRecalc) { 1163 1212 … … 1164 1213 // clear background 1165 1214 heatMapGraph2d.clearRect(0, 0, heatMapImgGray.getWidth(), heatMapImgGray.getHeight()); 1166 1215 1167 // alpha combines both values, therefore the foreground shall be lighter 1168 final float lineAlphaB = Math.min(Math.max((0.40f/(float) zoomScale)/(globalLineWidth + 1), 0.01f), 0.40f); 1169 final float lineAlphaF = lineAlphaB / 1.5f; 1216 // point or line blending 1217 if (heatMapDrawPointMode) { 1218 heatMapGraph2d.setComposite(AlphaComposite.SrcOver.derive(lineAlphaBPoint)); 1219 drawHeatGrayDotMap(heatMapGraph2d, mv, visibleSegments, lineWidthB); 1170 1220 1171 // derive draw parameters and draw 1172 drawHeatGrayMap(heatMapGraph2d, mv, visibleSegments, 1173 lineWidthF > 1 ? AlphaComposite.SrcOver.derive(lineAlphaF) : null, 1174 new BasicStroke(lineWidthF, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), 1175 AlphaComposite.SrcOver.derive(lineAlphaB), 1176 new BasicStroke(lineWidthB, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 1221 } else { 1222 drawHeatGrayLineMap(heatMapGraph2d, mv, visibleSegments, 1223 lineWidthF > 1 ? AlphaComposite.SrcOver.derive(lineAlphaFLine) : null, 1224 new BasicStroke(lineWidthF, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), 1225 AlphaComposite.SrcOver.derive(lineAlphaBLine), 1226 new BasicStroke(lineWidthB, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 1227 } 1177 1228 1178 // remember draw parameter s1229 // remember draw parameter 1179 1230 heatMapMapViewState = mapViewState; 1180 1231 heatMapCacheLineWith = globalLineWidth; 1181 1232 } 1182 1233 1183 1234 // 4th. Draw data on target layer, map data via color lookup table -------------- 1184 drawHeatMapGrayMap(g, heatMapImgGray, lineWidthB > 2 ? ( lineWidthB / 2) : 1, lineWidth > 2 ? (lineWidth - 2) : 1);1235 drawHeatMapGrayMap(g, heatMapImgGray, lineWidthB > 2 ? (int) (lineWidthB*1.25f) : 1, lineWidth > 2 ? (lineWidth - 2) : 1); 1185 1236 } 1186 1237 1238 1187 1239 /** 1240 * Draw a dotted heat map 1241 * 1242 * @param gB the common draw object to use 1243 * @param mv the meta data to current displayed area 1244 * @param listSegm segments visible in the current scope of mv 1245 * @param drawSize draw size of draw element 1246 */ 1247 private void drawHeatGrayDotMap(Graphics2D gB, MapView mv, List<WayPoint> listSegm, int drawSize) { 1248 1249 // typical rendering rate -> use realtime preview instead of accurate display 1250 final double maxSegm = 25000, nrSegms = listSegm.size(); 1251 1252 // determine random drop rate 1253 final double randomDrop = Math.min(nrSegms > maxSegm ? (nrSegms - maxSegm) / nrSegms : 0, 0.70f); 1254 1255 // http://www.nstb.tc.faa.gov/reports/PAN94_0716.pdf#page=22 1256 // Global Average Position Domain Accuracy, typical -> not worst case ! 1257 // < 4.218 m Vertical 1258 // < 2.168 m Horizontal 1259 final double pixelRmsX = (100 / mv.getDist100Pixel()) * 2.168; 1260 final double pixelRmsY = (100 / mv.getDist100Pixel()) * 4.218; 1261 1262 Point lastPnt = null; 1263 1264 // for all points, draw single lines 1265 for (WayPoint trkPnt : listSegm) { 1266 1267 // get transformed coordinates 1268 final Point paintPnt = mv.getPoint(trkPnt.getEastNorth()); 1269 1270 // end of line segment or end of list reached 1271 if (trkPnt.drawLine && null != lastPnt) { 1272 drawHeatSurfaceLine(gB, paintPnt, lastPnt, drawSize, pixelRmsX, pixelRmsY, randomDrop); 1273 } 1274 1275 // remember 1276 lastPnt = paintPnt; 1277 } 1278 } 1279 1280 /** 1281 * Draw a dotted surface line 1282 * 1283 * @param g the common draw object to use 1284 * @param fromPnt start point 1285 * @param toPnt end point 1286 * @param drawSize size of draw elements 1287 * @param rmsSizeX RMS size of circle for X (width) 1288 * @param rmsSizeY RMS size of circle for Y (height) 1289 * @param dropRate Pixel render drop rate 1290 */ 1291 private void drawHeatSurfaceLine(Graphics2D g, Point fromPnt, Point toPnt, int drawSize, double rmsSizeX, double rmsSizeY, double dropRate) { 1292 1293 // collect frequently used items 1294 final int fromX = (int) fromPnt.getX(); final int deltaX = (int) (toPnt.getX() - fromX); 1295 final int fromY = (int) fromPnt.getY(); final int deltaY = (int) (toPnt.getY() - fromY); 1296 1297 // use same random values for each point 1298 final Random heatMapRandom = new Random(fromX+fromY+deltaX+deltaY); 1299 1300 // cache distance between start and end point 1301 final int dist = (int) Math.abs(fromPnt.distance(toPnt)); 1302 1303 // number of increment ( fill wide distance tracks ) 1304 double scaleStep = Math.max(1.0f / dist, dist > 100 ? 0.10f : 0.20f); 1305 1306 // number of additional random points 1307 int rounds = Math.min(drawSize/2, 1)+1; 1308 1309 // decrease random noise at high drop rate ( more accurate draw of fewer points ) 1310 rmsSizeX *= (1.0d - dropRate); 1311 rmsSizeY *= (1.0d - dropRate); 1312 1313 double scaleVal = 0; 1314 1315 // interpolate line draw ( needs separate point instead of line ) 1316 while (scaleVal < (1.0d-0.0001d)) { 1317 1318 // get position 1319 final double pntX = fromX + scaleVal * deltaX; 1320 final double pntY = fromY + scaleVal * deltaY; 1321 1322 // add random distribution around sampled point 1323 for (int k = 0; k < rounds; k++) { 1324 1325 // add error distribution, first point with less error 1326 int x = (int) (pntX + heatMapRandom.nextGaussian() * (k > 0 ? rmsSizeX : rmsSizeX/4)); 1327 int y = (int) (pntY + heatMapRandom.nextGaussian() * (k > 0 ? rmsSizeY : rmsSizeY/4)); 1328 1329 // draw it, even drop is requested 1330 if (heatMapRandom.nextDouble() >= dropRate) { 1331 g.fillRect(x-drawSize, y-drawSize, drawSize, drawSize); 1332 } 1333 } 1334 scaleVal += scaleStep; 1335 } 1336 } 1337 1338 /** 1188 1339 * Apply default color configuration to way segments 1189 1340 * @param visibleSegments segments visible in the current scope of mv 1190 1341 */ … … 1205 1356 || (computeCacheColorTracksTune != colorTracksTune) 1206 1357 || (computeCacheColorDynamic != colorModeDynamic) 1207 1358 || (computeCacheHeatMapDrawColorTableIdx != heatMapDrawColorTableIdx) 1208 || (!neutralColor.equals(computeCacheColorUsed)) 1359 || (!neutralColor.equals(computeCacheColorUsed) 1360 || (computeCacheHeatMapDrawPointMode != heatMapDrawPointMode) 1361 || (computeCacheHeatMapDrawGain != heatMapDrawGain)) 1362 || (computeCacheHeatMapDrawLowerLimit != heatMapDrawLowerLimit) 1209 1363 ) { 1210 1364 computeCacheMaxLineLengthUsed = maxLineLength; 1211 1365 computeCacheInSync = false; … … 1214 1368 computeCacheColorTracksTune = colorTracksTune; 1215 1369 computeCacheColorDynamic = colorModeDynamic; 1216 1370 computeCacheHeatMapDrawColorTableIdx = heatMapDrawColorTableIdx; 1371 computeCacheHeatMapDrawPointMode = heatMapDrawPointMode; 1372 computeCacheHeatMapDrawGain = heatMapDrawGain; 1373 computeCacheHeatMapDrawLowerLimit = heatMapDrawLowerLimit; 1217 1374 } 1218 1375 } 1219 1376 -
src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java
9 9 import java.awt.Dimension; 10 10 import java.awt.GridBagLayout; 11 11 import java.awt.event.ActionListener; 12 import java.util.Enumeration; 12 13 14 import javax.swing.AbstractButton; 13 15 import javax.swing.BorderFactory; 14 16 import javax.swing.Box; 15 17 import javax.swing.ButtonGroup; … … 18 20 import javax.swing.JOptionPane; 19 21 import javax.swing.JPanel; 20 22 import javax.swing.JRadioButton; 23 import javax.swing.JSlider; 21 24 22 25 import org.openstreetmap.josm.Main; 23 26 import org.openstreetmap.josm.actions.ExpertToggleAction; … … 63 66 private final JRadioButton colorTypeGlobal = new JRadioButton(tr("Use global settings")); 64 67 private final JosmComboBox<String> colorTypeVelocityTune = new JosmComboBox<>(new String[] {tr("Car"), tr("Bicycle"), tr("Foot")}); 65 68 private final JosmComboBox<String> colorTypeHeatMapTune = new JosmComboBox<>(new String[] { 66 trc("Heat map", "User"), 69 trc("Heat map", "User Normal"), 70 trc("Heat map", "User Light"), 71 trc("Heat map", "Traffic Lights"), 67 72 trc("Heat map", "Inferno"), 68 73 trc("Heat map", "Viridis"), 69 74 trc("Heat map", "Wood"), 70 75 trc("Heat map", "Heat")}); 76 private final JCheckBox colorTypeHeatMapPoints = new JCheckBox(tr("Use points instead of lines for heat map")); 77 private final JSlider colorTypeHeatMapGain = new JSlider(); 78 private final JSlider colorTypeHeatMapLowerLimit = new JSlider(); 79 private JLabel colorTypeHeatMapLowerLimitLabel; 80 private JLabel colorTypeHeatMapGainLabel; 71 81 private final JCheckBox makeAutoMarkers = new JCheckBox(tr("Create markers when reading GPX")); 72 82 private final JCheckBox drawGpsArrows = new JCheckBox(tr("Draw Direction Arrows")); 73 83 private final JCheckBox drawGpsArrowsFast = new JCheckBox(tr("Fast drawing (looks uglier)")); … … 228 238 229 239 // colorTracks 230 240 ButtonGroup colorGroup = new ButtonGroup(); 241 231 242 if (layerName != null) { 232 243 colorGroup.add(colorTypeGlobal); 233 244 } … … 238 249 colorGroup.add(colorTypeTime); 239 250 colorGroup.add(colorTypeHeatMap); 240 251 241 colorTypeVelocity.addChangeListener(e -> {242 colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected());243 colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected());244 });245 246 colorTypeHeatMap.addChangeListener(e -> {247 colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected());248 colorDynamic.setEnabled(false);249 });250 251 colorTypeDilution.addChangeListener(e -> colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected()));252 253 252 colorTypeNone.setToolTipText(tr("All points and track segments will have the same color. Can be customized in Layer Manager.")); 254 253 colorTypeVelocity.setToolTipText(tr("Colors points and track segments by velocity.")); 255 254 colorTypeDirection.setToolTipText(tr("Colors points and track segments by direction.")); … … 280 279 add(colorTypeHeatIconLabel, GBC.std().insets(5, 0, 0, 5)); 281 280 add(colorTypeHeatMapTune, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5)); 282 281 282 colorTypeHeatMapGainLabel = new JLabel(tr("Overlay gain adjustment")); 283 colorTypeHeatMapLowerLimitLabel = new JLabel(tr("Lower limit of visibility")); 284 add(colorTypeHeatMapGainLabel, GBC.std().insets(80, 0, 0, 0)); 285 add(colorTypeHeatMapGain, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5)); 286 add(colorTypeHeatMapLowerLimitLabel, GBC.std().insets(80, 0, 0, 0)); 287 add(colorTypeHeatMapLowerLimit, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5)); 288 add(colorTypeHeatMapPoints, GBC.eol().insets(60, 0, 0, 0)); 289 290 colorTypeHeatMapGain.setToolTipText(tr("Adjust the gain of overlay blending.")); 291 colorTypeHeatMapGain.setOrientation(JSlider.HORIZONTAL); 292 colorTypeHeatMapGain.setPaintLabels(true); 293 colorTypeHeatMapGain.setMinimum(-10); 294 colorTypeHeatMapGain.setMaximum(+10); 295 colorTypeHeatMapGain.setMinorTickSpacing(1); 296 colorTypeHeatMapGain.setMajorTickSpacing(5); 297 298 colorTypeHeatMapLowerLimit.setToolTipText(tr("Draw all GPX traces that exceed this threshold.")); 299 colorTypeHeatMapLowerLimit.setOrientation(JSlider.HORIZONTAL); 300 colorTypeHeatMapLowerLimit.setMinimum(0); 301 colorTypeHeatMapLowerLimit.setMaximum(254); 302 colorTypeHeatMapLowerLimit.setPaintLabels(true); 303 colorTypeHeatMapLowerLimit.setMinorTickSpacing(10); 304 colorTypeHeatMapLowerLimit.setMajorTickSpacing(100); 305 306 colorTypeHeatMapPoints.setToolTipText(tr("Render engine uses points with simulated position error instead of lines. ")); 307 308 // iterate over the buttons, add change listener to any change event 309 for (Enumeration<AbstractButton> button = colorGroup.getElements(); button.hasMoreElements();) { 310 (button.nextElement()).addChangeListener(e -> { 311 colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected()); 312 colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected()); 313 colorTypeHeatMapPoints.setEnabled(colorTypeHeatMap.isSelected()); 314 colorTypeHeatMapGain.setEnabled(colorTypeHeatMap.isSelected()); 315 colorTypeHeatMapLowerLimit.setEnabled(colorTypeHeatMap.isSelected()); 316 colorTypeHeatMapGainLabel.setEnabled(colorTypeHeatMap.isSelected()); 317 colorTypeHeatMapLowerLimitLabel.setEnabled(colorTypeHeatMap.isSelected()); 318 colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected()); 319 }); 320 } 321 283 322 colorTypeHeatMapTune.addPropertyChangeListener(e -> { 284 323 final Dimension dim = colorTypeHeatMapTune.getPreferredSize(); 285 324 if (null != dim) { … … 298 337 299 338 ExpertToggleAction.addVisibilitySwitcher(colorTypeDirection); 300 339 ExpertToggleAction.addVisibilitySwitcher(colorTypeDilution); 340 ExpertToggleAction.addVisibilitySwitcher(colorTypeHeatMapLowerLimit); 341 ExpertToggleAction.addVisibilitySwitcher(colorTypeHeatMapLowerLimitLabel); 301 342 302 343 colorDynamic.setToolTipText(tr("Colors points and track segments by data limits.")); 303 344 add(colorDynamic, GBC.eop().insets(40, 0, 0, 0)); … … 377 418 colorTypeGlobal.setSelected(true); 378 419 colorDynamic.setSelected(false); 379 420 colorDynamic.setEnabled(false); 421 colorTypeHeatMapPoints.setSelected(false); 422 colorTypeHeatMapGain.setValue(0); 423 colorTypeHeatMapLowerLimit.setValue(0); 380 424 } else { 381 425 int colorType = Main.pref.getInteger("draw.rawgps.colors", layerName, 0); 382 426 switch (colorType) { … … 390 434 } 391 435 int ccts = Main.pref.getInteger("draw.rawgps.colorTracksTune", layerName, 45); 392 436 colorTypeVelocityTune.setSelectedIndex(ccts == 10 ? 2 : (ccts == 20 ? 1 : 0)); 393 colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected() && colorTypeVelocity.isEnabled());394 395 437 colorTypeHeatMapTune.setSelectedIndex(Main.pref.getInteger("draw.rawgps.heatmap.colormap", layerName, 0)); 396 colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected() && colorTypeHeatMap.isEnabled());397 398 438 colorDynamic.setSelected(Main.pref.getBoolean("draw.rawgps.colors.dynamic", layerName, false)); 399 colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected()); 439 colorTypeHeatMapPoints.setSelected(Main.pref.getBoolean("draw.rawgps.heatmap.use-points", layerName, false)); 440 colorTypeHeatMapGain.setValue(Main.pref.getInteger("draw.rawgps.heatmap.gain", layerName, 0)); 441 colorTypeHeatMapLowerLimit.setValue(Main.pref.getInteger("draw.rawgps.heatmap.lower-limit", layerName, 0)); 400 442 } 401 443 } 402 444 … … 469 511 Main.pref.putInteger("draw.rawgps.colorTracksTune"+layerNameDot, ccti == 2 ? 10 : (ccti == 1 ? 20 : 45)); 470 512 471 513 Main.pref.putInteger("draw.rawgps.heatmap.colormap"+layerNameDot, colorTypeHeatMapTune.getSelectedIndex()); 514 Main.pref.put("draw.rawgps.heatmap.use-points"+layerNameDot, colorTypeHeatMapPoints.isSelected()); 515 Main.pref.putInteger("draw.rawgps.heatmap.gain"+layerNameDot, colorTypeHeatMapGain.getValue()); 516 Main.pref.putInteger("draw.rawgps.heatmap.lower-limit"+layerNameDot, colorTypeHeatMapLowerLimit.getValue()); 472 517 473 518 return false; 474 519 }