我有一个应用程序,找到我的用户与多边形之间的最短距离.
我想将多边形转换为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 – 在多边形上找到最接近用户位置的点所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)