/**
         * 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()));
        }
        /**
         * Constructor for PolygonArea.
         * <p>
         * @param earth the Geodesic object to use for geodesic calculations.
         * @param polyline if true that treat the points as defining a polyline
         *   instead of a polygon.
         **********************************************************************/

        public PolygonArea(Geodesic earth, bool polyline)
        {
            _earth    = earth;
            _area0    = _earth.EllipsoidArea();
            _polyline = polyline;
            _mask     = GeodesicMask.LATITUDE | GeodesicMask.LONGITUDE |
                        GeodesicMask.DISTANCE |
                        (_polyline ? GeodesicMask.NONE :
                         GeodesicMask.AREA | GeodesicMask.LONG_UNROLL);
            _perimetersum = new Accumulator(0);
            if (!_polyline)
            {
                _areasum = new Accumulator(0);
            }
            Clear();
        }
示例#3
0
 public Accumulator(Accumulator a)
 {
     _s = a._s;
     _t = a._t;
 }