I'm looking for an algorithm which could create shapes based
on arrays with coordinates. I have two 50x50 arrays: one with x and second with y coordinates.
There is always 2500 points. Then I have another 50x50 array with my values for coordinates.
I create 3 to 6 areas based on value (for example 0-100, 200-300 and 300-500). Points with certain values creates areas.
I need an algorithm which can calculate if there is only one shape in area or more and fill shapes with colors.
I need that because I must fill shapes with certain colors for each area.
Language is C#.
Example points.
Expected edges.
Expected result
Basically you could use hierarchical clustering to find the clusters.
Each point is its own cluster
Find two cluster closest together and merge them
Repeat until end condition is met
Couple of specifics: In step 2 you could use many metrics to find the closest clusters. Mean-to-mean distance or minimum distance over all point pairs are probably best choices
In Step 3, you can either stop when remaining number of clusters is 2 (or some other number). Or stop when distance is more than a threshold.
To find the actual outline, I suggest coming up with some optimization function that minimizes the length of outline while minimizing the area of the outline. And the some heuristics to optimize the function.
Something like Area - constant*Length.
Related
I need to get inner border of shape. Previously, I found nearest point to the center of shape in case of square or circle shape, but how can I do it in M-shape case.
What I have (I need marked points at screenshot №2):
Any algorithms, steps to find these points?
UPD: Now, I have segments direction vector like (1, 0) or (0.5, 0.5)
It looks like the first step is to simplify by averaging near-neighbour dots into a single point. Then find the smallest convex polygon that contains all points (easily done). Then selectively punch some sides in to meet the internal points (the polygon becomes concave). There are many ways to select which sides to punch in, and which points to punch in to first, and I can't be sure what's best without knowing more about your specific goals.
A simple approach would be to deal first with those points that are closest to an existing side, and punch the nearest side in to meet them. But you may want to apply other scoring conditions to choose the best points to deal with first and the best sides to punch in. For instance, you may want to give higher scores to points that are closely vertically or horizontally aligned with one of the vertices of the current polygon, so that they are dealt with earlier rather than later; and give the sides adjoining that vertex a higher score as candidates for punching in. You probably also want to award longer sides with higher scores as candidates for punching in.
I imagine that with a few simple weighting criteria such as these, you will quickly get some sensible results.
Finally, if you wish, you can refer back to your original set of unaveraged dots, and make further small adjustments to the shape to ensure that all those dots fall outside its boundaries.
I have points from arrays which looks like this after printing:
Points are printed based on three arrays: one with x coordinate, second with y coordinate and third with value for color .Now I need an algorith to fill space between those points. Important thing is I don't want to fill space between separate shapes. Is there any method for doing that except using concave hull (there is no implementation in c#)
edit: is it possible to somehow separate those areas and then use flood fill?
How precise do you need the algorithm to be?
If you can tolerate some imprecision (a small area around the point shapes would be selected too), you could do with a blur.
It would go like this:
1) Blur the image with a small radius (equal to half of the maximum allowed distance between the points).
2) Each pixel that has color which is precisely equal to the background color is considered "outside" (each pixel with a different color is within a small disance to one of the darker points).
There is BlueBitmapEffect in WPF, but that probably cannot be used in your scenario. You can find countless blur implementations online though.
If you need to be precise, you are out of luck in my opinion. Your goal is basically the definition of convex/concave hull.
I got points on a map and lines connecting those points.
How do I get all independent inner polygons that are formed?
The linked picture describes the problem.
http://i.imgur.com/0LdA3ji.jpg
I'm supposing I need a tree search algorithm that enumerates all the points and connecting lines in a tree structure and then searches for cycles but this job is kinda over my head.
In a perfect world the example would be in C#.)
I found:
Finding all cycles in undirected graphs
but it does not mark independent polygons. It finds all possible polygons even overlapping ones.
I'm using google maps. The use case is: I detect clicks on map and draw points. I detect click on points and then get lines between points. Now I need to automaticaly generate polygons from the lines and points. Sure I can draw polygons. I just dont know which ones (what coordinates - or rather: what points to choose for a polygon)
I actually have no experience in graphics and how to actually colour a polygon once you've found it, but assuming:
You have the polygons themselves.
They do not patialy overlap or any other weird behaviour.
Then the colouring pseudo code could go something like this:
while listOfPolygons is not empty
temp <- find smallest polygon in listOfPolygons
colour temp
remove from listOfPolygons all polygons containing temp
remove temp from listOfPolygons
Notice that the part about finding the containing polygons might be tricky.
Edit:
Checking if polygon A is in polygon B can be done by checking if any corner (vertex?) of A is located inside B.
So I am working on a Risk type game in XNA/C#. I have a map, similar this one, and I need to be able to detect mouseovers on each territory (number). If these areas were squares, it would be easy, as they could each be represented by a rectangle. However, they are different size polygons. Is there a polygon shape that behaves similar to a square? If there isn't, how would I go about doing this?
I sugest this:attach color to each number, recreate your picture in these colors: every shape will be in its particular color. Dont draw it onscreen, use it only as reference map. And when the user clicks or moves mouse over your original map, you just simply project mouse coordinates into the color map, check the color of pixel laying under the mouse and because you have each color associated to number of territory...
This is not c# specific (as I've never written anything in the language, so no idea of what apis there are), though there are 2 algorithms that come to mind for detecting if a point is inside a polygon (which can be used to detect if a mouse point is over another polygon/map shape).
One is based on raycasting, where you cast a ray in 1 direction from the (mouse) point to "infinity" (edge of the board in this case) and count the number of times it crosses the polygon's edges. If it is odd, then the point is inside the polygon, if it is even, then the point is outside of the polygon.
A wiki link to it: http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
The other algorithm that comes to mind works only for triangles I think but it can be more simple to implement I think (taking a quick glance at your shapes, I think they can easily be broken down into triangles and some are already triangles). It is to do with checking if the point is on the same (internal) "side" of all the edges in the triangle. To find out what "side" a point is on vs an edge, you'd take create 2 vectors, the first vector would be the edge itself (made up of 2 points) and the other vector would be the first point of that edge to the input point, then calculate the cross product of those 2 vectors. The result will be negative or positive, which can be used to determine the "direction".
A link to it: http://www.blackpawn.com/texts/pointinpoly/default.html
(On that page is another algorithm that can also work for triangles)
Hit testing on a polygon is not so difficult to do in real time. You could use a KD-Tree for optimisation if the map is huge. Otherwise find a simple Contains method for a polygon and use that. I have one on another computer. Let me know if you'd like it.
I'll first introduce the problem: I'm developing an application where I've to show a map field, and overlay markers and lines. However, in BlacBerry OS 5.0, the only MapField available in the API does not provide means to overlay stuff, only show the map at a location. It also provides methods to transform screen coordinates (pixels) to/from WGS84 coordinates. These methods might be computationally expensive.
So to paint my own items, I need to extend this class and override its paint() method. The extending class will also hold a collection of locations.This is how the overriden method would look like (I'll use Java here):
public void paint (Graphics g) {
super.paint(g); //draws the map
//TODO
//Draw placemarks. The placemarks are basically holder objects
//(for latitude and longitude) stored in a collection in this class.
}
However, to paint these objects in the screen we should first convert the placemark locations (lat, long) to screen coordinates (x,y in pixels). This cannot be done in advance since the map is not static, so it is able to scroll and zoom in an out. This is why in each paint loop we should paint at least THE VISIBLE OBJECTS. That said, my question is:
Given a rectangular perimeter where the corners are geographic locations (the transformed four corners of the portion of the map currently displayed), is there a fast method to loop on every placemark in the collection and determine if they are visible or not?
I don't need this test to be 100% accurate, I don't mind if a few locations outside the screen are painted. But as the placemark collection can contain many elements (< 100), and the paint method will be called on each screen repaint, trying to paint every location in the collection without checking if it is visible or not could affect performance and introduce lag when the user interacts with the map.
Before you try to provide a naive answer, notice that this is not a simple geometrical problem: We're working with geographic coordinates, not with integer screen coordinates. The world doesn't end in longitude +180, or in latitude +90. This function should work in the poles and in the ecuator, so I need it to work also when we have a transition line (from -180 to +180, or from -90 to +90, or both lines) intersecting with the rectangle. As the logic can get complex, I'd like to know if there's an existing algorithm or open source library where this has already been done and tested, rather than implementing my own one.
I could also first convert every location in the collection to screen coordinates, and then easily check against a rectangle composed only by positive screen coordinates (starting from x=0, y=0), but as the transformation functions might be expensive, I think it is better to transform only 4 points in each refresh (the visible map corners) than an indeterminate number of placemarks.
Any other approach or idea would also be appreciated.
Thanks in advance.
Just a primitive idea: Take two opposite corners of your "rectangle", e.g. the upper left one and the lower right one. Transform both corners to Cartesian space coordinate (x,y,z) by:
x = cos[long] cos[lat]
y = sin[long] cos[lat]
z = sin[lat]
Both of the (x,y,z) coordinates are unit vectors (imagine the center of the sphere being in (0,0,0), and the vectors being arrows from there to the surface). Find the "middle" of your map area as the normed average of the two corner vectors (add as vectors, then divide by length of sum vector to make sure you have a new unit vector). When you have the middle (xMiddle,yMiddle,zMiddle), for every placemark coordinate transformed into cartesian (x,y,z), use the dot product with (xMiddle,yMiddle,zMiddle) as a measure of the closeness to the middle.
Now include every placemark whose dot product with (xMiddle,yMiddle,zMiddle) is greater than the upper left corner's dot product with (xMiddle,yMiddle,zMiddle).
This should give you all placemarks inside a circular disk centered at "middle".
You could at least rule out a large number of candidates with a naive box check in map coordinate space. There are probably three main cases here. Either there's a pole is in the rectangle or there isn't. If the pole isn't visible, either the rectangle crosses the +/-180 degrees line or not. There can't be any +/-90 line, because that would put together north and south pole and you're not working with a 4D map, are you? ;-)
Case 1, a pole is visible:
If it's the north pole, figure out which of the corners has the smallest latitude. Any latitude smaller than that is likely off-screen. If it's the south pole just reverse the logic, i.e. use the largest latitude and exclude any items with a greater latitude.
I know, having the pole in one corner and the equator in another means you still include an entire hemisphere. But at least you can cheaply exclude the other half.
Case 2, no pole, not crossing the +/-180 longitude line:
Find the min/max longitude and latitude values and use those for a simple box check. Anything outside the box is off-screen.
Case 3, no pole, but crossing the +/-180 longitude line:
Same as above for latitude. For longitude, find the longitudes furthest away from +180 and -180 respectively. Exclude any items with a latitude outside the min/max or between the two furthest longitudes you found.
The cases 2 and 3 should be able to rule out enough candidates to make a brute-force check for the others feasible. Case 1 may require further post-processing, but I'm afraid that part is a bit too complicated for me if you want something sophisticated.
I suppose you could somehow find an off-screen point closest to the pole if the pole is further away from the center of the screen. Then somehow construct a triangle-like shape with one corner at that point and make it as large as possible without touching the screen rectangle.
I think you just need to Convert your rectengular perimeter to geographic coordinates.
Instead of trying to convert the geogrpahic coordinates to screen coordinates.
I'm sorry that the answer is naive - but you do you ask about logic.
And so the logical thing I visualize is a window sliding on a spehere and that means you need to have that window geographical coordinates as your points of reference.
After you process that "3d" information you can start rendering your view.