ThinkGeo.com    |     Documentation    |     Premium Support

GetArea on Buffered shape not working as expected

If I draw a point and put a buffer around it, and then get the area of the buffer, the number is off. 


A simplistic example:

Plot point with 1 meter buffer and get area in square meters.  Since Area = pi*r^2 the area should be 3.14159, however:


map.MapUnit = GeographyUnit.DecimalDegree;



PointShape pointShape = new PointShape(0, 0);

MultipolygonShape areaShape = pointShape.Buffer(1.0, GeographyUnit.DecimalDegree, DistanceUnit.Meter);

double area = areaShape.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters);





area = 3.11880780371074



What's going on?



Ryan,


Thanks for your post and interests in MapSuite products, welcome you to ThinkGeo Mapsuite Destkop discussion forum.
 
I think there are 2 factors affects the result:
1) The caculation precision.
When we store a buffered shape, we did not buffer it into a real circle, instead , we buffer it into a PolygonShape very similar to a shape. So when we caculate the area, it will cause some difference with a real circle.
 
2) The Unit problem.
When a circle in DecimalDegree unit in fact it sill cause minor difference because of the geography difference.
 
You can try following code :

PointShape pointShape = new PointShape(0, 0);
MultipolygonShape areaShape = pointShape.Buffer(1.0, GeographyUnit.Meter, DistanceUnit.Meter);
double area = areaShape.GetArea(GeographyUnit.Meter, AreaUnit.SquareMeters);

 
It will gives out a more accuarte result : 3.1214451522580511.
 
Any more questions just feel free to let me know.
 
Thanks.
 
Yale

Yale, 
  
 I think my simplistic example was too simplistic.  If the point is farther away from (0, 0) the result gets worse.   
  
 map.MapUnit = GeographyUnit.DecimalDegree; 
  
 PointShape pointShape = new PointShape(-90.0, 45.0); 
 MultipolygonShape areaShape = pointShape.Buffer(1.0, GeographyUnit.DecimalDegree, DistanceUnit.Meter); 
 double area = areaShape.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters); 
  
  
 area = 4.4106603115797 
  
 The area of a circle shouldn’t change no matter where you are on the earth.

Ryan, 
  
 As I understanding, the drawn circle in the earth surface( MapUnit is Decimal degrees) will be not a real circle, especially far away from Equator, because every unit of decimal degree will get different distance in meter when in different latitudes. 
  
 So, you buffered the point shape into 1 decimaldegres while it probabally returns back a ellipse(in Meter unit) when very far away from the equator. 
  
 I am not a GIS specilist, may be I am not exaly right. 
  
 Any more questions or suggestions just feel free to let me know. 
  
 Thanks. 
  
 Yale 


Yale, 
  
 Yes, as you get away from the equator 1 decimal degree will correspond to a varying number of meters.  However, in my example, I am not buffering 1 decimal degree around a point, I am buffering one meter around a point.  A meter is a meter no matter where you are on the earth.  So, no matter where you are on the earth, the area of a one meter radius circle should be 3.14 sq meters (or very close to due to rounding).  3.12 sq meters is an acceptable answer, 4.41 is not.  Also, I tried doing this is in a GIS software, where the map was in decimal degrees (Latitude/Longitude projection); I buffered out a meter and got the expected ~3.14 answer. 
  
 Ryan

Ryan,


I agree wit you that no matter the lattitude of the point is, it should not vary greatly with a real circle.
 
While the current caculation will vary greatly depends on the latitude, following is the result:
Longtitude:-50 Latitude:0 Area:3.12144509331493
Longtitude:-50 Latitude:10 Area:3.16959842652893
Longtitude:-50 Latitude:45 Area:4.41439003507996
Longtitude:-50 Latitude:80 Area:17.9756853692017
Longtitude:-50 Latitude:90 Area:337717886.061048
Longtitude:-50 Latitude:-80 Area:17.9756853302002
 
The reason is hidden in the Buffer logic. We use the NTS as the background buffer logic, which has no any idea about the DecimalDegrees, so our rule is simplified. We just use the point latitude(Y value) as its radius in DecimalDegree and buffer it into a “circle”, this will obsolutely make difference with 0 based latitude buffered circle.
 
I know that in your descritpion case, the buffered polygon should not be a circle, it should be an ellipse or a very complicated polygon, up to now, we do not provide a built in logic for this precised caculation.
 
Sorry for the inconvinience now.
 
Thanks.
 
Yale

Guys, 
  
   I spoke with one of the guys here internally and he is going to post the exact reason why you are seeing this.  He told me that it has to do with the "circle" of a buffered point not being a circle at all and being an ellipse.  In any event he is going to post a complete explanation.  I expect to see it here tomorrow.  He is also going to show a technique to get a circle back fro the buffer that will comply with the pie result. 
  
 David

A meter is a meter on a planar system. When you are dealing with decimal degrees, it is a lot trickier. What is happening when you are buffering a point is that you are getting a MultiPolygonShape as a circle. This means that the vertical and horizontal radius is the same in decimal degrees but it also means consequently that the actual distances of the two radiuses in meter are different. That explains why you are getting a different value than 3.14 when getting the area. The horizontal radius is 1 meter but the vertical radius is more than that even though they have the same values in decimal degrees. We took the decision to return the result of the buffer operation on a point as a circle because to most people (who are not aware of those decimal degrees intricacies) it would be confusing to see a flattened ellipse.


 


-So from your code you get the following shape:


PointShape pointShape = new PointShape(-90.0, 45.0);

MultipolygonShape areaShape = pointShape.Buffer(1, GeographyUnit.DecimalDegree, DistanceUnit.Meter);


double area = areaShape.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters);


area is different from 3.14


Radiuses of equal decimal degrees values but different meter values.


 



 


 


-Now, if you want to buffer a point consistently in meter, use the following code:


 double latDiff = DecimalDegreesHelper.GetLatitudeDifferenceFromDistance(1, DistanceUnit.Meter, -90);

 double longDiff = DecimalDegreesHelper.GetLongitudeDifferenceFromDistance(1, DistanceUnit.Meter, 45);



  EllipseShape ellipseShape1 = new EllipseShape(pointShape, longDiff, latDiff);

  double area1 = ellipseShape1.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters);


area1 is equal to 3.14


But visually, you will get the following shape:


Radiuses of different decimal degrees values but equal meter values.



 



I was assuming that if I buffer by 1 meter that you intrenally projected the geometry so that you got a true polygonized circle, no matter where the circle was on the face of the world.    You are not doing that? 
  
 What about when you report the area?   Do you not project to a local cartesian system and return the true cartesian area?       
  
 I have not used the ThnkGeo methods because I had previously written my own NTS methods that transparently project as described above, but I was thinking about abandoning those methods in favor of a full commitment to your objects.    I guess I need to be sure how this is working before I make that commitment. 
  
 Thanks.

To me, the described default behavior is undesirable.  If I say “buffer out 1 meter from this point”, I really want to buffer out 1 meter from this point.  I don’t want to buffer out something that just looks pretty.  I am doing actual calculations that are dependent on the area of the calculated buffer.  Your solution is fine, but IMHO the default behavior is confusing and inaccurate.  Perhaps, if one of the DistanceUnit options was DecimalDegree, the described behavior would be warranted.

David & Val, 
  
 Thanks for your help on the explainations. 
  
 Ted, I don’t think we do any projection(while we did do some math conversions between Plannar system to spherial system) during the caculations. 
  
 Any more questions just feel free to let me know. 
  
 Thanks. 
  
 Yale 


Guys,  
  
  I understand your doubts about getting accurate measurements (areas and distances) when the map is in decimal degrees and I see where their might be some confusions about using Map Suite API. Today, I am working on giving a clear background  with some concrete examples. This afternoon, I will post my full answer.

Guys, 
  
   We are also open to suggestions on this as well.  The main thing is we need to get out in the open what it is doing and get pros and cons as to how we did it.   
  
 David









  MapSuite offers all the tools to get accurate measurements of area, distance. The issue for the developer is to understand how to use those tools according to what is desired. 


 


I am going to take a very concrete example using a Polygon because that shape is a good example for later understanding the overall concept underneath the seemingly simple task of getting the area of an ellipse. 


 


Let’s say that you have a polygon representing a field with GPS readings for its vertices. (I am using a polygon roughly in the same area as the circle used in this post). You need to plot the polygon on the map which is in decimal degrees. But you also have the need to get accurate measurements of the area of the polygon.


 


First, you create the Polygon with its vertices in decimal degrees.


 


PolygonShape polygonShape = new PolygonShape();


polygonShape.OuterRing.Vertices.Add(new Vertex(-90.0036, 45.0016));


polygonShape.OuterRing.Vertices.Add(new Vertex(-89.9966, 45.0011));


polygonShape.OuterRing.Vertices.Add(new Vertex(-89.9951, 44.9978));


polygonShape.OuterRing.Vertices.Add(new Vertex(-89.9990,44.9956));


polygonShape.OuterRing.Vertices.Add(new Vertex(-90.0040,44.9975));


polygonShape.OuterRing.Vertices.Add(new Vertex(-90.0036,45.0016));


 


When you display it on the Map in decimal degrees, it looks like that:


 



 










 


Now, you want to get the area of this polygon. Map Suite offers an API to get the area of a polygon GetArea. The first parameter is for passing the GeographyUnit. It can be in meters, feet or decimal degrees according to the unit your shape is in. (It turns out that only meters, feet and decimal degrees are used). If the unit is in meters or feet, the math used for calculating distances and areas is straightforward. It is the geometry used on a planar system.


On the other hand, if the unit is decimal degrees, we cannot use the planar geometry because basically decimal degrees are angles from the center of sphere. See picture below:


 



 







<object
classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id=ieooui>

st1\:*{behavior:url(#ieooui) }




So, we have to use spherical geometry based on a sphere of an average radius for the earth. In the case of our polygon, you would get the following result:


 


double polygonAreaGeo = polygonShape.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters);


 


The area is equal to 336,752 square meters.


 


 


While this API gives a convenient way to have an idea of the area, you have to be aware that doing spherical geometry on a sphere of that size is inherently not going to be very accurate 


 


To have a more accurate measurement of the area, you would have to project the polygon to the local projection that is best fit for the geographic area. A local projection is better for accurate measurement than decimal degrees because it uses parameters specific for that area such as reference spheroid, datum, origin latitude, longitude etc. I don’t have the time here to explain about projections but you can check it out at en.wikipedia.org/wiki/Map_projection


 


Now, different projections have different characteristics and one projection may be better fit then another based on what you really care. Do you want a projection that preserves shapes and angles? Then you may want to use UTM. Or do you want a projection specifically designed for preserving areas? Then, you may want to use State Plane which has been specifically designed for surveying.


 


In your case, what you care about is area, so I would use State Plane. The polygon is in <st1:place w:st="on">Wisconsin</st1:place> central zone. So I will apply the polygon to that projection to get a more accurate area measurements. For your convenience, I created the following function that takes a shape, the projection it is in, the geography unit (meters or feet) and the area unit for the result:


 


private double GetArea(AreaBaseShape areaBaseShape, Proj4Projection proj4, GeographyUnit projectionUnit, AreaUnit areaUnit )


{


   double result = 0;


   proj4.Open();


   AreaBaseShape projAreaBaseShape = (AreaBaseShape)proj4.ConvertToExternalProjection(areaBaseShape);


   result = projAreaBaseShape.GetArea(projectionUnit, areaUnit);


   proj4.Close();


   return result;


}


 


So for that polygon to get the most accurate area, I would use the stateplane projection for Central <st1:place w:st="on">Wisconsin</st1:place> spatialreference.org/ref/esri/102753/


 


Proj4Projection StatePlaneProj4 = new Proj4Projection();


StatePlaneProj4.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);


StatePlaneProj4.ExternalProjectionParametersString = Proj4Projection.GetEsriParametersString(102753);//unit in Feet     


 


double polygonAreaStatePlane = GetArea(polygonShape,StatePlaneProj4, GeographyUnit.Feet, AreaUnit.SquareMeters);


 


The result is 337,889 square meters.


 


Now let see what is the area given in UTM, that part of <st1:state w:st="on"><st1:place w:st="on">Wisconsin</st1:place></st1:state> is in zone 16. spatialreference.org/ref/epsg/26916/


 


 


Proj4Projection UTMProj4 = new Proj4Projection();


             UTMProj4.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);


             UTMProj4.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(26916);


 


double polygonAreaUTM = GetArea(polygonShape,UTMProj4, GeographyUnit.Meter, AreaUnit.SquareMeters);


 


The result is 338,123 square meters.


 


I would trust more the result from the State Plane projection if you compare the characteristics of StatePlane with UTM.


 


en.wikipedia.org/wiki/State_plane


en.wikipedia.org/wiki/Univer...ate_system


 


Using the method Of course, you can get the area of  the polygon in  any other projections.


 


 


Now, for a circle, it is a case a little bit particular because of a way it is defined as opposed to a polygon. A polygon is defined by a series of vertices. A circle is defined by a center and a radius. 


A radius cannot be projected. In that case, I think that sincerely the approach to adopt is to ignore projection and to create a circle in meters with a center at a location that does not matter and just use it for getting the area.


 


For displaying it, as I explain in the previous post, you can create the Ellipse in the two different ways:


 


-As circle:


 


PointShape pointShape = new PointShape(-90.0, 45.0);

MultipolygonShape areaShape = pointShape.Buffer(1, GeographyUnit.DecimalDegree, DistanceUnit.Meter);


 


 


 


As an Ellipse:


 


 double latDiff = DecimalDegreesHelper.GetLatitudeDifferenceFromDistance(1, DistanceUnit.Meter, -90);

 double longDiff = DecimalDegreesHelper.GetLongitudeDifferenceFromDistance(1, DistanceUnit.Meter, 45);



  EllipseShape ellipseShape1 = new EllipseShape(pointShape, longDiff, latDiff);

  double area1 = ellipseShape1.GetArea(GeographyUnit.DecimalDegree, AreaUnit.SquareMeters);


 


 


  You will notice that many GIS packages and the OGS do not deal at all with circle and deals only with polygons for area shapes. We offer that shape in the API as a convenient way to create ellipse but that comes at a price in adding complexity in dealing with projection. 


 


I hope that this gave a better understand of what the issues are with dealing with calulating areas when dealing with polygons and circles on a map in decimal degrees.






Val, 
  
 Thank you for your thorough explanation. 
  
 Ryan

Val, 
  
   Thanks for the explanation as well.  I remember the first time I asked about getting the center of a possible multi-polygon, I thought it was straight forward question.  You asked if I wanted the weighted center, equidistant center, center of mass, center of envelope, did the center have to be inside one of the polygons, (and on and on) …  I realized then it was a much bigger world than I had imagined.   
  
 David