I have an array of simple strings (simple meaning 1-4 words, not in complete sentences) that I want to distribute "evenly" within an arbitrary shape.
By "evenly" I mean that the text does whatever it can to not overlap other text, but all the strings aren't bunched up in one particular location. I don't mean that the text has to be the max distance from eachother, I just want to fill the space as best as I can.
Example:
I have the following array:
var array = new [] {"#WhatIDidLastWeek", "Salena Gomez", "#WWF", "#IThinkOomf", "CES" };
and I have a circle of radius 600px that I want every string in the array to be inside that circle and be spaced far enough appart that they don't overlap and that the general shape of the circle is apparent.
The first thing that comes to mind is to use some sort of MeasureString call in whatever environment you're working with.
The basic idea is measure each word to see if it will fit in the allotted space. If it doesn't fit, move it down to the next "line". The hard part will be what to do when you run out of space to fit all the words.
Related
I have some photos of white pages with some black points drawn on, like this:
photo (the points aren't very circular, I can draw them better),
and I would find the coordinates of these points.
I can binarize the images (the previous photo binarized: image), but how can I find the coordinates of these black points? I need only the coordinates of one pixel for each point, the approximate center.
This is for a school assignment.
Since its for school work I will only provide you with a high level algorithm.
Since the background is guarantee to be white, you are in luck.
First you need to define a threshold on the level black which you want to consider as the black dot's color.
#ffffff is pure white and #000000 is pure black. I would suggest some where like #383838 to be your threshold.
Then you make a two dimensional bool array to keep track of which pixel you have visited already.
Now we can start looking at the picture.
You read the pixel one at the time horizontally and see if the pixel is > threshold. If yes then you do a DFS or BFS to find the entire area where the pixel's neighbor is also > threshold.
During the process you will be marking the bool array we created earlier to indicate that you have already visited the pixel.
since its a circle point you can just take the min, max of x and y coordinate and calculate the center point.
Once you are done with one point you would keep looping thru the picture's pixel and find the points that you have not visited (false in the bool array)
Since the points you have on the photo contains some small dots on the edge which is not connected to the large point, you might have to do some math to see if the radius is > some number to consider that a valid point. Or instead of a radius 1 neighbor you do a 5 - 10 pixel neighbor BFS/DFS to include the ones that are really close to the main point.
The basics for processing image data can be found in other questions, so I won't go into deeper detail about that, but for the threshold check specifically, I'd do it by gathering the red, green and blue bytes of each pixel (as indicated in the answer I linked), and then just combine them to a Color c = Color.FromArgb(r,g,b) and testing that to be "dark" using c.GetBrightness() < brightnessThreshold. A value of 0.4 was a good threshold for your test image.
You should store the result of this threshold detection in an array in which each item is a value that indicates whether the threshold check passed or failed. This means you can use something as simple as a two-dimensional Boolean array with the original image's height and width.
If you already have methods of doing all that, all the better. Just make sure you got some kind of array in which you can easily look up the result of that binarization. If the method you have gives you the result as image, you will be more likely to end up with a simple one-dimensional byte array, but then your lookups will simply be of a format like imagedata[y * stride + x]. This is functionally identical to how internal lookups in a two-dimensional array happen, so it won't be any less efficient.
Now, the real stuff in here, as I said in my comment, would be an algorithm to detect which pixels should be grouped together to one "blob".
The general usage of this algorithm is to loop over every single pixel on the image, then check if A) it cleared the threshold, and B) it isn't already in one of your existing detected blobs. If the pixel qualifies, generate a new list of all threshold-passed pixels connected to this one, and add that new list to your list of detected blobs. I used the Point class to collect coordinates, making each of my blobs a List<Point>, and my collection of blobs a List<List<Point>>.
As for the algorithm itself, what you do is make two collections of points. One is the full collection of neighbouring points you're building up (the points list), the other is the current edge you're scanning (the current edge list). The current edge list will start out containing your origin point, and the following steps will loop as long as there are items in your current edge list:
Add all items from the current edge list into the full points list.
Make a new collection for your next edge (the next edge list).
For each point in your current edge list, get a list of its directly neighbouring points (excluding any that would fall outside the image bounds), and check for all of these points if they clear the threshold, and if they are not already in either the points list or the next edge list. Add the points that pass the checks to the next edge list.
After this loop through the current edge list ends, replace the original current edge list by the next edge list.
...and, as I said, loop these steps as long as your current edge list after this last step is not empty.
This will create an edge that expands until it matches all threshold-clearing pixels, and will add them all to the list. Eventually, as all neighbouring pixels end up in the main list, the new generated edge list will become empty, and the algorithm will end. Then you add your new points list to the list of blobs, and any pixels you loop over after that can be detected as already being in those blobs, so the algorithm is not repeated for them.
There are two ways of doing the neighbouring points; you either get the four points around it, or all eight. The difference is that using four will not make the algorithm do diagonal jumps, while using eight will. (An added effect is that one causes the algorithm to expand in a diamond shape, while the other expands in a square.) Since you seem to have some stray pixels around your blobs, I advise you to get all eight.
As Steve pointed out in his answer, a very quick way of doing checks to see if a point is present in a collection is to create a two-dimensional Boolean array with the dimensions of the image, e.g. Boolean[,] inBlob = new Boolean[height, width];, which you keep synchronized with the actual points list. So whenever you add a point, you also mark the [y, x] position in the Boolean array as true. This will make rather heavy checks of the if (collection.contains(point)) type as simple as if (inBlob[y,x]), which requires no iterations at all.
I had a List<Boolean[,]> inBlobs which I kept synced with the List<List<Point>> blobs I built, and in the expanding-edge algorithm I kept such a Boolean[,] for both the next edge list and the points list (the latter of which was added to inBlobs at the end).
As I commented, once you have your blobs, just loop over the points inside them per blob and get the minimums and maximums for both X and Y, so you end up with the boundaries of the blob. Then just take the averages of those to get the center of the blob.
Extras:
If all your dots are guaranteed to be a significant distance apart, a very easy way to get rid of floating edge pixels is to take the edge boundaries of each blob, expand them all by a certain threshold (I took 2 pixels for that), and then loop over these rectangles and check if any intersect, and merge those that do. The Rectangle class has both an IntersectsWith() for easy checks, and a static Rectangle.Inflate for increasing a rectangle's size.
You can optimise the memory usage of the fill method by only storing the edge points (threshold-matching points with non-matching neighbours in any of the four main directions) in the main list. The final boundaries, and thus the center, will remain the same. The important thing to remember then is that, while you exclude a bunch of points from the blob list, you should mark all of them in the Boolean[,] array that's used for checking the already-processed pixels. This doesn't take up any extra memory anyway.
The full algorithm, including optimisations, in action on your photo, using 0.4 as brightness threshold:
Blue are the detected blobs, red is the detected outline (by using the memory-optimised method), and the single green pixels indicate the center points of all blobs.
[Edit]
Since it's been almost a year since I posted this, I guess I might as well link to the implementation I made of this. I actually managed to use it myself about a month after I wrote it, when recreating the video compression algorithm of an old DOS game which used chunked up diff frames.
This might be a weird application.
The brief description of the problem is "How to get Absolute Coordination of nodes based on Relative Positions (distances) ?"
We have a number of Nodes (each with a unique ID) and a list specifying its Adjacent nodes and distance to each of them as Input.
The required output would be one possible way to lay out these nodes on a 2D Surface.
The resulting algorithm is going to be used in C#... So external .net libraries might help too.
It would be a great help if you could advise me an approach to do that.
Thank you in advance.
You must have coordinates of at least three known points at start.
Way I. If the known points are adjacent, the process is simple - you loop all your points, looking for such, which have in their lists three known points. Use two of them to count two possible positions, then use the third to choose right or left variant. Repeat the loops until you have no new points during a loop.
That simple algorithm has bad convergence - the errors are accumulating and far points could have bad coordinates. But as you have the coordinates integer, you can repair coords after each counting and have them good.
Way II. If the known points are not adjacent to each other, the process is more complicated.
Let's say, you have start known points A,B,C.
Take A and some its adjacent point D. Place it somewhere at the correct distance from A.
Find some point E adjacent to A and D. Choose any of two possible positions.
Starting from A, D, E, use the way I.
When you reach by distances the second start known point, let it be B, of course, it will be in bad place. Turn all the net you have built around A so, that B will get the correct coordinates. Continue the looping.
When you will reach the last of the start known points, C, it will be set correct or not. If not, mirror the whole net relatively AB axis - the C will be set correctly. (If not, you have bad data). Continue the way I looping till the end.
Both these two ways work if you have long lists for all points. If points have only few distances given, the task becomes much, much more complicated.
I have a series of Lat/Long points in a SQL Server database. I would like to be able to find shapes. By that I mean if in the mess of coordinates there are 8 coordinates making a perfect circle, or 7 coordinates making a triangle I would like to know.
I'd be surprised if there is already something out there which does this already, especially in C# (the language I'm using). But My question is really, how should I approach this?
I probably have 200k, but their timestamped, so I should only be working with maybe 1k at a time...
What you're trying to do is called least squares fitting.
Basically, you pick a shape. Let's pick a straight line for now.
You calculate the sum of the squares of the offsets ("the residuals") of the points from the line. You do this with different lines until you've minimized the sum of the squares.
I have no idea how you would automate this for several types of shapes.
You need to find a library, or develop your self, a way to calculate Least Squares over shapes.
If the error margin is over a threshold level of R2 then you do not have that "Shape". You will need to define a formula for the shape you test against (For example a circle: x2+y2=r2).
For things that do not have curves (triangle,square, ect.) it will be harder to do as they do not have a "Formula". You can use the least square for finding each side of the shape for a line (y=mX+b) and then building those lines together to make shapes.
Given an elevation map consisting of lat/lon/elevation pairs, what is the fastest way to find all points above a given elevation level (or better yet, just the the 2D concave hull)?
I'm working on a GIS app where I need to render an overlay on top of a map to visually indicate regions that are of higher elevation; it's determining this polygon/region that has me stumped (for now). I have a simple array of lat/lon/elevation pairs (more specifically, the GTOPO30 DEM files), but I'm free to transform that into any data structure that you would suggest.
We've been pointed toward Triangulated Irregular Networks (TINs), but I'm not sure how to efficiently query that data once we've generated the TIN. I wouldn't be surprised if our problem could be solved similarly to how one would generate a contour map, but I don't have any experience with it. Any suggestions would be awesome.
It sounds like you're attempting to create a polygonal representation of the boundary of the high land.
If you're working with raster data (sampled on a rectangular grid), try this.
Think of your grid as an assembly of right triangles.
Let's say you have a 3x3 grid of points
a b c
d e f
g h k
Your triangles are:
abd part of the rectangle abed
bde the other part of the rectangle abed
bef part of the rectangle bcfe
cef the other part of the rectangle bcfe
dge ... and so on
Your algorithm has these steps.
Build a list of triangles that are above the elevation threshold.
Take the union of these triangles to make a polygonal area.
Determine the boundary of the polygon.
If necessary, smooth the polygon boundary to make your layer look ok when displayed.
If you're trying to generate good looking contour lines, step 4 is very hard to to right.
Step 1 is the key to this problem.
For each triangle, if all three vertices are above the threshold, include the whole triangle in your list. If all are below, forget about the triangle. If some vertices are above and others below, split your triangle into three by adding new vertices that lie precisely on the elevation line (by interpolating elevation). Include the one or two of those new triangles in your highland list.
For the rest of the steps you'll need a decent 2d geometry processing library.
If your points are not on a regular grid, start by using the Delaunay algorithm (which you can look up) to organize your pointss in into triangles. Then follow the same algorith I mentioned above. Warning. This is going to look kind of sketchy if you don't have many points.
Assuming you have the lat/lon/elevation data stored in an array (or three separate arrays) you should be able to use array querying techniques to select all of the points where the elevation is above a certain threshold. For example, in python with numpy you can do:
indices = where(array > value)
And the indices variable will contain the indices of all elements of array greater than the threshold value. Similar commands are available in various other languages (for example IDL has the WHERE() command, and similar things can be done in Matlab).
Once you've got this list of indices you could create a new binary array where each place where the threshold was satisfied is set to 1:
binary_array[indices] = 1
(Assuming you've created a blank array of the same size as your original lat/long/elevation and called it binary_array.
If you're working with raster data (which I would recommend for this type of work), you may find that you can simply overlay this array on a map and get a nice set of regions appearing. However, if you need to convert the areas above the elevation threshold to vector polygons then you could use one of many inbuilt GIS methods to convert raster->vector.
I would use a nested C-squares arrangement, with each square having a pre-calculated maximum ground height. This would allow me to scan at a high level, discarding any squares where the max height is not above the search height, and drilling further into those squares where parts of the ground were above the search height.
If you're working to various set levels of search height, you could precalculate the convex hull for the various predefined levels for the smallest squares that you decide to use (or all the squares, for that matter.)
I'm not sure whether your lat/lon/alt points are on a regular grid or not, but if not, perhaps they could be interpolated to represent even 100' ft altitude increments, and uniform
lat/lon divisions (bearing in mind that that does not give uniform distance divisions). But if that would work, why not precompute a three dimensional array, where the indices represent altitude, latitude, and longitude respectively. Then when the aircraft needs data about points at or above an altitude, for a specific piece of terrain, the code only needs to read out a small part of the data in this array, which is indexed to make contiguous "voxels" contiguous in the indexing scheme.
Of course, the increments in longitude would not have to be uniform: if uniform distances are required, the same scheme would work, but the indexes for longitude would point to a nonuniformly spaced set of longitudes.
I don't think there would be any faster way of searching this data.
It's not clear from your question if the set of points is static and you need to find what points are above a given elevation many times, or if you only need to do the query once.
The easiest solution is to just store the points in an array, sorted by elevation. Finding all points in a certain elevation range is just binary search, and you only need to sort once.
If you only need to do the query once, just do a linear search through the array in the order you got it. Building a fancier data structure from the array is going to be O(n) anyway, so you won't get better results by complicating things.
If you have some other requirements, like say you need to efficiently list all points inside some rectangle the user is viewing, or that points can be added or deleted at runtime, then a different data structure might be better. Presumably some sort of tree or grid.
If all you care about is rendering, you can perform this very efficiently using graphics hardware, and there is no need to use a fancy data structure at all, you can just send triangles to the GPU and have it kill fragments above or below a certain elevation.
Is there an algorithm ( preferably in C# implementation) that allows me to compare how similar two lines are? In my case I have one reference line, and I have a lot of secondary lines, I need to choose, out of so many secondary lines, which is the closest to the reference line.
Edit: It is a 2D line, with start and stop points. When you compare the similarities, you to take into account of the full blown line. The direction of the line ( i.e., whether it's from left to right or vice versa) is not important. And yes, it has to do with how close it is from one another
I know this is kind of subjective ( the similarity, not the question), but still, I am sure there are people who have done work on this.
Obvious metrics include slope, length, and distance between midpoints. You could calculate those and then find weightings that you like.
If you want to kind of wrap them all up into one thing, try the sum of the distances between the endpoints.
You're going to have to try a few things and see which cases irritate you and then figure out why.
lines (and in general hyperplanes) sit on an object call Grassmanian; e.g. lines in the plane sit in Gr(1,3), which is isomorphic to the 2-dimensional projective space, and yours is the simplest non trivial one: Gr(2,4). It is a compact metric space, which comes with a standard metric (arising from the plucker embedding - see the link above). However, this metric is a little expensive to compute, so you may want to consider an approximation (just as you'd consider using dot product instead of angle in 2 dimensions - it works find for small angles)
A more detailed explantion (based in the metric defined in the linked wikipedia article):
For each line l take two points (x1,y1,z1) and (x2,y2,z2) on it. Let A be the 4 by 2 matrix whose columns are (1,x1,y1,z1)^t and (1,x2,y2,z2)^t. Define P to be the 4 by 4 matrix
A(A^tA)^(-1)A^t. Then P is dependent only on l and not of the choice of the two points.
The metric you want is the absolute value of the top eigen value of the difference between the matrices corresponding to the two lines.
If you are talking about lines in the graphical sense, then I would look at a combination of things like line length and angle.
Depending on your situation, you may be able to make optimizations such as using the square of the length (saves a square root) and dy/dx for angle (saves a trig function, but watch for the divide-by-zero case).