operations with Spatial data from Google Maps in SQL Server 2008 r2 - c#

How can i store a rectangle - consisting of 2 points NorthEast and SouthWest each point is a coordinate of lattitude and longitude
And add a circle consisting of a center ( lat-lng ) and a radius (int/float value)
what is the best way to store and later on query if a lat-lng is within the bounds of a any circle or rectangle ?
also , can i store an array of those ? say 10 rectangles and 5 circles in a single record ?
Can i use Nhibernate to ease the pain?
Sorry if this seems noobish , i have never done anything with spatial data and i don't even have clue from where to start.
Any samples and pointers are helpful !
Thanks in advance.

Here's how I would approach this problem using TSQL.
For a rectangle, the simplest method is to extrapolate the extra 2 points by using the relevant coordinates from the original points. e.g.
NorthEast (lat1, lon1) NorthWest* (lat1, lon2)
SouthEast* (lat2, lon1) SouthWest (lat2, lon2)
*New point
That doesn't give you a true rectangle (in a mathematical sense) but it's a common method in GIS (it's how geohashes are formed) what you get is a rough rectangle with varying size based on the distance from the equator. If you need an extact rectangle of a certain height/width you should look into using the Haversine formula to calculate the remaining 2 points, that will take into account bearing, and great circle distance.
http://www.movable-type.co.uk/scripts/latlong.html
To store the rectangle, I'd create a SQL table with a GEOGRAPHY type column, this will allow you assign additional attributes (e.g. name) along with a spatial index that will make future queries much faster.
CREATE TABLE dbo.geographies
(
NAME VARCHAR(50)
,GEOG GEOGRAPHY
)
INSERT INTO dbo.geographies (NAME, GEOG)
VALUES ('Rectangle', geography::STPolyFromText('POLYGON((lon1 lat1, lon2 lat1, lon2 lat2, lon1 lat2, lon1 lat1))', 4326))
Note that both the first point and the last point are the same, this is required to 'close' the polygon, and the final number denotes the SRID, or coordinate system, in this case WGS84. You can reference this page: http://msdn.microsoft.com/en-us/library/bb933971
As to the circle, it's simple to store a point and then use the radius to apply a buffer around the point:
INSERT INTO dbo.geographies (NAME, GEOG)
VALUES ('Circle with Radius', geography::STPointFromText('POINT(lon lat)', 4326).STBuffer([radius]))
Note that the buffer takes its input in meters so you may need to apply a conversion, more notes on this page: http://msdn.microsoft.com/en-us/library/bb933979
Now the fun part, it's quite easy to check for intersection on a point using the STIntersects
method.
http://msdn.microsoft.com/en-us/library/bb933962.aspx
DECLARE #point GEOGRAPHY = geography::STPointFromText('POINT(lon lat)', 4326)
SELECT * FROM dbo.geographies
WHERE #point.STIntersects(GEOG) = 1
The code sample takes a point and returns a list of all the geographies that the point is found within. It's important the the SRIDs of the new point and the geographies in the table match, otherwise you'll get zero matches (and probably pound you head against a wall for a while until you realize your mistake, at least, that's what I do).
As to integrating this with C#, I'm not sure how much help I can be, but it shouldn't be too much of a challenge to return the SQLGeography type
http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.aspx
Hopefully this at least points you in the right direction.

Related

Input a geographic coordinate, return a coordinate within x miles of that inputted coordinate - C# .NET

As the title suggests, I am trying to generate a coordinate based on another coordinate that is within an x mile (or whichever unit is most convenient) radius of the inputted one.
As an example:
I am given a geographic coordinate (lat, lon) of 39.083056, -94.820200.
I want to be returned another set of coordinates that is within a x
miles radius of that coordinate, such as 39.110998, -94.799668.
The x mile radius isn't as important as the fact that the returned
coordinates are within that x mile radius.
I have searched and searched, but I must be searching the wrong thing because all the posts that I have been able to find seem like they get very close to what I am trying to do but aren't quite hitting the nail on the head.
I'm sorry you're being downvoted to oblivion. I understand it can be frustrating trying to search for something without knowing what exactly to search for.
You may be interested in Orthodromic Lines/Distances: wiki. If this answer doesn't fulfil your needs, at least you have a new term to google and hopefully will lead you to one that does suit.
You could try using the Geo library. Its documentation is on the sparse side, but it does contain a method that could be useful to you: CalculateOrthodromicLine(startPoint, heading, distance)
A pseudocode would be something as simple as this:
var startPoint = new Coordinate(lat, long);
var heading = Random between 0 and 360 degrees
var distance = Random between 0 and X metres
var endPoint = //<-- et voila!
GeoContext.Current.GeodeticCalculator
.CalculateOrthodromicLine(startPoint, heading, distance)
.Coordinate2;
Edit: As mentioned in the wiki, the Earth is not a perfect sphere, but a spheroid instead. The library's GeoContext.Current by default uses its Spheroid calculations, so you should be okay.
Good luck!

How can you stitch multiple heightmaps together to remove seams?

I am trying to write an algorithm (in c#) that will stitch two or more unrelated heightmaps together so there is no visible seam between the maps. Basically I want to mimic the functionality found on this page :
http://www.bundysoft.com/wiki/doku.php?id=tutorials:l3dt:stitching_heightmaps
(You can just look at the pictures to get the gist of what I'm talking about)
I also want to be able to take a single heightmap and alter it so it can be tiled, in order to create an endless world (All of this is for use in Unity3d). However, if I can stitch multiple heightmaps together, I should be able to easily modify the algorithm to act on a single heightmap, so I am not worried about this part.
Any kind of guidance would be appreciated, as I have searched and searched for a solution without success. Just a simple nudge in the right direction would be greatly appreciated! I understand that many image manipulation techniques can be applied to heightmaps, but have been unable to find a image processing algorithm that produces the results I'm looking for. For instance, image stitching appears to only work for images that have overlapping fields of view, which is not the case with unrelated heightmaps.
Would utilizing a FFT low pass filter in some way work, or would that only be useful in generating a single tileable heightmap?
Because the algorithm is to be used in Unit3d, any c# code will have to be confined to .Net 3.5, as I believe that's the latest version Unity uses.
Thanks for any help!
Okay, seems I was on the right track with my previous attempts at solving this problem. My initial attemp at stitching the heightmaps together involved the following steps for each point on the heightmap:
1) Find the average between a point on the heightmap and its opposite point. The opposite point is simply the first point reflected across either the x axis (if stitching horizontal edges) or the z axis (for the vertical edges).
2) Find the new height for the point using the following formula:
newHeight = oldHeight + (average - oldHeight)*((maxDistance-distance)/maxDistance);
Where distance is the distance from the point on the heightmap to the nearest horizontal or vertical edge (depending on which edge you want to stitch). Any point with a distance less than maxDistance (which is an adjustable value that effects how much of the terrain is altered) is adjusted based on this formula.
That was the old formula, and while it produced really nice results for most of the terrain, it was creating noticeable lines in the areas between the region of altered heightmap points and the region of unaltered heightmap points. I realized almost immediately that this was occurring because the slope of the altered regions was too steep in comparison to the unaltered regions, thus creating a noticeable contrast between the two. Unfortunately, I went about solving this issue the wrong way, looking for solutions on how to blur or smooth the contrasting regions together to remove the line.
After very little success with smoothing techniques, I decided to try and reduce the slope of the altered region, in the hope that it would better blend with the slope of the unaltered region. I am happy to report that this has improved my stitching algorithm greatly, removing 99% of the lines reported above.
The main culprit from the old formula was this part:
(maxDistance-distance)/maxDistance
which was producing a value between 0 and 1 linearly based on the distance of the point to the nearest edge. As the distance between the heightmap points and the edge increased, the heightmap points would utilize less and less of the average (as defined above), and shift more and more towards their original values. This linear interpolation was the cause of the too step slope, but luckily I found a built in method in the Mathf class of Unity's API that allows for quadratic (I believe cubic) interpolation. This is the SmoothStep Method.
Using this method (I believe a similar method can be found in the Xna framework found here), the change in how much of the average is used in determining a heightmap value becomes very severe in middle distances, but that severity lessens exponentially the closer the distance gets to maxDistance, creating a less severe slope that better blends with the slope of the unaltered region. The new forumla looks something like this:
//Using Mathf - Unity only?
float weight = Mathf.SmoothStep(1f, 0f, distance/maxDistance);
//Using XNA
float weight = MathHelper.SmoothStep(1f, 0f, distance/maxDistance);
//If you can't use either of the two methods above
float input = distance/maxDistance;
float weight = 1f + (-1f)*(3f*(float)Math.Pow(input, 2f) - 2f*(float)Math.Pow(input, 3f));
//Then calculate the new height using this weight
newHeight = oldHeight + (average - oldHeight)*weight;
There may be even better interpolation methods that produce better stitching. I will certainly update this question if I find such a method, so anyone else looking to do heightmap stitching can find the information they need. Kudos to rincewound for being on the right track with linear interpolation!
What is done in the images you posted looks a lot like simple linear interpolation to me.
So basically: You take two images (Left, Right) and define a stitching region. For linear interpolation you could take the leftmost pixel of the left image (in the stitching region) and the rightmost pixel of the right image (also in the stitching region). Then you fill the space in between with interpolated values.
Take this example - I'm using a single line here to show the idea:
Left = [11,11,11,10,10,10,10]
Right= [01,01,01,01,02,02,02]
Lets say our overlap is 4 pixels wide:
Left = [11,11,11,10,10,10,10]
Right= [01,01,01,01,02,02,02]
^ ^ ^ ^ overlap/stitiching region.
The leftmost value of the left image would be 10
The rightmost value of the right image would be 1.
Now we interpolate linearly between 10 and 1 in 2 steps, our new stitching region looks as follows
stitch = [10, 07, 04, 01]
We end up with the following stitched line:
line = [11,11,11,10,07,04,01,02,02,02]
If you apply this to two complete images you should get a result similar to what you posted before.

Check if coordinate is within area

I got a real-estate facing problem.
I've got a real-world address that I'm converting to earth coordinates (such as "London Eye" to "-0.119543;51.503324").
I also got a perimeter or area within I'm going to search (for example "10" is "10 km").
Now I got a bunch of coordinates (totally random around the earth) and I want to check if the current coordinate is within 10km of the coordinates of the london eye.
Is there any solution to this or maybe am I even facing a x-y-problem?
You could use the Haversine Formula to calculate the distance between two points:
http://www.stormconsultancy.co.uk/blog/development/code-snippets/the-haversine-formula-in-c-and-sql/
Nearest GPS coordinate based on distance from a given point
However for speed I think you need to calculate max/min longitude and latitude values (i.e a square around the London Eye) as this will be a lot quicker to calculate if there are lots of points to check. Then use the Haversine formula on this small subset of points (within your square) to find those within 10km.
It seems like this could help you:
http://www.doogal.co.uk/dotnetcoords.php
It is based on http://www.jstott.me.uk/jcoord, which allows distance calculation between points. Don't take my word for it though, haven't used either.
There is a well known solution to the problem. Haversine_formula
I think you can also search for C# code for the same. Hope it helps.

Efficiently remove points with same slope

In one of mine applications I am dealing with graphics objects. I am using open source GPC library to clip/merge two shapes. To improve accuracy I am sampling (adding multiple points between two edges) existing shapes. But before displaying back the merged shape I need to remove all the points between two edges.
But I am not able to find an efficient algorithm that will remove all points between two edges which has same slope with minimum CPU utilization. Currently all points are of type
PointF
I am calculating slope using following function
private float Slope(PointF point1, PointF point2)
{
return (point2.Y - point1.Y) / (point2.X - point1.X);
}
Any pointer on this will be a great help.
What algorithm are you currently using? I can think only of going through all point and for each 3 to check wherher middle point is on vector (or close to) defined by 2 other points.
Do you need math for that operation?
Just to be clear, you have three points A = (a,b), C = (c,d), and E = (e,f), and are wondering if the segment AE goes through C and thus you can replace the pair of segments AC and CE with the single segment AE?
slope AC = (d-b)/(c-a) = slope CE = (f-d)/(e-c)
multiply through by the denominators, you get
(d-b)(e-c) = (f-d)(c-a)
that's just four subtracts, two multiplies, and a compare. You'll need to do the comparison with some error tolerance due to the use of floating point.
Well.. I found the solution for my question. Instead of using Sampling method provided by SDK, I created my own sampling method which insert a point between two points at a fixed distance. This reduces the number of point that I need to process and in turn reducing processor usage.

How to find a random point in a quadrangle?

I have to be able to set a random location for a waypoint for a flight sim. The maths challenge is straightforward:
"To find a single random location within a quadrangle, where there's an equal chance of the point being at any location."
Visually like this:
An example ABCD quadrangle is:
A:[21417.78 37105.97]
B:[38197.32 24009.74]
C:[1364.19 2455.54]
D:[1227.77 37378.81]
Thanks in advance for any help you can provide. :-)
EDIT
Thanks all for your replies. I'll be taking a look at this at the weekend and will award the accepted answer then. BTW I should have mentioned that the quadrangle can be CONVEX OR CONCAVE. Sry 'bout dat.
Split your quadrangle into two triangles and then use this excellent SO answer to quickly find a random point in one of them.
Update:
Borrowing this great link from Akusete on picking a random point in a triangle.
(from MathWorld - A Wolfram Web Resource: wolfram.com)
Given a triangle with one vertex at
the origin and the others at positions v1
and v2, pick
(from MathWorld - A Wolfram Web Resource: wolfram.com)
where A1
and A2 are uniform
variates in the interval [0,1] , which gives
points uniformly distributed in a
quadrilateral (left figure). The
points not in the triangle interior
can then either be discarded, or
transformed into the corresponding
point inside the triangle (right
figure).
I believe there are two suitable ways to solve this problem.
The first mentioned by other posters is to find the smallest bounding box that encloses the rectangle, then generate points in that box until you find a point which lies inside the rectangle.
Find Bounding box (x,y,width, height)
Pick Random Point x1,y1 with ranges [x to x+width] and [y to y+height]
while (x1 or y1 is no inside the quadrangle){
Select new x1,y1
}
Assuming your quadrangle area is Q and the bounding box is A, the probability that you would need to generate N pairs of points is 1-(Q/A)^N, which approaches 0 inverse exponentially.
I would reccommend the above approach, espesially in two dimensions. It is very fast to generate the points and test.
If you wanted a gaurentee of termination, then you can create an algorithm to only generate points within the quadrangle (easy) but you must ensure the probablity distribution of the points are even thoughout the quadrangle.
http://mathworld.wolfram.com/TrianglePointPicking.html
Gives a very good explination
The "brute force" approach is simply to loop through until you have a valid coordinate. In pseudocode:
left = min(pa.x, pb.x, pc.x, pd.x)
right = max(pa.x, pb.x, pc.x, pd.x)
bottom = min(pa.y, pb.y, pc.y, pd.y)
top = max(pa.y, pb.y, pc.y, pd.y)
do {
x = left + fmod(rand, right-left)
y = bottom + fmod(rand, top-bottom)
} while (!isin(x, y, pa, pb, pc, pd));
You can use a stock function pulled from the net for "isin". I realize that this isn't the fastest-executing thing in the world, but I think it'll work.
So, this time tackling how to figure out if a point is within the quad:
The four edges can be expressed as lines in y = mx + b form. Check if the point is above or below each of the four lines, and taken together you can figure out if it's inside or outside.
Are you allowed to just repeatedly try anywhere within the rectangle which bounds the quadrangle, until you get something within the quad? Might this even be faster than some fancy algorithm to ensure that you pick something within the quad?
Incidentally, in that problem statement, I think the use of the word "find" is confusing. You can't really find a random value that satisfies a condition; the randomizer just gives it to you. What you're trying to do is set parameters on the randomizer to give you values matching certain criteria.
I would divide your quadrangle into multiple figures, where each figure is a regular polygon with one side (or both sides) parallel to one of the axes. For eg, for the figure above, I would first find the maximum rectangle that fits inside the quadrangle, the rectangle has to be parallel to the X/Y axes. Then in the remaining area, I would fit triangles, such triangles will be adjacent to each side of the rectangle.
then it is simple to write a function:
1) get a figure at random.
2) find a random point in the figure.
If the figure chosen in #1 is a rectangle, it should be pretty easy to find a random point in it. The tricky part is to write a routine which can find a random point inside the triangle
You may randomly create points in a bound-in-box only stopping after you find one that it's inside your polygon.
So:
Find the box that contains all the points of your polygon.
Create a random point inside the bounds of the previously box found. Use random functions to generate x and y values.
Check if that point is inside the polygon (See how here or here)
If that point is inside the polygon stop, you're done, if not go to step 2
So, it depends on how you want your distribution.
If you want the points randomly sampled in your 2d view space, then Jacob's answer is great. If you want the points to be sort of like a perspective view (in your example image, more density in top right than bottom left), then you can use bilinear interpolation.
Bilinear interpolation is pretty easy. Generate two random numbers s and t in the range [0..1]. Then if your input points are p0,p1,p2,p3 the bilinear interpolation is:
bilerp(s,t) = t*(s*p3+(1-s)*p2) + (1-t)*(s*p1+(1-s)*p0)
The main difference is whether you want your distribution to be uniform in your 2d space (Jacob's method) or uniform in parameter space.
This is an interesting problem and there's probably as really interesting answer, but in case you just want it to work, let me offer you something simple.
Here's the algorithm:
Pick a random point that is within the rectangle that bounds the quadrangle.
If it is not within the quadrangle (or whatever shape), repeat.
Profit!
edit
I updated the first step to mention the bounding box, per Bart K.'s suggestion.

Categories

Resources