Example #1
0
        /**
         * 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()));
        }
Example #2
0
        /**
         * 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 [&minus;90&deg;, 90&deg;].
         **********************************************************************/

        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));
        }