Cédric Bignon:
Let's note the Points
points of the polygon (where to Points[0] == Points[Points.Count - 1]
close the polygon).
The idea behind the next methods are to split the polygon into triangles (the area is the sum of all triangle areas). Polygon types with a simple decomposition (not only star-shaped polygon), some triangle contributions is negative (we have a "negative" area). The triangles decomposition I use are: where is the origin of the The {(O, Points[i], Points[i + 1]}
O
affine space.
The area of a non-self-intersecting polygon (in Euclidian geometry) are given by:
In:
float Getarea (list<vector2> points { float area2 = 0 ; for (int numpoint = 0 ; Numpoint < points. Count-1 ; Numpoint++ = Points[numpoint ]; MyPoint Nextpoint = points[numpoint + ]; AREA2 + = point.x * nextpoint.y-point.y * Nextpoint.x; return area2/ 2f;}
In-given normal
, the unitary normal of the polygon (which is planar):
float Getarea (list<vector3> points , Vector3 normal) {Vector3 vector = Vector3.zero; for (int numpoint = 0 ; Numpoint < points. Count-1 ; Numpoint++ = Points[numpoint ]; MyPoint Nextpoint = points[numpoint + ]; Vector += Vector3.crossproduct (point, Nextpoint); return (1f/2f) * Math.Abs ( Vector3.dotproduct (vector, Normal));}
The previous code I assumed you has a Vector3 struct with Add
,, Subtract
Multiply
, and CrossProduct
DotProduct
operations.
In the your case, you have a lattitude and longitude. Then, you is not a 2D Euclidean space. It's a spheric space where computing the area of any polygon are much more complex. However, it is locally homeomorphic to a 2D vector space (using the tangent space). Then, if the area of your try to measure are not too wide (few kilometers), the above formula should work.
Now, you just has to find the normal of the polygon. To do, and to reduce the error (because we is approximating the area), we use the normal at the centroid of the Polygo N. The centroid is given by:
Vector3 Getcentroid (list<vector3>points) {Vector3 vector=Vector3.zero; Vector3 Normal= Vector3.crossproduct (points[0], points[1]);//Gets the normal of the first triangle (it's used to know if the contribution of the triangle is positive or negative )normal = (1f/normal. Length) * normal;//makes the vector unitary floatSumprojectedareas =0; for(intNumpoint =0; Numpoint < points. Count-1; numpoint++) {MyPoint point=Points[numpoint]; MyPoint Nextpoint= Points[numpoint +1]; floatTriangleprojectedarea =vector3.dotproduct (Vector3.crossproduct (Point, Nextpoint), normal); Sumprojectedareas+=Triangleprojectedarea; Vector+ = Triangleprojectedarea * (Point +nextpoint); } return(1f/(6f * sumprojectedareas)) *Vector;}
I ' ve added a new property to Vector3
:Vector3.Length
Finally, to-convert latitude and longitude into a Vector3
:
Vector3 geographiccoordinatestopoint (floatfloat longitude) { return New Vector3 (Math.Cos (latitude) * Math.Cos (longitude), Math.Cos (latitude) * Math.sin (longitude), Math.sin ( latitude));}
To sum up:
//converts the latitude/longitude coordinates to 3D coordinatesList<vector3> pointsin3d = ( fromPointinchpointsSelectGeographiccoordinatestopoint (point. Latitude, point. Longitude)). ToList ();//Gets the centroid (to having the normal of the vector space)Vector3 centroid =getcentroid (pointsin3d);//as we are in a sphere, the normal at a given point was the colinear to the vector going from the center of the sphere to the point.Vector3 normal = (1f/centroid. Length) * centroid;//We want a unitary normal.//Finally the area is computed using:floatArea = Getarea (pointsin3d, Normal);
The Vector3
struct
Public structvector3{ Public Static ReadOnlyVector3 Zero =NewVector3 (0,0,0); Public ReadOnly floatX; Public ReadOnly floatY; Public ReadOnly floatZ; Public floatLength {returnMATH.SQRT (x * x + y * y + Z *Z); } PublicVector3 (floatXfloatYfloatz) {X=x; Y=y; Z=Z; } Public StaticVector3operator+(Vector3 vector1, Vector3 vector2) {return NewVector3 (Vector1. X + Vector2. X, Vector1. Y + Vector2. Y, Vector1. Z +Vector2. Z); } Public StaticVector3operator-(Vector3 vector1, Vector3 vector2) {return NewVector3 (Vector1. X-vector2. X, Vector1. Y-vector2. Y, Vector1. ZVector2. Z); } Public StaticVector3operator*(floatscalar, Vector3 vector) { return NewVector3 (scalar * vector. X, scalar * vector. Y, scalar *vector. Z); } Public Static floatDotProduct (Vector3 vector1, Vector3 vector2) {returnVector1. X * Vector2. X + Vector1. Y * Vector2. Y + Vector1. ZVector2. Z } Public StaticVector3 crossproduct (Vector3 vector1, Vector3 vector2) {return return NewVector3 (Vector1. Y * Vector2. Z-vector1. ZVector2. Y, Vector1. Z* Vector2. X-vector1. XVector2. Z, Vector1. X* Vector2. Y-vector1. YVector2. X); }}
Boeykes:
I fixed it with part of the code from Cédric and code from the Internet.
I fixed it by using Poly. Points and Poly. Localpoints. The Poly. Points is the latitude and longitude while the localpoints is Points see to the center of the map on the screen.
The C # Library has a function to calculate the distance (km) so I calculted the distance and then I calculated the Distanc E in localpoints. Dived the localpoints throug the length of and then you know how long 1 localpoint was in km.
List<pointlatlng> firsttwopoints =NewList<pointlatlng>(); Firsttwopoints.add (Poly. points[0]); Firsttwopoints.add (Poly. points[1]); Gmappolygon Oneline=NewGmappolygon (Firsttwopoints,"TESTESDDFSDSD");//Create New Polygone from messuring the distance. DoubleLengtelocalline =math.sqrt ((Poly. localpoints[1]. X-poly. localpoints[0]. X) * (Poly. localpoints[1]. X-poly. localpoints[0]. X)) +(Poly. localpoints[1]. Y-poly. localpoints[0]. Y) * (Poly. localpoints[1]. Y-poly. localpoints[0]. (Y)));//This calculates the length of the line in localpoints. DoublePOINTINKM = Oneline.distance/lengtelocalline;//This gives me the length of 1 localpoint in miles.List<Carthesian> Waarden =NewList<carthesian>(); //Here we fill the list "Waarden" with the points.//Note:the Last value was not copied because this is handled in calculation method. foreach(Gpoint LocalpointinchPoly. localpoints) {Waarden. ADD (NewCarthesian () {X = (Localpoint.x * pointinkm), Y = (LOCALPOINT.Y *POINTINKM)}); } MessageBox.Show (""+ Getarea (waarden) *1000000); }//Method for calculating area Private DoubleGetarea (ilist<carthesian>points) { if(Points. Count <3) { return 0; } DoubleArea = Getdeterminant (points[points. Count-1]. X, Points[points. Count-1]. Y, points[0]. X, points[0]. Y); for(inti =1; I < points. Count; i++) { //Debug.WriteLine ("Lng:" + points[i). Lng + "Lat:" + points[i]. Lat);Area + = Getdeterminant (Points[i-1]. X, Points[i-1]. Y, Points[i]. X, Points[i]. Y); } returnMath.Abs (Area/2); }//Methode for getting the determinant Private DoubleGetdeterminant (DoubleX1,DoubleY1,DoubleX2,Doubley2) { returnX1 * Y2-X2 *Y1; }//This is just-to-make it nicer-show in code and it also were from previous tries classCarthesian { Public DoubleY ZGet;Set; } Public DoubleYGet;Set; } Public DoubleZGet;Set; } }because we calculate the surfaceusingThere
Because we calculate the surface using 2D there is a small error, but for my application this is acceptable.
And thanks to Cédric for answering my question and helping me to fix the problem I had.
From:http://stackoverflow.com/questions/17775832/c-sharp-gmap-net-calculate-surface-of-polygon
C # gmap.net Compute polygon Area