/** * Return the results so far. * <p> * @param reverse if true then clockwise (instead of counter-clockwise) * traversal counts as a positive area. * @param sign if true then return a signed result for the area if * the polygon is traversed in the "wrong" direction instead of returning * the area for the rest of the earth. * @return PolygonResult(<i>num</i>, <i>perimeter</i>, <i>area</i>) where * <i>num</i> is the number of vertices, <i>perimeter</i> is the perimeter * of the polygon or the length of the polyline (meters), and <i>area</i> * is the area of the polygon (meters<sup>2</sup>) or Double.NaN of * <i>polyline</i> is true in the constructor. * <p> * More points can be added to the polygon after this call. **********************************************************************/ public PolygonResult Compute(bool reverse, bool sign) { if (_num < 2) { return(new PolygonResult(_num, 0, _polyline ? Double.NaN : 0)); } if (_polyline) { return(new PolygonResult(_num, _perimetersum.Sum(), Double.NaN)); } GeodesicData g = _earth.Inverse(_lat1, _lon1, _lat0, _lon0, _mask); Accumulator tempsum = new Accumulator(_areasum); tempsum.Add(g.GeodesicScale12); int crossings = _crossings + Transit(_lon1, _lon0); if ((crossings & 1) != 0) { tempsum.Add((tempsum.Sum() < 0 ? 1 : -1) * _area0 / 2); } // area is with the clockwise sense. If !reverse convert to // counter-clockwise convention. if (!reverse) { tempsum.Negate(); } // If sign put area in (-area0/2, area0/2], else put area in [0, area0) if (sign) { if (tempsum.Sum() > _area0 / 2) { tempsum.Add(-_area0); } else if (tempsum.Sum() <= -_area0 / 2) { tempsum.Add(+_area0); } } else { if (tempsum.Sum() >= _area0) { tempsum.Add(-_area0); } else if (tempsum.Sum() < 0) { tempsum.Add(+_area0); } } return (new PolygonResult(_num, _perimetersum.Sum(g.Distance), 0 + tempsum.Sum())); }
/** * Return the results assuming a tentative final test point is added; * however, the data for the test point is not saved. This lets you report * a running result for the perimeter and area as the user moves the mouse * cursor. Ordinary floating point arithmetic is used to accumulate the * data for the test point; thus the area and perimeter returned are less * accurate than if AddPoint and Compute are used. * <p> * @param lat the latitude of the test point (degrees). * @param lon the longitude of the test point (degrees). * @param reverse if true then clockwise (instead of counter-clockwise) * traversal counts as a positive area. * @param sign if true then return a signed result for the area if * the polygon is traversed in the "wrong" direction instead of returning * the area for the rest of the earth. * @return PolygonResult(<i>num</i>, <i>perimeter</i>, <i>area</i>) where * <i>num</i> is the number of vertices, <i>perimeter</i> is the perimeter * of the polygon or the length of the polyline (meters), and <i>area</i> * is the area of the polygon (meters<sup>2</sup>) or Double.NaN of * <i>polyline</i> is true in the constructor. * <p> * <i>lat</i> should be in the range [−90°, 90°]. **********************************************************************/ public PolygonResult TestPoint(double lat, double lon, bool reverse, bool sign) { if (_num == 0) { return(new PolygonResult(1, 0, _polyline ? Double.NaN : 0)); } double perimeter = _perimetersum.Sum(); double tempsum = _polyline ? 0 : _areasum.Sum(); int crossings = _crossings; int num = _num + 1; for (int i = 0; i < (_polyline ? 1 : 2); ++i) { GeodesicData g = _earth.Inverse(i == 0 ? _lat1 : lat, i == 0 ? _lon1 : lon, i != 0 ? _lat0 : lat, i != 0 ? _lon0 : lon, _mask); perimeter += g.Distance; if (!_polyline) { tempsum += g.GeodesicScale12; crossings += Transit(i == 0 ? _lon1 : lon, i != 0 ? _lon0 : lon); } } if (_polyline) { return(new PolygonResult(num, perimeter, Double.NaN)); } if ((crossings & 1) != 0) { tempsum += (tempsum < 0 ? 1 : -1) * _area0 / 2; } // area is with the clockwise sense. If !reverse convert to // counter-clockwise convention. if (!reverse) { tempsum *= -1; } // If sign put area in (-area0/2, area0/2], else put area in [0, area0) if (sign) { if (tempsum > _area0 / 2) { tempsum -= _area0; } else if (tempsum <= -_area0 / 2) { tempsum += _area0; } } else { if (tempsum >= _area0) { tempsum -= _area0; } else if (tempsum < 0) { tempsum += _area0; } } return(new PolygonResult(num, perimeter, 0 + tempsum)); }