Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(revision 11565)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(revision 11566)
@@ -28,4 +28,5 @@
 import java.util.Date;
 import java.util.List;
+import java.util.Random;
 
 import javax.swing.ImageIcon;
@@ -96,4 +97,7 @@
     private int computeCacheColorTracksTune;
     private int computeCacheHeatMapDrawColorTableIdx;
+    private boolean computeCacheHeatMapDrawPointMode;
+    private int computeCacheHeatMapDrawGain;
+    private int computeCacheHeatMapDrawLowerLimit;
 
     //// Color-related fields
@@ -135,4 +139,10 @@
     // used index for color table (parameter)
     private int heatMapDrawColorTableIdx;
+    // use point or line draw mode
+    private boolean heatMapDrawPointMode;
+    // extra gain > 0 or < 0 attenuation, 0 = default
+    private int heatMapDrawGain;
+    // do not draw elements with value lower than this limit
+    private int heatMapDrawLowerLimit;
 
     // normal buffered image and draw object (cached)
@@ -156,5 +166,5 @@
 
     // user defined heatmap color
-    private Color[] heatMapLutColor = createColorLut(Color.BLACK, Color.WHITE);
+    private Color[] heatMapLutColor = createColorLut(0, Color.BLACK, Color.WHITE);
 
     private void setupColors() {
@@ -278,5 +288,11 @@
         heatMapEnabled = Main.pref.getBoolean("draw.rawgps.heatmap.enabled", spec, false);
         heatMapDrawExtraLine = Main.pref.getBoolean("draw.rawgps.heatmap.line-extra", spec, false);
-        heatMapDrawColorTableIdx = Main.pref.getInteger("draw.rawgps.heatmap.colormap", specName(layerName), 0);
+        heatMapDrawColorTableIdx = Main.pref.getInteger("draw.rawgps.heatmap.colormap", spec, 0);
+        heatMapDrawPointMode = Main.pref.getBoolean("draw.rawgps.heatmap.use-points", spec, false);
+        heatMapDrawGain = Main.pref.getInteger("draw.rawgps.heatmap.gain", spec, 0);
+        heatMapDrawLowerLimit = Main.pref.getInteger("draw.rawgps.heatmap.lower-limit", spec, 0);
+
+        // shrink to range
+        heatMapDrawGain = Math.min(Math.max(-10, heatMapDrawGain), 10);
 
         neutralColor = getColor(layerName, true);
@@ -514,6 +530,7 @@
         if (ColorMode.HEATMAP == colored) {
 
-            // generate and get new user color map
-            heatMapLutColor = selectColorMap(neutralColor != null ? neutralColor : Color.WHITE, heatMapDrawColorTableIdx);
+            // get new user color map and refresh visibility level
+            heatMapLutColor = createColorLut(heatMapDrawLowerLimit,
+                                             selectColorMap(neutralColor != null ? neutralColor : Color.WHITE, heatMapDrawColorTableIdx));
 
             // force redraw of image
@@ -795,9 +812,10 @@
 
     /**
-     * Creates a linear distributed colormap by linear blending between colors
+     * Creates a distributed colormap by linear blending between colors
+     * @param lowerLimit lower limit for first visible color
      * @param colors 1..n colors
      * @return array of Color objects
      */
-    protected static Color[] createColorLut(Color... colors) {
+    protected static Color[] createColorLut(int lowerLimit, Color... colors) {
 
         // number of lookup entries
@@ -825,8 +843,8 @@
 
             // smooth alpha like sin curve
-            int alpha = (int) (Math.sin(i * mapTo90Deg) * 255);
+            int alpha = (i > lowerLimit) ? (int) (Math.sin((i-lowerLimit) * mapTo90Deg) * 255) : 0;
 
             // alpha with pre-offset, first color -> full transparent
-            alpha = i > 0 ? (10 + alpha) : 0;
+            alpha = alpha > 0 ? (20 + alpha) : 0;
 
             // shrink to maximum bound
@@ -916,5 +934,5 @@
         }
 
-        return createColorLut(colorList.toArray(new Color[ colorList.size() ]));
+        return createColorLut(0, colorList.toArray(new Color[ colorList.size() ]));
     }
 
@@ -928,11 +946,18 @@
     protected static Color[] selectColorMap(Color userColor, int tableIdx) {
 
+        // generate new user color map ( dark, user color, white )
+        Color[] userColor1 = createColorLut(0, userColor.darker(), userColor, userColor.brighter(), Color.WHITE);
+
+        // generate new user color map ( white -> color )
+        Color[] userColor2 = createColorLut(0, Color.WHITE, Color.WHITE, userColor);
+
         // generate new user color map
-        Color[] nextUserColor = createColorLut(Color.BLACK, userColor.darker(),
-                                               userColor, userColor.brighter(), Color.WHITE);
+        Color[] colorTrafficLights = createColorLut(0, Color.WHITE, Color.GREEN.darker(), Color.YELLOW, Color.RED);
 
         // decide what, keep order is sync with setting on GUI
         Color[][] lut = {
-                nextUserColor,
+                userColor1,
+                userColor2,
+                colorTrafficLights,
                 heatMapLutColorJosmInferno,
                 heatMapLutColorJosmViridis,
@@ -941,4 +966,7 @@
         };
 
+        // default case
+        Color[] nextUserColor = userColor1;
+
         // select by index
         if (tableIdx < lut.length) {
@@ -946,4 +974,5 @@
         }
 
+        // adjust color map
         return nextUserColor;
     }
@@ -971,7 +1000,7 @@
      * @param backStroke      stroke use to draw background objects
      */
-    private void drawHeatGrayMap(Graphics2D gB, MapView mv, List<WayPoint> listSegm,
-                                 Composite foreComp, Stroke foreStroke,
-                                 Composite backComp, Stroke backStroke) {
+    private void drawHeatGrayLineMap(Graphics2D gB, MapView mv, List<WayPoint> listSegm,
+                                     Composite foreComp, Stroke foreStroke,
+                                     Composite backComp, Stroke backStroke) {
 
         // draw foreground
@@ -1037,5 +1066,5 @@
 
         // always full or outlines at big samples rasters
-        final boolean drawOutlines = (outlineWidth > 0) && ((0 == sampleRaster) || (sampleRaster > 8));
+        final boolean drawOutlines = (outlineWidth > 0) && ((0 == sampleRaster) || (sampleRaster > 10));
 
         // backup stroke
@@ -1143,4 +1172,13 @@
             heatMapGraph2d.setColor(Color.WHITE);
 
+            // fast draw ( maybe help or not )
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+            heatMapGraph2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
+
             // cache it
             heatMapCacheScreenBounds = screenBounds;
@@ -1150,6 +1188,19 @@
 
         // the line width (foreground: draw extra small footprint line of track)
-        final int lineWidthB = (int) Math.max(1.5f * (globalLineWidth / zoomScale) + 1, 2);
-        final int lineWidthF = lineWidthB > 2 ? (globalLineWidth - 1) : 0;
+        int lineWidthB = (int) Math.max(1.5f * (globalLineWidth / zoomScale) + 1, 2);
+        int lineWidthF = lineWidthB > 2 ? (globalLineWidth - 1) : 0;
+
+        // global alpha adjustment
+        float lineAlpha = Math.min(Math.max((0.40f/(float) zoomScale)/(globalLineWidth+1), 0.01f), 0.40f);
+
+        // adjust 0.15 .. 1.85
+        float scaleAlpha = 1.0f + ((heatMapDrawGain/10.0f) * 0.85f);
+
+        // add to calculated values
+        float lineAlphaBPoint = Math.max(Math.min(((lineAlpha * 0.65f) * scaleAlpha), 0.90f), 0.001f);
+        float lineAlphaBLine = Math.max(Math.min(((lineAlpha * 1.00f) * scaleAlpha), 0.90f), 0.001f);
+        float lineAlphaFLine = Math.max(Math.min(((lineAlpha / 1.50f) * scaleAlpha), 0.90f), 0.001f);
+
+        // 3rd Calculate the heat map data by draw GPX traces with alpha value ----------
 
         // recalculation of image needed
@@ -1157,6 +1208,4 @@
                                     heatMapCacheLineWith != globalLineWidth;
 
-        // 3rd Calculate the heat map data by draw GPX traces with alpha value ----------
-
         // need re-generation of gray image ?
         if (imageSetup || imageRecalc) {
@@ -1165,16 +1214,18 @@
             heatMapGraph2d.clearRect(0, 0, heatMapImgGray.getWidth(), heatMapImgGray.getHeight());
 
-            // alpha combines both values, therefore the foreground shall be lighter
-            final float lineAlphaB = Math.min(Math.max((0.40f/(float) zoomScale)/(globalLineWidth + 1), 0.01f), 0.40f);
-            final float lineAlphaF = lineAlphaB / 1.5f;
-
-            // derive draw parameters and draw
-            drawHeatGrayMap(heatMapGraph2d, mv, visibleSegments,
-                            lineWidthF > 1 ? AlphaComposite.SrcOver.derive(lineAlphaF) : null,
-                            new BasicStroke(lineWidthF, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND),
-                            AlphaComposite.SrcOver.derive(lineAlphaB),
-                            new BasicStroke(lineWidthB, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-
-            // remember draw parameters
+            // point or line blending
+            if (heatMapDrawPointMode) {
+                heatMapGraph2d.setComposite(AlphaComposite.SrcOver.derive(lineAlphaBPoint));
+                drawHeatGrayDotMap(heatMapGraph2d, mv, visibleSegments, lineWidthB);
+
+            } else {
+                drawHeatGrayLineMap(heatMapGraph2d, mv, visibleSegments,
+                                    lineWidthF > 1 ? AlphaComposite.SrcOver.derive(lineAlphaFLine) : null,
+                                    new BasicStroke(lineWidthF, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND),
+                                    AlphaComposite.SrcOver.derive(lineAlphaBLine),
+                                    new BasicStroke(lineWidthB, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+            }
+
+            // remember draw parameter
             heatMapMapViewState = mapViewState;
             heatMapCacheLineWith = globalLineWidth;
@@ -1182,5 +1233,105 @@
 
         // 4th. Draw data on target layer, map data via color lookup table --------------
-        drawHeatMapGrayMap(g, heatMapImgGray, lineWidthB > 2 ? (lineWidthB / 2) : 1, lineWidth > 2 ? (lineWidth - 2) : 1);
+        drawHeatMapGrayMap(g, heatMapImgGray, lineWidthB > 2 ? (int) (lineWidthB*1.25f) : 1, lineWidth > 2 ? (lineWidth - 2) : 1);
+    }
+
+
+    /**
+     * Draw a dotted heat map
+     *
+     * @param gB              the common draw object to use
+     * @param mv              the meta data to current displayed area
+     * @param listSegm        segments visible in the current scope of mv
+     * @param drawSize        draw size of draw element
+     */
+    private void drawHeatGrayDotMap(Graphics2D gB, MapView mv, List<WayPoint> listSegm, int drawSize) {
+
+        // typical rendering rate -> use realtime preview instead of accurate display
+        final double maxSegm = 25000, nrSegms = listSegm.size();
+
+        // determine random drop rate
+        final double randomDrop = Math.min(nrSegms > maxSegm ? (nrSegms - maxSegm) / nrSegms : 0, 0.70f);
+
+        // http://www.nstb.tc.faa.gov/reports/PAN94_0716.pdf#page=22
+        // Global Average Position Domain Accuracy, typical -> not worst case !
+        // < 4.218 m Vertical
+        // < 2.168 m Horizontal
+        final double pixelRmsX = (100 / mv.getDist100Pixel()) * 2.168;
+        final double pixelRmsY = (100 / mv.getDist100Pixel()) * 4.218;
+
+        Point lastPnt = null;
+
+        // for all points, draw single lines
+        for (WayPoint trkPnt : listSegm) {
+
+            // get transformed coordinates
+            final Point paintPnt = mv.getPoint(trkPnt.getEastNorth());
+
+            // end of line segment or end of list reached
+            if (trkPnt.drawLine && null != lastPnt) {
+                drawHeatSurfaceLine(gB, paintPnt, lastPnt, drawSize, pixelRmsX, pixelRmsY, randomDrop);
+            }
+
+            // remember
+            lastPnt = paintPnt;
+        }
+    }
+
+    /**
+     * Draw a dotted surface line
+     *
+     * @param g                 the common draw object to use
+     * @param fromPnt           start point
+     * @param toPnt             end point
+     * @param drawSize          size of draw elements
+     * @param rmsSizeX          RMS size of circle for X (width)
+     * @param rmsSizeY          RMS size of circle for Y (height)
+     * @param dropRate          Pixel render drop rate
+     */
+    private void drawHeatSurfaceLine(Graphics2D g, Point fromPnt, Point toPnt, int drawSize, double rmsSizeX, double rmsSizeY, double dropRate) {
+
+        // collect frequently used items
+        final int fromX = (int) fromPnt.getX(); final int deltaX = (int) (toPnt.getX() - fromX);
+        final int fromY = (int) fromPnt.getY(); final int deltaY = (int) (toPnt.getY() - fromY);
+
+        // use same random values for each point
+        final Random heatMapRandom = new Random(fromX+fromY+deltaX+deltaY);
+
+        // cache distance between start and end point
+        final int dist = (int) Math.abs(fromPnt.distance(toPnt));
+
+        // number of increment ( fill wide distance tracks )
+        double scaleStep = Math.max(1.0f / dist, dist > 100 ? 0.10f : 0.20f);
+
+        // number of additional random points
+        int rounds = Math.min(drawSize/2, 1)+1;
+
+        // decrease random noise at high drop rate ( more accurate draw of fewer points )
+        rmsSizeX *= (1.0d - dropRate);
+        rmsSizeY *= (1.0d - dropRate);
+
+        double scaleVal = 0;
+
+        // interpolate line draw ( needs separate point instead of line )
+        while (scaleVal < (1.0d-0.0001d)) {
+
+            // get position
+            final double pntX = fromX + scaleVal * deltaX;
+            final double pntY = fromY + scaleVal * deltaY;
+
+            // add random distribution around sampled point
+            for (int k = 0; k < rounds; k++) {
+
+                // add error distribution, first point with less error
+                int x = (int) (pntX + heatMapRandom.nextGaussian() * (k > 0 ? rmsSizeX : rmsSizeX/4));
+                int y = (int) (pntY + heatMapRandom.nextGaussian() * (k > 0 ? rmsSizeY : rmsSizeY/4));
+
+                // draw it, even drop is requested
+                if (heatMapRandom.nextDouble() >= dropRate) {
+                    g.fillRect(x-drawSize, y-drawSize, drawSize, drawSize);
+                }
+            }
+            scaleVal += scaleStep;
+        }
     }
 
@@ -1206,5 +1357,8 @@
                 || (computeCacheColorDynamic != colorModeDynamic)
                 || (computeCacheHeatMapDrawColorTableIdx != heatMapDrawColorTableIdx)
-                || (!neutralColor.equals(computeCacheColorUsed))
+                || (!neutralColor.equals(computeCacheColorUsed)
+                || (computeCacheHeatMapDrawPointMode != heatMapDrawPointMode)
+                || (computeCacheHeatMapDrawGain != heatMapDrawGain))
+                || (computeCacheHeatMapDrawLowerLimit != heatMapDrawLowerLimit)
       ) {
             computeCacheMaxLineLengthUsed = maxLineLength;
@@ -1215,4 +1369,7 @@
             computeCacheColorDynamic = colorModeDynamic;
             computeCacheHeatMapDrawColorTableIdx = heatMapDrawColorTableIdx;
+            computeCacheHeatMapDrawPointMode = heatMapDrawPointMode;
+            computeCacheHeatMapDrawGain = heatMapDrawGain;
+            computeCacheHeatMapDrawLowerLimit = heatMapDrawLowerLimit;
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java	(revision 11565)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java	(revision 11566)
@@ -10,5 +10,7 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionListener;
-
+import java.util.Enumeration;
+
+import javax.swing.AbstractButton;
 import javax.swing.BorderFactory;
 import javax.swing.Box;
@@ -19,4 +21,5 @@
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
+import javax.swing.JSlider;
 
 import org.openstreetmap.josm.Main;
@@ -64,9 +67,14 @@
     private final JosmComboBox<String> colorTypeVelocityTune = new JosmComboBox<>(new String[] {tr("Car"), tr("Bicycle"), tr("Foot")});
     private final JosmComboBox<String> colorTypeHeatMapTune = new JosmComboBox<>(new String[] {
-        trc("Heat map", "User"),
+        trc("Heat map", "User Normal"),
+        trc("Heat map", "User Light"),
+        trc("Heat map", "Traffic Lights"),
         trc("Heat map", "Inferno"),
         trc("Heat map", "Viridis"),
         trc("Heat map", "Wood"),
         trc("Heat map", "Heat")});
+    private final JCheckBox colorTypeHeatMapPoints = new JCheckBox(tr("Use points instead of lines for heat map"));
+    private final JSlider colorTypeHeatMapGain = new JSlider();
+    private final JSlider colorTypeHeatMapLowerLimit = new JSlider();
     private final JCheckBox makeAutoMarkers = new JCheckBox(tr("Create markers when reading GPX"));
     private final JCheckBox drawGpsArrows = new JCheckBox(tr("Draw Direction Arrows"));
@@ -239,16 +247,4 @@
         colorGroup.add(colorTypeHeatMap);
 
-        colorTypeVelocity.addChangeListener(e -> {
-            colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected());
-            colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected());
-        });
-
-        colorTypeHeatMap.addChangeListener(e -> {
-            colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected());
-            colorDynamic.setEnabled(false);
-        });
-
-        colorTypeDilution.addChangeListener(e -> colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected()));
-
         colorTypeNone.setToolTipText(tr("All points and track segments will have the same color. Can be customized in Layer Manager."));
         colorTypeVelocity.setToolTipText(tr("Colors points and track segments by velocity."));
@@ -280,4 +276,44 @@
         add(colorTypeHeatIconLabel, GBC.std().insets(5, 0, 0, 5));
         add(colorTypeHeatMapTune, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5));
+
+        JLabel colorTypeHeatMapGainLabel = new JLabel(tr("Overlay gain adjustment"));
+        JLabel colorTypeHeatMapLowerLimitLabel = new JLabel(tr("Lower limit of visibility"));
+        add(colorTypeHeatMapGainLabel, GBC.std().insets(80, 0, 0, 0));
+        add(colorTypeHeatMapGain, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5));
+        add(colorTypeHeatMapLowerLimitLabel, GBC.std().insets(80, 0, 0, 0));
+        add(colorTypeHeatMapLowerLimit, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 5));
+        add(colorTypeHeatMapPoints, GBC.eol().insets(60, 0, 0, 0));
+
+        colorTypeHeatMapGain.setToolTipText(tr("Adjust the gain of overlay blending."));
+        colorTypeHeatMapGain.setOrientation(JSlider.HORIZONTAL);
+        colorTypeHeatMapGain.setPaintLabels(true);
+        colorTypeHeatMapGain.setMinimum(-10);
+        colorTypeHeatMapGain.setMaximum(+10);
+        colorTypeHeatMapGain.setMinorTickSpacing(1);
+        colorTypeHeatMapGain.setMajorTickSpacing(5);
+
+        colorTypeHeatMapLowerLimit.setToolTipText(tr("Draw all GPX traces that exceed this threshold."));
+        colorTypeHeatMapLowerLimit.setOrientation(JSlider.HORIZONTAL);
+        colorTypeHeatMapLowerLimit.setMinimum(0);
+        colorTypeHeatMapLowerLimit.setMaximum(254);
+        colorTypeHeatMapLowerLimit.setPaintLabels(true);
+        colorTypeHeatMapLowerLimit.setMinorTickSpacing(10);
+        colorTypeHeatMapLowerLimit.setMajorTickSpacing(100);
+
+        colorTypeHeatMapPoints.setToolTipText(tr("Render engine uses points with simulated position error instead of lines. "));
+
+        // iterate over the buttons, add change listener to any change event
+        for (Enumeration<AbstractButton> button = colorGroup.getElements(); button.hasMoreElements();) {
+            (button.nextElement()).addChangeListener(e -> {
+                colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected());
+                colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected());
+                colorTypeHeatMapPoints.setEnabled(colorTypeHeatMap.isSelected());
+                colorTypeHeatMapGain.setEnabled(colorTypeHeatMap.isSelected());
+                colorTypeHeatMapLowerLimit.setEnabled(colorTypeHeatMap.isSelected());
+                colorTypeHeatMapGainLabel.setEnabled(colorTypeHeatMap.isSelected());
+                colorTypeHeatMapLowerLimitLabel.setEnabled(colorTypeHeatMap.isSelected());
+                colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected());
+            });
+        }
 
         colorTypeHeatMapTune.addActionListener(e -> {
@@ -299,4 +335,6 @@
         ExpertToggleAction.addVisibilitySwitcher(colorTypeDirection);
         ExpertToggleAction.addVisibilitySwitcher(colorTypeDilution);
+        ExpertToggleAction.addVisibilitySwitcher(colorTypeHeatMapLowerLimit);
+        ExpertToggleAction.addVisibilitySwitcher(colorTypeHeatMapLowerLimitLabel);
 
         colorDynamic.setToolTipText(tr("Colors points and track segments by data limits."));
@@ -378,4 +416,7 @@
             colorDynamic.setSelected(false);
             colorDynamic.setEnabled(false);
+            colorTypeHeatMapPoints.setSelected(false);
+            colorTypeHeatMapGain.setValue(0);
+            colorTypeHeatMapLowerLimit.setValue(0);
         } else {
             int colorType = Main.pref.getInteger("draw.rawgps.colors", layerName, 0);
@@ -391,11 +432,9 @@
             int ccts = Main.pref.getInteger("draw.rawgps.colorTracksTune", layerName, 45);
             colorTypeVelocityTune.setSelectedIndex(ccts == 10 ? 2 : (ccts == 20 ? 1 : 0));
-            colorTypeVelocityTune.setEnabled(colorTypeVelocity.isSelected() && colorTypeVelocity.isEnabled());
-
             colorTypeHeatMapTune.setSelectedIndex(Main.pref.getInteger("draw.rawgps.heatmap.colormap", layerName, 0));
-            colorTypeHeatMapTune.setEnabled(colorTypeHeatMap.isSelected() && colorTypeHeatMap.isEnabled());
-
             colorDynamic.setSelected(Main.pref.getBoolean("draw.rawgps.colors.dynamic", layerName, false));
-            colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected());
+            colorTypeHeatMapPoints.setSelected(Main.pref.getBoolean("draw.rawgps.heatmap.use-points", layerName, false));
+            colorTypeHeatMapGain.setValue(Main.pref.getInteger("draw.rawgps.heatmap.gain", layerName, 0));
+            colorTypeHeatMapLowerLimit.setValue(Main.pref.getInteger("draw.rawgps.heatmap.lower-limit", layerName, 0));
         }
     }
@@ -468,6 +507,8 @@
         int ccti = colorTypeVelocityTune.getSelectedIndex();
         Main.pref.putInteger("draw.rawgps.colorTracksTune"+layerNameDot, ccti == 2 ? 10 : (ccti == 1 ? 20 : 45));
-
         Main.pref.putInteger("draw.rawgps.heatmap.colormap"+layerNameDot, colorTypeHeatMapTune.getSelectedIndex());
+        Main.pref.put("draw.rawgps.heatmap.use-points"+layerNameDot, colorTypeHeatMapPoints.isSelected());
+        Main.pref.putInteger("draw.rawgps.heatmap.gain"+layerNameDot, colorTypeHeatMapGain.getValue());
+        Main.pref.putInteger("draw.rawgps.heatmap.lower-limit"+layerNameDot, colorTypeHeatMapLowerLimit.getValue());
 
         return false;
