예제 #1
0
        /// <summary>
        /// Add an edge to the polygon or polyline.
        /// </summary>
        /// <param name="g">The geod_geodesic object specifying the ellipsoid.</param>
        /// <param name="p">The geod_polygon object specifying the polygon.</param>
        /// <param name="azi">The azimuth at current point (degrees).</param>
        /// <param name="s">The distance from current point to next point (meters).</param>
        /// <remarks>
        /// g and p must have been initialized with calls to geod_init() and
        /// geod_polygon_init(), respectively. The same g must be used for all the
        /// points and edges in a polygon. azi should be in the range
        /// [-540deg, 540deg). This does nothing if no points have been
        /// added yet. The lat and lon fields of p give the location of
        /// the new vertex.
        /// </remarks>
        public void geod_polygon_addedge(geod_geodesic g, double azi, double s)
        {
            if (num != 0)
            {             // Do nothing is num is zero
                double lat, lon, S12 = 0, dummy;
                if (polyline)
                {
                    g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE | GEOD.LONGITUDE, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out dummy);
                }
                else
                {
                    g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE | GEOD.LONGITUDE | GEOD.AREA, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);
                }

                accadd(P, s);
                if (!polyline)
                {
                    accadd(A, S12);
                    crossings += transitdirect(this.lon, lon);
                }
                this.lat = lat; this.lon = lon;
                ++num;
            }
        }
예제 #2
0
        /// <summary>
        /// Return the results assuming a tentative final test point is added via an
        /// azimuth and distance; 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 geod_polygon_addedge() and
        /// geod_polygon_compute() are used.
        /// </summary>
        /// <param name="g">The geod_geodesic object specifying the ellipsoid.</param>
        /// <param name="p">The geod_polygon object specifying the polygon.</param>
        /// <param name="azi">The azimuth at current point (degrees).</param>
        /// <param name="s">The distance from current point to final test point (meters).</param>
        /// <param name="reverse">If set <b>true</b> then clockwise (instead of counter-clockwise)
        /// traversal counts as a positive area.</param>
        /// <param name="sign">If set <b>true</b> 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.</param>
        /// <param name="pA">The area of the polygon (square meters); only set if polyline is set <b>true</b>
        /// in the call to geod_polygon_init().</param>
        /// <param name="pP">The perimeter of the polygon or length of the polyline (meters).</param>
        /// <returns>The number of points.</returns>
        /// <remarks>
        /// azi should be in the range [-540deg, 540deg).
        /// </remarks>
        public int geod_polygon_testedge(geod_geodesic g, double azi, double s, bool reverse, bool sign, out double pA, out double pP)
        {
            pP = pA = NaN;

            int num = this.num + 1;

            if (num == 1)
            {
                return(0);                   // we don't have a starting point!
            }
            double perimeter = P[0] + s;

            if (polyline)
            {
                pP = perimeter;
                return(num);
            }

            double tempsum   = A[0];
            int    crossings = this.crossings;

            {
                double lat, lon, s12, S12, dummy;
                g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE | GEOD.LONGITUDE | GEOD.AREA, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);

                tempsum   += S12;
                crossings += transitdirect(this.lon, lon);
                g.geod_geninverse(lat, lon, lat0, lon0, GEOD.DISTANCE | GEOD.AREA, out s12, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);
                perimeter += s12;
                tempsum   += S12;
                crossings += transit(lon, lon0);
            }

            double area0 = 4 * pi * g.c2;

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

            pP = perimeter;
            pA = 0 + tempsum;
            return(num);
        }
예제 #3
0
        /// <summary>
        /// Return the results assuming a tentative final test point is added via an
        /// azimuth and distance; 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 geod_polygon_addedge() and
        /// geod_polygon_compute() are used.
        /// </summary>
        /// <param name="g">The geod_geodesic object specifying the ellipsoid.</param>
        /// <param name="p">The geod_polygon object specifying the polygon.</param>
        /// <param name="azi">The azimuth at current point (degrees).</param>
        /// <param name="s">The distance from current point to final test point (meters).</param>
        /// <param name="reverse">If set <b>true</b> then clockwise (instead of counter-clockwise)
        /// traversal counts as a positive area.</param>
        /// <param name="sign">If set <b>true</b> 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.</param>
        /// <param name="pA">The area of the polygon (square meters); only set if polyline is set <b>true</b>
        /// in the call to geod_polygon_init().</param>
        /// <param name="pP">The perimeter of the polygon or length of the polyline (meters).</param>
        /// <returns>The number of points.</returns>
        /// <remarks>
        /// azi should be in the range [-540deg, 540deg).
        /// </remarks>
        public int geod_polygon_testedge(geod_geodesic g, double azi, double s, bool reverse, bool sign, out double pA, out double pP)
        {
            pP=pA=NaN;

            int num=this.num+1;
            if(num==1) return 0; // we don't have a starting point!

            double perimeter=P[0]+s;
            if(polyline)
            {
                pP=perimeter;
                return num;
            }

            double tempsum=A[0];
            int crossings=this.crossings;

            {
                double lat, lon, s12, S12, dummy;
                g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE|GEOD.LONGITUDE|GEOD.AREA, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);

                tempsum+=S12;
                crossings+=transitdirect(this.lon, lon);
                g.geod_geninverse(lat, lon, lat0, lon0, GEOD.DISTANCE|GEOD.AREA, out s12, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);
                perimeter+=s12;
                tempsum+=S12;
                crossings+=transit(lon, lon0);
            }

            double area0=4*pi*g.c2;
            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;
            }

            pP=perimeter;
            pA=0+tempsum;
            return num;
        }
예제 #4
0
        /// <summary>
        /// Add an edge to the polygon or polyline.
        /// </summary>
        /// <param name="g">The geod_geodesic object specifying the ellipsoid.</param>
        /// <param name="p">The geod_polygon object specifying the polygon.</param>
        /// <param name="azi">The azimuth at current point (degrees).</param>
        /// <param name="s">The distance from current point to next point (meters).</param>
        /// <remarks>
        /// g and p must have been initialized with calls to geod_init() and
        /// geod_polygon_init(), respectively. The same g must be used for all the
        /// points and edges in a polygon. azi should be in the range
        /// [-540deg, 540deg). This does nothing if no points have been
        /// added yet. The lat and lon fields of p give the location of
        /// the new vertex.
        /// </remarks>
        public void geod_polygon_addedge(geod_geodesic g, double azi, double s)
        {
            if(num!=0)
            { // Do nothing is num is zero
                double lat, lon, S12=0, dummy;
                if(polyline) g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE|GEOD.LONGITUDE, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out dummy);
                else g.geod_gendirect(this.lat, this.lon, azi, GEOD.LONG_UNROLL, s, GEOD.LATITUDE|GEOD.LONGITUDE|GEOD.AREA, out lat, out lon, out dummy, out dummy, out dummy, out dummy, out dummy, out S12);

                accadd(P, s);
                if(!polyline)
                {
                    accadd(A, S12);
                    crossings+=transitdirect(this.lon, lon);
                }
                this.lat=lat; this.lon=lon;
                ++num;
            }
        }