android– 在多边形上找到最接近用户位置的点

android– 在多边形上找到最接近用户位置的点,第1张

概述我有一个应用程序,找到我的用户多边形之间的最短距离.我想将多边形转换为Geofence以检查用户与区域之间的距离,以便向用户提供准确的信息.我怎样才能做到这一点?这是MapsActivitypublicclassMapsActivityextendsFragmentActivityimplementsOnMapReadyCallback,Locatio

我有一个应用程序,找到我的用户与多边形之间的最短距离.

我想将多边形转换为Geofence以检查用户与区域之间的距离,以便向用户提供准确的信息.

我怎样才能做到这一点?

这是MapsActivity

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener, MinimumdistanceTask.GetMinimumdistanceListener {    private GoogleMap mMap;    private  LocationManager manager;    private double lat, lng;    private KmlLayer layer;    private LatLng latLngTest;    private  boolean contains = false;    private  ArrayList<LatLng> outerBoundary;    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_maps);        // Obtain the SupportMapFragment and get notifIEd when the map is ready to be used.        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()                .findFragmentByID(R.ID.map);        mapFragment.getMapAsync(this);        manager = (LocationManager) getSystemService(LOCATION_SERVICE);    }    @OverrIDe    protected voID onResume() {        super.onResume();        String provIDer = LocationManager.GPS_PROVIDER;        //take the user location every second        try {            manager.requestLocationUpdates(provIDer, 1000, 0, this);        }catch (SecurityException e){        }    }    @OverrIDe    public voID onMapReady(GoogleMap GoogleMap) {        mMap = GoogleMap;    }    @OverrIDe    public voID onLocationChanged(Location location) {        //clear map before create new location        mMap.clear();        try {            //load the kml file            layer = new KmlLayer(mMap, R.raw.polygon_layer, this);            layer.addLayerToMap();        } catch (IOException e) {            e.printstacktrace();        } catch (XmlPullParserException e) {            e.printstacktrace();        }        lat = location.getLatitude();        lng = location.getLongitude();        latLngTest = new LatLng(lat,lng);        // Add a marker in user location        LatLng userLocation = new LatLng(latLngTest.latitude, latLngTest.longitude);        mMap.addMarker(new MarkerOptions().position(userLocation).Title("you are here"));        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));        //check if the user in the polygon        boolean insIDe = ifUserInsIDe();        if(insIDe){            Toast.makeText(MapsActivity.this, "you are in the polygon", Toast.LENGTH_SHORT).show();        }else{            Toast.makeText(MapsActivity.this, "you are outsIDe the polygon", Toast.LENGTH_SHORT).show();            //create the string address for the url            String address = "";            for (int i = 0; i < outerBoundary.size(); i++) {                address += (outerBoundary.get(i).toString() + "|");                address = address.replace("lat/lng:", "");                address = address.replace(" ", "");                address = address.replace("(", "");                address = address.replace(")", "");            }            MinimumdistanceTask task = new MinimumdistanceTask(this);            task.execute("https://maps.GoogleAPIs.com/maps/API/distancematrix/Json?units=imperial&origins="+latLngTest.latitude+ "," + latLngTest.longitude                    + "&destinations=" + address + "&mode=walking");        }    }    @OverrIDe    public voID getMinimumdistance(int closeLocation) {        //check if you get results properly        if(closeLocation != -1) {            GetDirection direction = new GetDirection();            direction.execute("https://maps.GoogleAPIs.com/maps/API/directions/Json?origin=" + latLngTest.latitude + "," + latLngTest.longitude                    + "&destination=" + outerBoundary.get(closeLocation).latitude + "+" + outerBoundary.get(closeLocation).longitude);        }    }    @OverrIDe    public voID onStatusChanged(String provIDer, int status, Bundle extras) {    }    @OverrIDe    public voID onProvIDerEnabled(String provIDer) {    }    @OverrIDe    public voID onProvIDerDisabled(String provIDer) {    }    public boolean ifUserInsIDe(){        if (layer.getContainers() != null) {            for (KmlContainer container : layer.getContainers()) {                if (container.getPlacemarks() != null) {                    for (KmlPlacemark placemark : container.getPlacemarks()) {                        contains = false;                        if (placemark.getGeometry() instanceof Kmlpolygon) {                            Kmlpolygon polygon = (Kmlpolygon) placemark.getGeometry();                            // Get the outer boundary and check if the test location lIEs insIDe                            outerBoundary = polygon.getouterBoundaryCoordinates();                            contains = polyUtil.containsLocation(latLngTest, outerBoundary, true);                            if (contains) {                                // Get the inner boundarIEs and check if the test location lIEs insIDe                                ArrayList<ArrayList<LatLng>> innerBoundarIEs = polygon.getInnerBoundaryCoordinates();                                if (innerBoundarIEs != null) {                                    for (ArrayList<LatLng> innerBoundary : innerBoundarIEs) {                                        // If the test location lIEs in a hole, the polygon doesn't contain the location                                        if (polyUtil.containsLocation(latLngTest, innerBoundary, true)) {                                            contains = false;                                        }                                    }                                }                            }                        }                    }                }            }        }        return contains;    }    public class GetDirection extends AsyncTask<String , VoID, String> {        httpsURLConnection connection = null;        BufferedReader reader = null;        StringBuilder builder = new StringBuilder();        @OverrIDe        protected String doInBackground(String... params) {            String address = params[0];            try {                URL url = new URL(address);                connection = (httpsURLConnection) url.openConnection();                if(connection.getResponseCode() != httpURLConnection.http_OK){                    return "Error from server";                }                reader = new BufferedReader(new inputStreamReader(connection.getinputStream()));                String line;                while ((line = reader.readline()) != null){                    builder.append(line);                }            } catch (MalformedURLException e) {                e.printstacktrace();            } catch (IOException e) {                e.printstacktrace();            }            return builder.toString();        }        @OverrIDe        protected voID onPostExecute(String s) {        //get the polyline string            String polygonPoints = "";            try {                JsONObject object = new JsONObject(s);                JsONArray array = object.getJsONArray("routes");                for (int i = 0; i < array.length(); i++) {                    JsONObject arrObj1 = array.getJsONObject(i);                    JsONObject points = arrObj1.getJsONObject("overvIEw_polyline");                    polygonPoints = points.getString("points");                }                //convert the string to polyline;                ArrayList<LatLng> a = new ArrayList<>(decodepolyPoints(polygonPoints));                //add polyline to the map                mMap.addpolyline(new polylineoptions().addAll(a).wIDth(10).color(color.BLUE));            } catch (JsONException e) {                e.printstacktrace();            }        }    }    //the method that convert the string to polyline    public static ArrayList<LatLng> decodepolyPoints(String encodedpath){        int len = encodedpath.length();        final ArrayList<LatLng> path = new ArrayList<LatLng>();        int index = 0;        int lat = 0;        int lng = 0;        while (index < len) {            int result = 1;            int shift = 0;            int b;            do {                b = encodedpath.charat(index++) - 63 - 1;                result += b << shift;                shift += 5;            } while (b >= 0x1f);            lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);            result = 1;            shift = 0;            do {                b = encodedpath.charat(index++) - 63 - 1;                result += b << shift;                shift += 5;            } while (b >= 0x1f);            lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);            path.add(new LatLng(lat * 1e-5, lng * 1e-5));        }        return path;    }}

这是我的AsyncTask来获得最小距离点

public class MinimumdistanceTask extends AsyncTask<String, VoID, Integer>{    private int closeLocation;    // private String points;    private GetMinimumdistanceListener Listener;    public MinimumdistanceTask(GetMinimumdistanceListener Listener){        // this.points = points;        this.Listener = Listener;    }    @OverrIDe    protected Integer doInBackground(String... params) {        httpsURLConnection connection = null;        BufferedReader reader = null;        StringBuilder builder = new StringBuilder();        int minimumdis = -1;            String address = params[0];            try {                URL url = new URL(address);                connection = (httpsURLConnection) url.openConnection();                if(connection.getResponseCode() != httpURLConnection.http_OK){                    return -1;                }                reader = new BufferedReader(new inputStreamReader(connection.getinputStream()));                String line;                while ((line = reader.readline()) != null){                    builder.append(line);                }            ///get the Json data                JsONObject JsonObject1 = new JsONObject(builder.toString());                JsONArray points = JsonObject1.getJsONArray("rows");                JsONObject JsonObject2 = points.getJsONObject(0);                JsONArray elements = JsonObject2.getJsONArray("elements");                for (int i = 0; i < elements.length(); i++) {                    JsONObject JsonObject3 = elements.getJsONObject(i);                    JsONObject distance = JsonObject3.getJsONObject("distance");                    if( distance.getInt("value") < minimumdis || minimumdis == -1) {                        minimumdis = distance.getInt("value");                        closeLocation = i;                    }                }            } catch (MalformedURLException | JsONException e) {                e.printstacktrace();            } catch (IOException e) {                e.printstacktrace();            }        return closeLocation;        }    @OverrIDe    protected voID onPostExecute(Integer closeLocation) {            Listener.getMinimumdistance(closeLocation);    }    public interface GetMinimumdistanceListener{        voID getMinimumdistance(int closeLocation);    }}

非常感谢 :)

解决方法:

您可以使用如下所示的函数来计算由List< LatLng>定义的多边形中的最近点.和给定的LatLng.

它使用Google Maps Android API Utility Library中的polyUtil.distancetoline计算测试LatLng与列表的每个段之间的距离,以及基于https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java的distancetoline方法计算段上点的投影的方法.

private LatLng findNearestPoint(LatLng test, List<LatLng> target) {    double distance = -1;    LatLng minimumdistancePoint = test;    if (test == null || target == null) {        return minimumdistancePoint;    }    for (int i = 0; i < target.size(); i++) {        LatLng point = target.get(i);        int segmentPoint = i + 1;        if (segmentPoint >= target.size()) {            segmentPoint = 0;        }        double currentdistance = polyUtil.distancetoline(test, point, target.get(segmentPoint));        if (distance == -1 || currentdistance < distance) {            distance = currentdistance;            minimumdistancePoint = findNearestPoint(test, point, target.get(segmentPoint));        }    }    return minimumdistancePoint;}/** * Based on `distancetoline` method from * https://github.com/Googlemaps/androID-maps-utils/blob/master/library/src/com/Google/maps/androID/polyUtil.java */private LatLng findNearestPoint(final LatLng p, final LatLng start, final LatLng end) {    if (start.equals(end)) {        return start;    }    final double s0lat = Math.toradians(p.latitude);    final double s0lng = Math.toradians(p.longitude);    final double s1lat = Math.toradians(start.latitude);    final double s1lng = Math.toradians(start.longitude);    final double s2lat = Math.toradians(end.latitude);    final double s2lng = Math.toradians(end.longitude);    double s2s1lat = s2lat - s1lat;    double s2s1lng = s2lng - s1lng;    final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)            / (s2s1lat * s2s1lat + s2s1lng * s2s1lng);    if (u <= 0) {        return start;    }    if (u >= 1) {        return end;    }    return new LatLng(start.latitude + (u * (end.latitude - start.latitude)),            start.longitude + (u * (end.longitude - start.longitude)));}

您可以使用以下代码进行测试:

List<LatLng> points = new ArrayList<>();points.add(new LatLng(2, 2));points.add(new LatLng(4, 2));points.add(new LatLng(4, 4));points.add(new LatLng(2, 4));points.add(new LatLng(2, 2));LatLng testPoint = new LatLng(3, 0);LatLng nearestPoint = findNearestPoint(testPoint, points);Log.e("NEAREST POINT: ", "" + nearestPoint); // lat/lng: (3.0,2.0)Log.e("disTANCE: ", "" + SphericalUtil.computedistanceBetween(testPoint, nearestPoint)); // 222085.35856591124
总结

以上是内存溢出为你收集整理的android – 在多边形上找到最接近用户位置的点全部内容,希望文章能够帮你解决android – 在多边形上找到最接近用户位置的点所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1115740.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存