Calculating the area of any polygon, the center of gravity

Recent project uses: add an icon to the central point of any irregular polygons. (Eg: xx region occurred Blizzard, Blizzard area is a polygon, polygon center to add a Blizzard icon)

Previous designs, the center point is calculated irregular rectangular bounds of the polygon. This is relatively simple, some round, rectangular, convex polygon are more suitable. But encountered concave polygon will be a problem, such as an irregular polygon crescent, bounds, center point, falls outside the crescent. It is a little difficult to accept.

After discussion, we decided to change the center of gravity.

Below the code

Calculation of any irregular polygonal center:

 / ** 
     * Get the geometric center of an irregular polygon 
     * 
     * @param mPoints 
     * @return 
     * / 
    public  static of LatLng getCenterPoint (List <of LatLng> mPoints) {
         // . 1 own calculation
         // method provided by Google map API 2 (Recommended ) 
        LatLngBounds.Builder boundsBuilder = LatLngBounds.builder ();
         for (LL of LatLng: mPoints) 
            boundsBuilder.include (LL); 
        return . boundsBuilder.build () getCenter (); 
    }

Or learn each of the maximum and minimum, sum, and then averaged, the maximum value and the minimum latitude, summed and then averaged, so that the center point.

And all of course also take the average of the longitude and latitude so that the average of this is also the center point.

 

Calculating the center of gravity of any irregular polygonal:

/ ** 
     * Get irregular polygon the center of gravity 
     * 
     * @param mPoints 
     * @return 
     * / 
    public  static of LatLng getCenterOfGravityPoint (List <of LatLng> mPoints) {
         Double Area = 0.0; // polygon area 
        Double the Gx = 0.0, Gy = 0.0; // center of gravity of the X, Y 
        for ( int I =. 1; I <= mPoints.size (); I ++ ) {
             Double ILAT = mPoints.get (I% mPoints.size ()) Latitude;.
             Double iLng = mPoints.get (I% mPoints.size ()) longitude;.
             Double nextLat = mPoints.get(i - 1).latitude;
            double nextLng = mPoints.get(i - 1).longitude;
            double temp = (iLat * nextLng - iLng * nextLat) / 2.0;
            area += temp;
            Gx += temp * (iLat + nextLat) / 3.0;
            Gy += temp * (iLng + nextLng) / 3.0;
        }
        Gx = Gx / area;
        Gy = Gy / area;
        return new LatLng(Gx, Gy);
    }

Wherein the class is a simple class LatLng latitude and longitude points contained. You can create your own that contains x, y class instead.

public class LatLng {
        public final double latitude;
        public final double longitude;
    }

A lot of people did not know the specific implementation LatLngBounds class, in fact, this is a class Google map package, the internal function is very simple, is to provide a constructor Builder can continue to fill to add latitude and longitude points LatLng, calculated continuously updated range and Bounds center center point.

After finishing LatLngBounds paste the following class, minus the trouble can import Google map pack

/ ** 
 * range based Coordinates 
 * 
 * com.google.android.gms.maps.model.LatLngBounds core replication method 
 * 
 * @author Maple
  * / 
@Deprecated ( "conditions permit, use com.google.android.gms. maps.model.LatLngBounds " )
 class the LatLngBounds of constructor (
         Private Val Southwest: of LatLng, // the lower left corner point 
        Private Val Northeast: of LatLng // upper right corner 
) { 
 
    Val Center: of LatLng 
        GET () { 
            // calculate the center point latitude 
            val centerLat = ( the this .southwest.latitude + the this .northeast.latitude) / 2.0
            // computing center longitude 
            Val = neLng the this .northeast.longitude // upper right corner longitude 
            Val swLng: Double = the this .southwest.longitude // lower left corner longitude 
            Val centerLng: Double = IF (swLng <= neLng) { 
                (neLng + swLng) / 2.0 
            } the else { 
                (neLng + 360.0 + swLng) / 2.0 
            } 
            return of LatLng (centerLat, centerLng) 
        } 
 
    // whether a point is within the range (inclusive) 
    Fun the contains (point: of LatLng): Boolean {
         returnlatContains (point.latitude) && the this .lngContains (point.longitude) 
    } 
 
    // a latitude value is within the range (inclusive) 
    Private Fun latContains (LAT: Double): Boolean {
         return  the this .southwest.latitude <= && LAT LAT <= the this .northeast.latitude 
    } 
 
    // a longitude value is within the range (inclusive) 
    Private Fun lngContains (LNG: Double): Boolean {
         return  iF ( the this .southwest.longitude <= the this .northeast .longitude) {
             the this .southwest.longitude <&& LNG LNG = <= the this .northeast.longitude 
        }the else {
             the this .southwest.longitude <= LNG LNG || <= the this .northeast.longitude 
        } 
    } 
 
    // small amount of data can use this method, a large amount of data is recommended Builder in the include () 
    Fun Including (Point: of LatLng) : {the LatLngBounds of 
        Val swLat = Math.min ( the this .southwest.latitude, point.latitude) 
        Val neLat = Math.max ( the this .northeast.latitude, point.latitude) 
        var neLng = the this .northeast.longitude 
        var swLng = the this . southwest.longitude 
        Val PLNG = point.longitude
        IF (! the this .lngContains (PLNG)) {
             IF (ZZA (swLng, PLNG) < ZZB (neLng, PLNG)) { 
                swLng = PLNG 
            } the else { 
                neLng = PLNG 
            } 
        } 
        return the LatLngBounds of (of LatLng (swLat, swLng), of LatLng (neLat, neLng)) 
    } 
 
    / ** 
     * the LatLngBounds of generator 
     * / 
    class Builder {
         private var swLat = 1.0 / 0.0    // lower left corner latitude 
        private var swLng = 0.0 / 0.0    // lower left corner longitude 
        private var neLat = -1.0 / 0.0  // 右上角 纬度
        private var neLng = 0.0 / 0.0   // 右上角 经度
 
        fun include(point: LatLng): Builder {
            this.swLat = Math.min(this.swLat, point.latitude)
            this.neLat = Math.max(this.neLat, point.latitude)
            val pLng = point.longitude
            if (java.lang.Double.isNaN(this.swLng)) {
                this.swLng = pLng
            } else {
                if (lngContains(pLng)) {
                    return  the this 
                } 
                IF (ZZA ( the this .swLng, PLNG) <ZZB ( the this .neLng, PLNG)) {
                     the this .swLng = PLNG
                     return  the this 
                } 
            } 
            the this .neLng = PLNG
             return  the this 
        } 
 
        // a longitude value is the the range (inclusive) 
        Private Fun lngContains (LNG: Double): Boolean {
             return  IF ( the this .swLng <= the this .neLng) {
                 the this .swLng <&& LNG LNG = <=this.neLng
            } else {
                this.swLng <= lng || lng <= this.neLng
            }
        }
 
        fun build(): LatLngBounds {
            // Preconditions.checkState(!java.lang.Double.isNaN(this.swLng), "no included points")
            return LatLngBounds(LatLng(this.swLat, this.swLng), LatLng(this.neLat, this.neLng))
        }
    }
 
    companion object {
        fun builder(): Builder {
            return Builder()
        }
 
        // 前者 - 后者
        private fun zza(var0: Double, var2: Double): Double {
            return (var0 - var2 + 360.0) % 360.0
        }
 
        // 后者 - 前者
        private fun zzb(var0: Double, var2: Double): Double {
            return (var2 - var0 + 360.0) % 360.0
        }
    }
 
}

Note ⚠️: LatLngBounds in Including () method and the Builder include () method on the same specific implementation, but LatLngBounds every time a new object is new, it is not suitable to use large quantities of data.

eg: When calculating the range of a relatively large number of point Polygon recommended to use include () method Builder.

Demo Institute Add: Https://Github.Com/shaoshuai904/GoogleMap_Demo

By this figure, we can find the difference between the center of gravity and

 

This switched: https://blog.csdn.net/shao941122/article/details/53671643

Guess you like

Origin www.cnblogs.com/nizuimeiabc1/p/11030953.html