Changeset 11566 in josm for trunk/src/org/openstreetmap/josm/gui/layer
- Timestamp:
- 2017-02-14T23:37:10+01:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
r11483 r11566 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; … … 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 … … 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) … … 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() { … … 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); 294 295 // shrink to range 296 heatMapDrawGain = Math.min(Math.max(-10, heatMapDrawGain), 10); 281 297 282 298 neutralColor = getColor(layerName, true); … … 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 … … 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 … … 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 … … 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 … … 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, … … 941 966 }; 942 967 968 // default case 969 Color[] nextUserColor = userColor1; 970 943 971 // select by index 944 972 if (tableIdx < lut.length) { … … 946 974 } 947 975 976 // adjust color map 948 977 return nextUserColor; 949 978 } … … 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 … … 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 … … 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; … … 1150 1188 1151 1189 // the line width (foreground: draw extra small footprint line of track) 1152 final int lineWidthB = (int) Math.max(1.5f * (globalLineWidth / zoomScale) + 1, 2); 1153 final int 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; 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 ---------- 1154 1205 1155 1206 // recalculation of image needed … … 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) { … … 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; 1170 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)); 1177 1178 // remember draw parameters 1216 // point or line blending 1217 if (heatMapDrawPointMode) { 1218 heatMapGraph2d.setComposite(AlphaComposite.SrcOver.derive(lineAlphaBPoint)); 1219 drawHeatGrayDotMap(heatMapGraph2d, mv, visibleSegments, lineWidthB); 1220 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 } 1228 1229 // remember draw parameter 1179 1230 heatMapMapViewState = mapViewState; 1180 1231 heatMapCacheLineWith = globalLineWidth; … … 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); 1236 } 1237 1238 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 } 1185 1336 } 1186 1337 … … 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; … … 1215 1369 computeCacheColorDynamic = colorModeDynamic; 1216 1370 computeCacheHeatMapDrawColorTableIdx = heatMapDrawColorTableIdx; 1371 computeCacheHeatMapDrawPointMode = heatMapDrawPointMode; 1372 computeCacheHeatMapDrawGain = heatMapDrawGain; 1373 computeCacheHeatMapDrawLowerLimit = heatMapDrawLowerLimit; 1217 1374 } 1218 1375 }
Note:
See TracChangeset
for help on using the changeset viewer.