New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix heat transfer between overlapping heat sources. #90
base: master
Are you sure you want to change the base?
Conversation
Blending function of CSS shadow is not averaging as blurring applied but addition, so it creates exaggerated heat at overlapping area between two heat sources, even exceed the center of a heat source. Heat transfer between sources should be gradually blend like normal color, RGB, then I made it on G channel and used Math.min to make sure the edge still feathering.
The amount of bleedover should really be configurable. |
I just made it on current code base. It should somehow solve the issue #186 and #223 . To use it, add "absolute" property to configuration when creating HeatmapOverlay object I would call it "absolute mode" because it is intended for plotting absolute measured value like scatterplot. The points themselves are not actually heat sources but just heat sampling, so the more point existence in the same area won't increase heat density. Overlapping areas are just casual interpolation effect on top of plain scatterplot, not heat accumulation, so the overlapping area shouldn't have greater intensity than one of its measured points. The technique I did was to separate face filling rendering on Red channel and silhouette edge rendering on Alpha channel. Calculating the overlapping face filling area using ctx.globalCompositeOperation = 'lighten' can retain actual greater value no matter how many times it was overlapped. The trick was to lighten composite using fully opaque color (unless it would use minimum value at the feathering edge), so it needs separated templates for each intensity value. Although it is not true interpolation, I would leave it as maximum biased. The silhouette edge rendering remain the same, and may still be replaced by useGradientOpacity: true . I just renamed variables from shadowXxx to edgeXxx to be consistent with faceXxx . I have to mention that this library is only the one I have seen so far that can work on absolute values rather than relative fashion. I mean the case when points aren't overlapped, the color tone depends on the actual provided value, unlike others (e.g. Google's Heatmap Layer) those will always visualize both extreme red and green for remaining points on current viewport regardless of global value range. |
Hi @adam144dev , The screenshot above was captured from 2013 version, the zero blur option was not available then. I had modified internal constant just to capture and show the cause. The color transition was intended to come from blurring radius. The color transition effect on overlapping area that you see above was side effect by accident but it looks desirable. Unfortunately, was not true averaging. The correct average calculation is like
but what the code does was just combining intermediate result color with next point color
This example shows ratio of 50% of intermediate result and 50% of next point, which the final value tend to bias to the latest point as the ratio always weights new data point equally to whole previous aggregation. The actual 2013 code even changes ratio using opacity left from every next point. It has to be this way because I still cannot calculate true average from stream of data points on uint8 html5 canvas buffer. My April 2018 version was reimplemented on current v2 code base which is using different technique, but still on html5 canvas. I understand that your application would not use blurring option because your data has ordinal nature but this library has interval nature with unknown as zero, so it will result in green(very good, next to unknown) around red(hazardous) which is misleading. You may use this patch on current version for the side effect like in the 2013 screenshot with these assumptions in mind,
You may also change globalAlpha to 0.33 to weight 67% to intermediate result and 33% to every next point. |
Hi Woracheth, I just feel that I am missing something. |
Hi @ErikaHD , Sorry if you downloaded from Woracheth/heatmap.js/build/heatmap.min.js. When you call heatmap via leaflet plugin, you must also pass I didn't test on leaflet plugin, but it should work because I modified on the core heatmap, not particular plugin. I'm not sure whether my version would solve exactly your problem. Your screenshot doesn't seem that you have exaggerated heat between points, unlike my initial problem. |
Hi @Woracheth, The heatmap is looking way better :-) |
Great job @Woracheth We are using the heatmap with around 70.000 points and after applying your changes in Mozilla FF and Edge we have issues with the performance (browser took lot of time to render the heatmap) , however in Chrome is working quite well. Do you have any idea what we can try to solve the performance issues? Thanks |
Hello @Woracheth Would it be possible to do this for the rest of the library (not only for leaflet pluggin)? I cloned the branch and tried
|
Hi @ErikaHD, do you have a demo of your display somewhere? The temperature field looks good visually. I'm having some patchy display but that may be because my data have a log-normal distribution. Comparing with another continuous field, such as yours, would be useful. Thanks I'm also using Leaflet v1.40, heatmap.js leaflet-heatmap.js - unsure if the latter two are the latest available version. Thanks |
Blending function of CSS shadow is not averaging as blurring applied but it is addition, so it creates exaggerated heat at overlapping area between two heat sources, even exceed the center of a heat source.
Heat transfer between sources should be gradually blend like normal color, RGB, then I made it on G channel and used Math.min() to make sure the edge still feathering to transparent.