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