1 """Define the :class:`~geographiclib.polygonarea.PolygonArea` class 3 The constructor initializes a empty polygon. The available methods are 5 * :meth:`~geographiclib.polygonarea.PolygonArea.Clear` reset the 7 * :meth:`~geographiclib.polygonarea.PolygonArea.AddPoint` add a vertex 9 * :meth:`~geographiclib.polygonarea.PolygonArea.AddEdge` add an edge 11 * :meth:`~geographiclib.polygonarea.PolygonArea.Compute` compute the 12 properties of the polygon 13 * :meth:`~geographiclib.polygonarea.PolygonArea.TestPoint` compute the 14 properties of the polygon with a tentative additional vertex 15 * :meth:`~geographiclib.polygonarea.PolygonArea.TestEdge` compute the 16 properties of the polygon with a tentative additional edge 18 The public attributes for this class are 20 * :attr:`~geographiclib.polygonarea.PolygonArea.earth` 21 :attr:`~geographiclib.polygonarea.PolygonArea.polyline` 22 :attr:`~geographiclib.polygonarea.PolygonArea.area0` 23 :attr:`~geographiclib.polygonarea.PolygonArea.num` 24 :attr:`~geographiclib.polygonarea.PolygonArea.lat1` 25 :attr:`~geographiclib.polygonarea.PolygonArea.lon1` 52 """Area of a geodesic polygon""" 55 """Count crossings of prime meridian for AddPoint.""" 59 lon1 = Math.AngNormalize(lon1)
60 lon2 = Math.AngNormalize(lon2)
61 lon12, _ = Math.AngDiff(lon1, lon2)
62 cross = (1
if lon1 <= 0
and lon2 > 0
and lon12 > 0
63 else (-1
if lon2 <= 0
and lon1 > 0
and lon12 < 0
else 0))
68 """Count crossings of prime meridian for AddEdge.""" 73 lon1 = math.fmod(lon1, 720.0); lon2 = math.fmod(lon2, 720.0)
74 return ( (0
if ((lon2 >= 0
and lon2 < 360)
or lon2 < -360)
else 1) -
75 (0
if ((lon1 >= 0
and lon1 < 360)
or lon1 < -360)
else 1) )
79 """Construct a PolygonArea object 81 :param earth: a :class:`~geographiclib.geodesic.Geodesic` object 82 :param polyline: if true, treat object as a polyline instead of a polygon 84 Initially the polygon has no vertices. 89 """The geodesic object (readonly)""" 91 """Is this a polyline? (readonly)""" 92 self.
area0 = 4 * math.pi * earth._c2
93 """The total area of the ellipsoid in meter^2 (readonly)""" 94 self.
_mask = (Geodesic.LATITUDE | Geodesic.LONGITUDE |
96 (Geodesic.EMPTY
if self.
polyline else 97 Geodesic.AREA | Geodesic.LONG_UNROLL))
101 """The current number of points in the polygon (readonly)""" 103 """The current latitude in degrees (readonly)""" 105 """The current longitude in degrees (readonly)""" 109 """Reset to empty polygon.""" 112 if not self.
polyline: self._areasum.Set(0)
113 self._perimetersum.Set(0)
117 """Add the next vertex to the polygon 119 :param lat: the latitude of the point in degrees 120 :param lon: the longitude of the point in degrees 122 This adds an edge from the current vertex to the new vertex. 129 _, s12, _, _, _, _, _, _, _, S12 = self.earth._GenInverse(
131 self._perimetersum.Add(s12)
133 self._areasum.Add(S12)
140 """Add the next edge to the polygon 142 :param azi: the azimuth at the current the point in degrees 143 :param s: the length of the edge in meters 145 This specifies the new vertex in terms of the edge from the current 151 _, lat, lon, _, _, _, _, _, S12 = self.earth._GenDirect(
153 self._perimetersum.Add(s)
155 self._areasum.Add(S12)
162 def Compute(self, reverse = False, sign = True):
163 """Compute the properties of the polygon 165 :param reverse: if true then clockwise (instead of 166 counter-clockwise) traversal counts as a positive area 167 :param sign: if true then return a signed result for the area if the 168 polygon is traversed in the "wrong" direction instead of returning 169 the area for the rest of the earth 170 :return: a tuple of number, perimeter (meters), area (meters^2) 172 If the object is a polygon (and not a polygon), the perimeter 173 includes the length of a final edge connecting the current point to 174 the initial point. If the object is a polyline, then area is nan. 176 More points can be added to the polygon after this call. 183 return self.
num, perimeter, area
186 perimeter = self._perimetersum.Sum()
187 return self.
num, perimeter, area
189 _, s12, _, _, _, _, _, _, _, S12 = self.earth._GenInverse(
191 perimeter = self._perimetersum.Sum(s12)
196 tempsum.Add( (1
if tempsum.Sum() < 0
else -1) * self.
area0/2 )
199 if not reverse: tempsum.Negate()
202 if tempsum.Sum() > self.
area0/2:
203 tempsum.Add( -self.
area0 )
204 elif tempsum.Sum() <= -self.
area0/2:
205 tempsum.Add( self.
area0 )
207 if tempsum.Sum() >= self.
area0:
208 tempsum.Add( -self.
area0 )
209 elif tempsum.Sum() < 0:
210 tempsum.Add( self.
area0 )
212 area = 0.0 + tempsum.Sum()
213 return self.
num, perimeter, area
216 def TestPoint(self, lat, lon, reverse = False, sign = True):
217 """Compute the properties for a tentative additional vertex 219 :param lat: the latitude of the point in degrees 220 :param lon: the longitude of the point in degrees 221 :param reverse: if true then clockwise (instead of 222 counter-clockwise) traversal counts as a positive area 223 :param sign: if true then return a signed result for the area if the 224 polygon is traversed in the "wrong" direction instead of returning 225 the area for the rest of the earth 226 :return: a tuple of number, perimeter (meters), area (meters^2) 233 return 1, perimeter, area
235 perimeter = self._perimetersum.Sum()
236 tempsum = 0.0
if self.
polyline else self._areasum.Sum()
238 for i
in ([0]
if self.
polyline else [0, 1]):
239 _, s12, _, _, _, _, _, _, _, S12 = self.earth._GenInverse(
240 self.
lat1 if i == 0
else lat, self.
lon1 if i == 0
else lon,
241 self.
_lat0 if i != 0
else lat, self.
_lon0 if i != 0
else lon,
246 crossings += PolygonArea._transit(self.
lon1 if i == 0
else lon,
247 self.
_lon0 if i != 0
else lon)
250 return num, perimeter, area
253 tempsum += (1
if tempsum < 0
else -1) * self.
area0/2
256 if not reverse: tempsum *= -1
259 if tempsum > self.
area0/2:
260 tempsum -= self.
area0 261 elif tempsum <= -self.
area0/2:
262 tempsum += self.
area0 264 if tempsum >= self.
area0:
265 tempsum -= self.
area0 267 tempsum += self.
area0 270 return num, perimeter, area
273 def TestEdge(self, azi, s, reverse = False, sign = True):
274 """Compute the properties for a tentative additional edge 276 :param azi: the azimuth at the current the point in degrees 277 :param s: the length of the edge in meters 278 :param reverse: if true then clockwise (instead of 279 counter-clockwise) traversal counts as a positive area 280 :param sign: if true then return a signed result for the area if the 281 polygon is traversed in the "wrong" direction instead of returning 282 the area for the rest of the earth 283 :return: a tuple of number, perimeter (meters), area (meters^2) 288 return 0, Math.nan, Math.nan
290 perimeter = self._perimetersum.Sum() + s
292 return num, perimeter, Math.nan
294 tempsum = self._areasum.Sum()
296 _, lat, lon, _, _, _, _, _, S12 = self.earth._GenDirect(
299 crossings += PolygonArea._transitdirect(self.
lon1, lon)
300 _, s12, _, _, _, _, _, _, _, S12 = self.earth._GenInverse(
304 crossings += PolygonArea._transit(lon, self.
_lon0)
307 tempsum += (1
if tempsum < 0
else -1) * self.
area0/2
310 if not reverse: tempsum *= -1
313 if tempsum > self.
area0/2:
314 tempsum -= self.
area0 315 elif tempsum <= -self.
area0/2:
316 tempsum += self.
area0 318 if tempsum >= self.
area0:
319 tempsum -= self.
area0 321 tempsum += self.
area0 324 return num, perimeter, area
def Compute(self, reverse=False, sign=True)
def TestPoint(self, lat, lon, reverse=False, sign=True)
def AddPoint(self, lat, lon)
def TestEdge(self, azi, s, reverse=False, sign=True)
def __init__(self, earth, polyline=False)
def AddEdge(self, azi, s)