I have a large set of rectangles that are drawn on html5 canvas.
I would like to be able to interact with this image using mouse tracking (I cannot use SVG because it does not scale to 10-100k rectangles). Is there any data structure/algo that, given the mouse x,y coordinates would be able to tell you which box the mouse was over (using the computed locations of the rectangles)? I was thinking something like a k-d tree but was not sure.
If your data is always of the form shown I think you should be able to do better than a spatial tree data structure.
Since the data is structured in y you should be able to calculate which 'strip' of rectangles the points is in based on offsets in O(1) time.
If you store the individual rectangles within each 'strip' in sorted order (using xmax say) you should then be able to locate the specific rectangle within the strip using a binary search (in O(log(n))).
Hope this helps.
The naive solution would be to iterate over all rectangles and check if you are in it. Checking for a single rectangle is easy (if you want I will write it down explicitly).
If you have many rectangles and care about performance, you can easily speed things up by putting the rectangles in a data structure which is faster to look in. Looking at the image you sent, one obvious property of your data is that there is a limited amount of vertical positions ("rows"). This means that if you check which row you are on, you then only need to check rectangles within that row. Finally, to select which row you are on or within a row select which rectangle, keep a sorted data structure (e.g. some search tree).
So your data structure could be something like a search tree for row, where each node holds a search tree of rectangles along the row.
R-tree is suitable for providing spatial access of this kind
But some questions:
Is your rectangle set static or dynamic?
How many point queries do you expect for rectangle set?
Edit:
Because rectangle set is static:
There is method, used in traditional graphics with bitmaps (don't know is it applicable to html5 canvas or not):
Make additional bitmap with the same size as main picture. Draw every rectangle with the same coordinates, but fill it with unique color (for example, color = rectangle index). Then check color under mouse point => get rectangle index in O(1)
Related
I have some geoJSON polygons that I render via layers on top of my map. Depending on the shape itself and the zoom level, sometimes the rendered shapes are too small and it doesn't make sense to even show them.
Is there a way to hide shapes that have rendered area less than some number?
So, as Babis.amas suggested, first I calculate the area of the feature with help of turf.area. It gives the value in square meters. Then I convert this value to pixels using the function mentioned here. And then it really depends on the shape type I'm dealing with. If the shape considered to be too small to be rendered, I just don't add it to the layer data feature collection.
I am working on an API that use shapes (and irregular) shapes to build websites. My problem is where I can provide a div that can carry as a background to irregular shapes so .
However to do this I would need to know the max area the object is taking up by having the max height and width.
I am aware that element.getBoundingClientRect does this but my roadblock is that is does not consider any psuedo elements, which is how most of these shapes are made.
I know when working with the CSS transform property, especially using scale, the browser knows to resize the whole shape including the pseudo element that makes up the shape.
It also uses the border-box coordinate system.
However the browser does not provide this information as it comes from the user agent
My main question is how do I access the dimensions the user agent computes for any given element, or how do I find the proper dimensions of a 'getBoundingClientRect' that considers an elements psuedo classes
My shapes can be found in the attached links.
httpsmichaelodumosu57.github.iosigma-xi-mu
https://css-tricks.com/examples/ShapesOfCSS/
I can't afford to use any other method to create my shapes because I have limited time on the project, but I do know that the browser can provide me with the information I am looking for.
Yes I have answered my own question. What you want to do is to scale the image to a very small since (since transform scale() works perfectly) and place it in a grid box (this could be a div of small size as well. You would run document.elementsFromPoint(x, y)
(notice the pluralization) on every point in the div containing you shrunked irregular shape and from there you can find the height and width of its bounding box by the difference of the highest range of their respective coordinate values. To center you must place your irregular shape in the bounding box of the background drop with the re-scaled dimensions (remember your skrunked your irregular shape to find them) and have the margin of the inner shape set to zero. This works only if your real (not pseudo element) is to the left most of the screen. Question is how do you position your background when your irregular shape is not properrly centering inside of it?
You can use document.elementFromPoint(x, y) for getting the element that exists in specific point, but I have not tested it for any kind of shapes.
I am working on a data set of coordinate points(many dots in area) either (x,y) or (lat,lon) which fall into multiple categories. What I am trying to do is get polygons of areas from those points which are called concave or non-convex as far as I know, but also those polygons have to be next to each other with no gaps between them.
These are the initial points(example)
This is the approximate result I am aiming for
Real life example would be European geopolitical map, if you had all of the addresses of all countries and wanted to get area of each country as a polygon and end up with a map.
I have come across many questions related to getting polygons from set of points, but were unable to use it in my scenario. If you need any more information please let me know. Thank you for your help.
You could use a Voronoi tesselation of the input space. Instead of having point you have sets of points though. Basically, you take each point in space, and look at the closest point to it. It then gets the same "class" as that point. For smoother outputs you could look at a k majority out of N nearest points. It would mean working with a bitmap image rather than 2D coordinates, but you'd get something workable. You could then use simpler image manipulation tricks (edge detection, binary set operations etc to get just the edges, and then perhaps superimpose those on the image).
As an alternative, you could run a convex hull algorithm on each data set, and then try to fix the overlap areas.
I have a javascript class that uses an SVG to draw a set of cartesian graphs using paths (with both line and curve segments)
Now, the code must intercept a click event on the graph area, and if the click is on - or near - one of the path, it must take the X value, and get the Y values of other paths on the graph.
Click ON the graph area is not a problem with native events, but detecting click NEAR the graph and get all the Y values is a thing that I don't know how to do, because I'm searching for a method using the native JS function and methond, if available.
Yes, I can render every curve in a 2d array and do a lookup, but I'm trying to avoid it. Is there a way to do it without "reverting" to the math approach?
Draw the same curve with a stroke and stroke-width (to make it wider) but make it visibility="hidden" and then use the pointer-events property to make the hidden stroked curve clickable. You can either put the hidden curve on top or underneath the original stroke but if you put it underneath you'll probably want to make the original curve pointer-events="none"
I have an svg element composed of many different path objects, each of which represents one U.S state.
http://jsfiddle.net/jGjZ2/
I would like to merge the east territory (gold) into a single path object with no visible divisions.
The end result should look like this (ignore the inaccuracies):
I am using D3.
There is no GeoJSON or TopoJSON data - the map is svg directly embedded in html (see jsfiddle).
Thanks a lot!
Assuming you can ignore the stated restriction of manipulating an existing SVG image (which seems like an arbitrary restriction given the ready availability of cartographic boundaries in more easy-to-manipulate formats…), you can use topojson.mesh to merge multiple polygons. Though, note this approach has a few limitations as described in this example:
Another simple approach is to just draw the highlighted polygons twice: once with a thick black stroke and no fill, and a second time on top with orange fill and no stroke. This achieves the same effect without any need for topological manipulation:
I suppose if you really had to, you could reach into the SVG element and do the same thing by extracting the vector data, but it will be easier if you start from clean data.