I have a web application with several points placed on a map. Every point is associated with a value, good values are green,ok values yellow and bad values red. If two values are close enough I would like them to merge colours between them e.g. One point is red and the other point is yellow the area between them should be orange.
I have looked into heat maps but not found anything that works for my needs.
Anyone know of any good libraries that solve this problem?
Just make the images for these points being PNGs with alpha channels set to 0.5 or other suitable value.
Related
I've been struggling the past few days to optimize performance on a D3 map, especially on mobile. I am using SVG transforms for zooming and panning but made the following observation: the overkill comes from path strokes used to fake spacing between countries.
I have uploaded a pair of sample maps for comparison:
http://www.nicksotiriadis.gr/d3/d3-map-1.html
http://www.nicksotiriadis.gr/d3/d3-map-2.html
The only difference between the two maps is the stroke path along the country paths, and the difference in performance is even noticeable on desktop devices - but more obvious on mobile. Removing the path strokes makes mobile performance a breeze..
I tried all kinds of svg stroke shape-rendering options without significant results.
Now to the question. Is there any way to remove a thin border from each country to fake the spacing between countries instead of using a stroke?
If anyone else has a different suggestion I'd love to hear it!
Update: Attaching explanation photo.
What I have drawn is this. The red arrow points to the country joints. When adding a stroke in a color same as the background to the country paths (here depicted in dark grey color) it creates the sense that the countries are seprated - however this adds a serious performance hit on mobile devices. What I am looking for is somehow re-shape the countries paths so that their borderlines are where the blue arrow points, but without having a stroke.
Update 2: People seem not to be able to understand what I am looking for, so I am updating this in order to make the question even clearer.
Let's assume that the original countries paths are shown on the left of this image. What I am looking for is a way that I can somehow 'contract' the paths inwards so that the newly created paths shown in red, leave enough empty space between them that will 'emulate' a stroke between them.
Doing this, will leave no use to having an extra layer of strokes, thus gain performance from only using paths instead of paths+strokes.
Update 2: Hello again, I seem to have found a half-solution to my problem. I managed to extract the topojson to shapefile, edit the shapefile the way I want (used a program named OpenJump), but the conversion takes away all the topojson properties I need - id, country name, so I can't convert back to the original topojson.
Does anyone have any suggestions?
D3 has a thing just for that: topojson.mesh() (see documentation). The idea is that since most countries share borders, there's no need to draw the shared borders twice. If you can draw each border only once, you get as much as 80% reduction in the number of strokes you have to draw. The mesh method does the javascript processing to turn a bunch of closed shapes (countries) into the multiline path of just the borders between them. You can then draw that multiline path into a single <path> object that you position on top of the fills.
The mesh looks like this.
Here's another example.
Finally found the answer. This radically improves d3 map performance!
1) I got my topojson file and extracted to shapefile using mapshaper.org. This gives 3 files: .shp, .shx, .dbf . From what I realized the .dbf file holds all the TopoJSON properties/attributes.
2) Opened the .shp shape file to OpenJUMP http://www.openjump.org/ - Which automatically imports the .dbf file as well.
3) I selected the countries layer and went to Tools > Analysis > Buffer.
4) Checked the Update geometry in source layer box so that the geometry is edited without losing the rest of the attributes/properties and added a negative Fixed Distance -0.1. This shrinked all the country geometries to the result I was looking for.
5) Saved Dataset as ESRI Shapefile
6) Reimported BOTH .shp and .dbf that were produced from OpenJUMP back to mapshaper.org - careful, BOTH files.
7) Exported as TopoJSON. Contains new shape and all original properties/attributes!
The following link has been updated with the new produced map; we have a 'bordered' look without the need of strokes.
http://v7.nicksotiriadis.gr/d3/d3-map-1.html
Compare the performance to this link that has the original shapes + stroke. Please try on mobile to see the performance difference!
http://v7.nicksotiriadis.gr/d3/d3-map-2.html
Also, here is the updated world map TopoJSON file in case someone wants some extra performance! :D
http://v7.nicksotiriadis.gr/d3/js/world-topo-bordered.json
There might be a couple of reasons of this behaviour (on my computer, everything is working fine at the same speed ):
Browser
Which browser do you use ? On Chrome, your exemples are working perfectly.
TopoJson
eg. previous answer.
Animation
You are launching the animation when the page is loading. You might want to add a delay (animation().delay(in ms)). There is also a function in D3: queue(), https://github.com/mbostock/queue which load the data before launching a function.
--
If none of this change your problem, and if you want it to work fine on mobile, you can try to mix D3 and Leaflet (map for mobiles), which is great in term of performance by loading tiles.
One example:
http://bl.ocks.org/zross/6a31f4ef9e778d94c204
Hope it helps
I am looking for an algorithm or a code to find similar pixels (pixels that have similar colors) in client side and change the color of just those pixels. I searched a lot but couldn't find any formula for finding similar pixels. The thing that I want to make is like Magic Wand tool in Photoshop. So with this tool we can colorize some part of a product to make the custom color. Also we have some color restriction in production and we can just use some colors.
I tried to find a logic with some formula like: finding euclidean distance of each pixel in compare with its neighbors' pixels with canvas and java script and compare the amount. But its not working well. The weakness is every picture has pixels with similar colors but different color shades. This algorithm is not very smart in finding different color shades. But in Photoshop we can select an area with same color with magic wand tool and then expand that area to the similar color shades with "similar" option.
What do you have so far? It would be helpful if you shared relevant code you've written so far (i.e. for searching through pixels, comparing pixel colors...)
If you haven't already, you may want to familiarize yourself with floodfill algorithms. This will be the basis of your traversal algorithm.
Color comparison, as I understand it, is not exactly a solved problem. A three dimensional euclidean distance measurement is not a bad idea and is a simple solution to implement. This article suggests "[computing] the absolute difference between each component in the chosen color versus the current color. We say the difference between two colors is the largest difference between the individual color components."
However, humans do not perceive color differences as differences in red, green and blue features.
Another page you'd be interested in reading: How to compare two colors for similarity/difference. One answer for that question suggests computing the HSL values of the color, then using the formula:
avghue = (color1.hue + color2.hue)/2
distance = abs(color1.hue-avghue)
If you want to get into some color theory, Delta-E could provide you with some insight into color differences.
Your solution might be to let your users wave the magic wand !
So instead of selecting 1 color by clicking with the magic wand, how about letting the user drag the magic wand across multiple pixels.
Accumulate any unique colors the user drags across.
Then do a color-change based on that accumulated group of colors rather than 1 color.
Yes, it's not as automatic as Photoshop's magic wand tolerance setting, but substituting the human eye/brain can't be all bad !
#Austin is right about color theory vs the human eye not coordinating well. The Euclidian method will do mathematical color matching...but the human eye is very picky about how it perceives color.
You mention "different color shades"...
You might look into presenting your images in HSL color format to make color comparison easier.
Instead of color-mixing (like rgb does), HSL breaks colors into Hue (color), Saturation (depth) and Lightness (well, lightness).
In HSL all hues (colors) are arithmetically grouped together so you can request all blue colors from a specified blue plus the 10 nearest blue hues.
I've been searching the internet for a package which can create a simply global map.
There are several which I've searched, webgl globe, kartograph, cartodb, R etc.
None of these have what I'm looking for.
What I'm looking for:
I want a map of the globe, which has two colours for the each country.
there would be a background colour, then the second colour would fill from the bottom by x percent based on an input. For example, if I created a map of gun owners as a percentage over the US map, the background colour would be cream and the second colour would fill the map 55% which represents the amount of gun owners.
So, basically, the second colour in the map would act like a bar chart which fills the colour of the country by the % being applied to the country/area.
Please let me know if any .js library or which tools might be able to do this.
Just take any SVG map of the world and change every country into a mask with two rects below it. Do the rest with a simple loop and svgTopOfTwoElements.style.setProperty("height", heightPercentage, ""). Just search google for getting started with SVG from javascript (it's practically the same as working with HTML elements). The only possible concern would be that 17% of the users don't support SVG (IE8-), but for the ease of use you get in return I would believe this to be an acceptable price.
I have a canvas with image drawn to it.
When the user clicks on the image, I need to find the color region that the user clicked on. A region is defined as a set of 4-way connected pixels with the same color as the pixel that was clicked on.
I need the region in a form that I could use to set a clipping path on the canvas, so that I could fill the area with, say, a gradient, etc.
Are there efficient algorithms for finding a boundary? Something more optimal than flood fill algorithms (I do not need to fill, I just need to find a path around my region).
I believe the Moore Neighborhood tracing algorithm will do what you want. By definition, the Moore Neighborhood looks at 8-connectedness, but you should be able to easily adjust it to 4-connectedness. Your resulting regions will most likely be better if you test for 8-connectedness, but your application may have specific requirements.
Wikipedia has a good outline of the algorithm here. I've worked with this in the past and had great success--it's very fast.
I have locations that have quality 'X', where X can be a negative or positive value. I would like to plot negative values of X as red, and positive values as green. Intermediate values will be yellow. The opacity of the color will correspond to local density of data.
Issue 85 proves that fusion tables alone can't do this yet. Is there a viable extension that can handle this style of heatmapping?
I've made a mockup of what I want here.
I don't know if variable transparency will be an inherent problem. Would that even be possible for a Google Map overlay?
It is indeed possible, though I was only able to solve this problem with custom heatmap code. You can see the result here.
I hope to add the ability to handle both density and data values simultaneously in this API I created. Keep checking.