Polygon Area in Bing Maps - c#

Hi I have a problem calculating the area of a polygon in Bing maps. I'm using this code to calculate area.
public static double PolygonArea(LocationCollection points, double resolution)
{
int n = points.Count;
var partialSum = 0.0;
var sum = 0.0;
for (int i = 0; i < n - 1; i++)
{
partialSum = (points[i].Longitude * points[i + 1].Latitude) -
(points[i + 1].Longitude * points[i].Latitude);
sum += partialSum;
}
var area = 0.5 * sum / Math.Pow(resolution, 2);
area = Math.Abs(area);
return area;
}
This is the resolution method
public static double Resolution(double latitude, double zoomLevel)
{
double groundResolution = Math.Cos(latitude * Math.PI / 180) *
2 * Math.PI * EARTH_RADIUS_METERS / (256 * Math.Pow(2, zoomLevel));
return groundResolution;
}
How can I trasform it in m^2?
EDIT1: I tried your answer but I noticed that area change if I change zoom level.
I try to explain my problem from another point of you. I have to make the porting of an iOS app that uses this algorithm to calculate area
-(long double)calcArea :(CLLocationCoordinate2D*) pastureCordinates :(long) count {
long double area = 0.0;
long double scale = 0.0;
for (int cnt = 1; cnt < count; cnt++) {
area += (MKMapPointForCoordinate(pastureCordinates[cnt - 1]).x)
* (MKMapPointForCoordinate(pastureCordinates[cnt]).y)
- (MKMapPointForCoordinate(pastureCordinates[cnt]).x)
* (MKMapPointForCoordinate(pastureCordinates[cnt - 1]).y);
}
area += (MKMapPointForCoordinate(pastureCordinates[count - 1]).x)
* (MKMapPointForCoordinate(pastureCordinates[0]).y)
- (MKMapPointForCoordinate(pastureCordinates[0]).x)
* (MKMapPointForCoordinate(pastureCordinates[count - 1]).y);
scale = MKMapPointsPerMeterAtLatitude(pastureCordinates[count -1].latitude);
area = (area / (long double)2) / pow(scale,2);
area = fabsl(area);
return area;
}
I used the functions found here: https://msdn.microsoft.com/en-us/library/bb259689.aspx to calculate the scale, the ground resolution but the results are different compared to the iOS solution.

Ok, I've played around with some code and put together a simple method that calculates the area fairly accurately without having to use really in-depth spatial mathematics.
private double CalculateArea(LocationCollection locs)
{
double area = 0;
for (var i = 0; i < locs.Count - 1; i++)
{
area += Math.Atan(
Math.Tan(Math.PI / 180 * (locs[i + 1].Longitude - locs[i].Longitude) / 2) *
Math.Sin(Math.PI / 180 * (locs[i + 1].Latitude + locs[i].Latitude) / 2) /
Math.Cos(Math.PI / 180 * (locs[i + 1].Latitude - locs[i].Latitude) / 2));
}
if (area < 0)
{
area *= -1;
}
return area * 2 * Math.Pow(6378137.0, 2);
}
Testing this with various polygons and comparing them to the calculated area in SQL, I found that in the worse case the difference was about 0.673% when using a ridiculously large polygon. When testing against a polygon that was about 0.5 sq KM in size, the difference was about 0.06%. Note that this method returns an area in sq meters.

Calculating the area of a polygon on a map is very complicated as the world is a sphere and you are actually trying to calculate the area of a polygon stretched on the surface of a sphere. Since you are using WPF I'd suggest to make things easy and make use of the spatial library available in SQL server. All the spatial functionalities in SQL server are available as a dll which you can use in your WPF application. You can easily use this library to calculate the area of a polygon accurately and do a lot of other really powerful things as well. To start off with, if you have SQL instelled you can find the SQL Spatial Library (Microsoft.SqlServer.Types) located in the C:\Program Files (x86)\Microsoft SQL Server\110\Shared directory. If you don't have SQL Server installed, don't worry, you don't have to install it, this library is available as a Nuget package here: https://www.nuget.org/packages/Microsoft.SqlServer.Types
Take a look at this hands on lab for information using SQL spatial tools in .NET: http://view.officeapps.live.com/op/view.aspx?src=http%3A%2F%2Fecn.channel9.msdn.com%2Fo9%2Flearn%2FSQL2008R2TrainingKit%2FLabs%2FUsingSpatialDataInManagedCode%2FLab.docx
Once you have this library you can create an SQL Geography object from your polygon. Once this is done you can then use the STArea method to calculate the area of the polygon. There is a ton of other spatial methods available as well which you can use to create a really powerful mapping application.

Related

Set zoom level to see only 3 pins in Xamarin Forms

I'm using Xamarin Forms and I'm using the Google Maps nuget for iOS and Android. I have a ListView with different places that I click to navigate to the MapPage to see the location of the place there.
Since the pins on the map are on different places I cannot set one zoom level for every location. I always want the 3 closest pins to be shown upon entering the page.
I have tried these solutions but I'm looking for a Forms solution for this problem.
LatLng marker1LatLng = new LatLng(marker1lat, marker1lng);
Latlng marker2LatLng = new LatLng(marker2lat, marker2lng);
LatLngBounds.Builder b = new LatLngBounds.Builder()
.Include(marker1LatLng)
.Include(marker2LatLng);
Also tried this but no luck:
var markers = [];//some array
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markers.length; i++) {
bounds.extend(markers[i].getPosition());
}
map.fitBounds(bounds);
How to dynamically set the zoom level depending on the lat & lon of those 3 pins that I want to be visible.
I have a total of 10 pins for each place on the map but only wanna show closest 3. Once I zoom out i wanna be able to see all 10 tho.
Thanks for all the help in advance!
First, you need to find the three closest pins to the selected location, which I assume you will want to be the center of the map. Once you find the three closest pins, calculate how far the furthest of the 3 pins is and the use the
map.MoveToRegion (MapSpan.FromCenterAndRadius (
new Position (centerLatitude,centerLongitude), Distance.FromKilometers (distanceToThirdPin)));
where centerLatitude and centerLongitude are the coordinates of the selected location that will be at the center, and distanceToThirdPin is the calculated distance (in Km) to the farthest of the 3 pins.
Formula to calculate distance between a pair of latitudes and longitudes:
double R = 6371.0; // Earth's radius
var dLat = (Math.PI / 180) * (pinLatitude - centerLatitude);
var dLon = (Math.PI / 180) * (pinLongitude - centerLongitude);
var lat1 = (Math.PI / 180) * centerLatitude;
var lat2 = (Math.PI / 180) * pinLatitude;
var a = Math.Sin(dLat/2) * Math.Sin(dLat/2) + Math.Sin(dLon/2) * Math.Sin(dLon/2) * Math.Cos(lat1) * Math.Cos(lat2);
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
var d = R * c; // distance in Km.
So use the above formula to find the distances to all of your pins, then find the three closest. Once found, use the distance to the third closest pin as the distanceToThirdPin value when you call the map.MoveToRegion method.

How to traverse mesh vertices based on their location?

I am using Point Cloud Free Viewer to visualize Point Clouds in Unity. It has a script and it parses .off files and creates meshes without triangulating. However, the code creates multiple meshes since its index format is 16bit. I modified the code for utilizing 32 bit format and i have a mesh with 2 million points:
What i want to do is creating a grid like geometry and color this point cloud based on point density. I want to find a rough volume of this point cloud by multiplying differences between max and min x,y,z values and divide this volume into equal boxes. Each of these boxes will be colored based of how many points they contain. I would be happy if someone can offer me a lead. I tried KDTree approach but it is a bit slow since i have 2 million points. I also tried sorting points before creating the mesh but it takes too much time as well. Is there a way to traverse mesh vertices based on the location without visiting all vertices considering they are indexed randomly? I believe i am looking for a solution like mesh.bounds.contains() but i do not know if a method like spatial search exists.
Not really, a full solution, more a hint towards a direction I would pursue: divide your vertex pool into smaller groups first, I.e into cubes (seperate meshes maybe), precalculate this, then you only have to search within a much smaller region, after an initial search for a set of cubes that neighbour (or touch) your region.
It sounds to me like you want an octree.
First, load all of the points into memory (2 million points really isn't that many - assuming doubles, that's 2,000,000 * 3 * 8 bytes ~= 45 MB). While you are parsing the file and loading the points into memory, record the min and max x, y, and z coordinates. You can then build your octree which bounds that volume in N*LogN. Then, for each of your grid volumes, you can very quickly query the tree to get only the points in that region. I'm pretty sure this is the most efficient way to do what you want.
I would suggest checking the quadtree article for its implementation of queryRange to see how this would be done. An octree is just a 3-d implementation of a quadtree, so the underlying code is more or less the same (with each node containing 8 children instead of 4).
For those who might visit this question later i found a really fast solution based on Nico's comment. I am traversing whole points by parsing my scan file using this script
for (int i = 0; i < numPoints; i++)
{
buffer = sr.ReadLine().Split();
points[i] = new Vector3(float.Parse(buffer[0]) , float.Parse(buffer[1]) , -float.Parse(buffer[2]) );
//Finding minX, minY, minZ
if (points[i].x < minX)
minX = points[i].x;
if (points[i].y < minY)
minY = points[i].y;
if (points[i].z < minZ)
minZ = points[i].z;
//Finding maxX, maxY, maxZ
if (points[i].x > maxX)
maxX = points[i].x;
if (points[i].y > maxY)
maxY = points[i].y;
if (points[i].z > maxZ)
maxZ = points[i].z;
}
Here is my and variables i use with itFindPointIndex function.
deltaX = maxX - minX;
deltaY = maxY - minY;
deltaZ = maxZ - minZ;
gridCountX = Mathf.CeilToInt(deltaX / gridSize);
gridCountY = Mathf.CeilToInt(deltaY / gridSize);
gridCountZ = Mathf.CeilToInt(deltaZ / gridSize);
Resolution = gridCountX * gridCountY * gridCountZ;
Histogram = new int[Resolution];
int FindPointIndex(Vector3 point)
{
//Finds the grid index of the point
int index = Mathf.FloorToInt((point.x - minX) / gridSize) + ((Mathf.FloorToInt((point.z - minZ) / gridSize)) * gridCountX)
+ Mathf.FloorToInt((point.y - minY) / gridSize) * gridCountX * gridCountZ;
if (index < 0)
{
index = 0;
}
return index;
}
Then i can traverse the points again to increment index for each of them to see how many points each grid holds like this:
for (int i = 0; i < numPoints; i++)
{
Histogram[FindPointIndex(points[i])]++;
}
At the end using this histogram i can color the point cloud with another loop.

Creating a phillotaxic sphere / hemisphere with C#?

I'm trying to follow a tutorial which is written in a math programming language I'm not familiar with and attempting to convert the tutorial to C# code for Unity 3d.
See here: http://blog.wolfram.com/2011/07/28/how-i-made-wine-glasses-from-sunflowers/
float theta = Mathf.PI * (3 - Mathf.Sqrt(5));
for (int i = 0; i < spawnPoints.Length; i++)
{
float r = (radius / 2) * Mathf.Sqrt(i) / Mathf.Sqrt(points);
float a = theta * i;
Vector3 coords = transform.TransformDirection( new Vector3(Mathf.Cos(a) * r, 0, Mathf.Sin(a) * r) )+transform.position;
spawnPoints[i] = coords;
}
This if course generates the flat phillotaxic arrangement in 2d. I'm trying to modify Y (up) axis for depth (creating the sphere).
I cannot seem to set the Y (up) axis correctly in proportion with i and radius.
Considering the tutorial above, how should I be calculating Y?
The 3D version is called a spherical Fibonacci lattice. This paper gives a nice explanation. This stackoverflow post has more links.

GPS lap & Segment timer

I've been searching for a while but haven't found exactly what I'm looking for.
I'm working on an app that will go in a race car. It will give the driver the ability to press a button to mark a Start/Finish line. It will also have a button to allow a driver to set segment times.
Keep in mind a track can be an oval which I'm working on first. It could be a road course or it could be an auto cross where the start and finish line aren't the exact same location. They could be with 50 feet of each other or so but the car never crosses where it starts.
I have my gps data coming in and I convert the NMea messages to my classes and I store Lat, Lon, Speed, Course etc. In my research I've ran across this which is interesting. The GPS will be mounted outside the roof for better signal. It generates 10 hits per second. (Garmin Glo)
http://www.drdobbs.com/windows/gps-programming-net/184405690?pgno=1
It's old but it talks about UTM and the Cartesian coordinate system. So using the DecDeg2UTM, I convert Lat & Lon to X & coordinates as well.
I've also been trying to use the Intersect formula I found Here I took the intersect and tried to convert it to C# which I'll post at the end. However, feeding coordinates of an oval track, it doesn't seem to be working. Also, I'm not sure exactly what it's supposed to be doing. But the coordinates it returns when it does somethign like -35.xxx & 98.xxxx which out in an ocean somewhere 1000's of miles from where the track is.
I looking for answers to the following.
I assume I need to take the location recorded when a button is pressed for Start/Finish or Segment and calculate a line perpendicular to the direction the car in able to be able to do some sort of Line Intersection calculation. The Cartesian coordinates seems to calculate the bearing fairly well. But the question here is how do you get the "left and right coordinates". Also, keep in mind, an oval track may be 60 feet wide. But as mentioned an auto cross track may only be 20 ft wide and part of the track may be with 50 ft. Note I'm fine with indicating to set the points, the car needs to be going slow or stopped at the points to get an accurate coordinate. Some tracks they will have to be set while walking the track.
Based on this, should I be trying to use decimal lat lon or would utilizing the Cartesian coordinate system based on UTM be a more accurate method for what I'm trying to do?
Either one is there a .Net library or C based library with source code that has methods for making these calculations?
How can this be accurately handled. (Not that great with Math, links to code samples would help tremendously.)
Next, after I have the lines or whatever is needed for start/finish and segments, as I get GPS sign from the car racing, I need to figure out the most accurate way to tell when a car has crossed those segments. again if I'm lucky I'll get 10 hits per second but it will probably be lower. Then the vehicle speeds could vary significantly depending on the type of track and vehicle. So the GPS hit could be many feet "left or right" of a segment. Also, it could be many feet before or after a segment.
Again, if there is a GIS library out there I can feed coordinates and all this is calculated, that's would work as well as long as it's performant. If not again I'm trying to decide if it's best to break down coordinates to X Y or some geometry formulas for coordinates in decimal format. Mods, I assume there is hard data to support an answer of either way and this isn't responses aren't fully subjective to opinions.
Here is the C# code I came up with from the Script page above. I'm starting to feel UTM and the Cartesian Coordinate system would be better for accuracy and performance. But again I'm open to evidence to the contrary if it exists.
Thanks
P.S. Note GeoCoordinate is from the .Net System.Device.Location assemble. GpsData is just a class I use to convert NMEA messages into Lat, Lon, Course, NumSats, DateTime etc.
The degree Radian methods are extensions as as follows.
public static double DegreeToRadians(this double angle)
{
return Math.PI * angle / 180.0;
}
public static double RadianToDegree(this double angle)
{
return angle * (180.0 / Math.PI);
}
}
public static GeoCoordinate CalculateIntersection(GpsData p1, double brng1, GpsData p2, double brng2)
{
// see http://williams.best.vwh.net/avform.htm#Intersection
// Not sure I need to use Cosine
double _p1LatRadians = p1.Latitude.DegreeToRadians();
double _p1LonToRadians = p1.Longitude.DegreeToRadians();
double _p2LatToRadians = p2.Latitude.DegreeToRadians();
double _p2LonToRadians = p2.Longitude.DegreeToRadians();
double _brng1ToRadians = brng1.DegreeToRadians();
double _brng2ToRadians = brng2.DegreeToRadians();
double _deltaLat = _p2LatToRadians - _p1LatRadians;
double _deltaLon = _p2LonToRadians - _p1LonToRadians;
var _var1 = 2 * Math.Asin(Math.Sqrt(Math.Sin(_deltaLat / 2) * Math.Sin(_deltaLat / 2)
+ Math.Cos(_p1LatRadians) * Math.Cos(_p2LatToRadians) * Math.Sin(_deltaLon / 2) * Math.Sin(_deltaLon / 2)));
if (_var1 == 0) return null;
// initial/final bearings between points
var _finalBrng = Math.Acos((Math.Sin(_p2LatToRadians) - Math.Sin(_p1LatRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p1LatRadians)));
//if (isNaN(θa)) θa = 0; // protect against rounding
var θb = Math.Acos((Math.Sin(_p1LatRadians) - Math.Sin(_p2LatToRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p2LatToRadians)));
var θ12 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? _finalBrng : 2 * Math.PI - _finalBrng;
var θ21 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? 2 * Math.PI - θb : θb;
var α1 = (_brng1ToRadians - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3
var α2 = (θ21 - _brng2ToRadians + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3
if (Math.Sin(α1) == 0 && Math.Sin(α2) == 0) return null; // infinite intersections
if (Math.Sin(α1) * Math.Sin(α2) < 0) return null; // ambiguous intersection
α1 = Math.Abs(α1);
α2 = Math.Abs(α2);
// ... Ed Williams takes abs of α1/α2, but seems to break calculation?
var α3 = Math.Acos(-Math.Cos(α1) * Math.Cos(α2) + Math.Sin(α1) * Math.Sin(α2) * Math.Cos(_var1));
var δ13 = Math.Atan2(Math.Sin(_var1) * Math.Sin(α1) * Math.Sin(α2), Math.Cos(α2) + Math.Cos(α1) * Math.Cos(α3));
var _finalLatRadians = Math.Asin(Math.Sin(_p1LatRadians) * Math.Cos(δ13) + Math.Cos(_p1LatRadians) * Math.Sin(δ13) * Math.Cos(_brng1ToRadians));
var _lonBearing = Math.Atan2(Math.Sin(_brng1ToRadians) * Math.Sin(δ13) * Math.Cos(_p1LatRadians), Math.Cos(δ13) - Math.Sin(_p1LatRadians) * Math.Sin(_finalLatRadians));
var _finalLon = _p1LonToRadians + _lonBearing;
var _returnLat = _finalLatRadians.RadianToDegree();
var _latToDegree = _finalLon.RadianToDegree();
var _returnLon = ( _latToDegree + 540) % 360 - 180;
return new GeoCoordinate(_returnLat, _returnLon);
//return new LatLon(φ3.toDegrees(), (λ3.toDegrees() + 540) % 360 - 180); // normalise to −180..+180°
}

Kinect: Calculate head's pitch, yaw, roll angles

I am trying to use Kinect sensor and SDK to calculate the orientation of user's head but I wasn't able to find any good help for this on google. Does anybody have any good sample, tutorial or something like that that might help me?
I think that I have found a solution although it's limited, it works only if the Kinect SDK can detect the face since I'm using the FaceTrackFrame object.
If somebody finds a solution to track more extreme angles when Kinect SDK is unable to detect a face I'd be more then happy to see it.
My solution looks something like this:
FaceTrackFrame faceFrame = faceTracker.Track(
kinectSensor.ColorStream.Format, colorPixelData,
kinectSensor.DepthStream.Format, depthPixelData, skeleton);
// Only works if face is detected
if (faceFrame.TrackSuccessful)
{
txtTracked.Content = "TRACKED";
txtRoll.Content = faceFrame.Rotation.Z;
txtPitch.Content = faceFrame.Rotation.X;
txtYaw.Content = faceFrame.Rotation.Y;
}
I managed to calculate these manually using the depth data from the image.
First you need to get the depth point
private EnumIndexableCollection<FeaturePoint, Vector3DF> depthPoints;
Then if you look at the FaceTracking viewer code that comes with the SDK and search for the DrawFaceModel function. You can extract the code like this in the 1st for loop.
faceModelPts3D.Add(new Point3D(this.depthPoints[i].X + 0.5f, this.depthPoints[i].Y + 0.5f, this.depthPoints[i].Z + 0.5f));
FaceDataPoints.DepthXPointInfo[i] = this.depthPoints[i].X;
FaceDataPoints.DepthYPointInfo[i] = this.depthPoints[i].Y;
FaceDataPoints.DepthZPointInfo[i] = this.depthPoints[i].Z;
I then placed point 0 and point 9 into the following function to obtain the Pitch. I then put the Points 120 and 116 in to obtain the yawn angle.
public static double FacePitch(double FirstXPos, double FirstYPos, double FirstZPos, double SecXPos, double SecYPos, double SecZPos)
{
double PitchAngle = 0;
double r = 0;
double XDifference, YDifference, ZDifference = 0;
double DifferenceSquared = 0;
XDifference = FirstXPos - SecXPos;//Calculates distance from Points
YDifference = FirstYPos - SecYPos;
ZDifference = FirstZPos - SecZPos;
DifferenceSquared = Math.Pow(XDifference, 2) + Math.Pow(YDifference, 2) + Math.Pow(ZDifference, 2);
r = Math.Sqrt(DifferenceSquared);
PitchAngle = (Math.Acos(ZDifference / r));
PitchAngle = ((PitchAngle * 180 / Math.PI) - 90) * -1; //Converts to Degrees as easier to recognise visually
return PitchAngle;
}
for the roll i placed point 0 and 9 in again and used the above function again But i changed
PitchAngle = (Math.Acos(ZDifference / r));
to
RollAngle = Math.Acos(XDifference / r);

Categories

Resources