Android, Java + Карта Google: прямые маршруты бесполезны. Можно ли их устранить?

Видео проблемы

Прямые маршруты бесполезны. Можно ли их устранить? есть прямые линии, которые мне бы не хотелось.

Ввод от rest_api - это простой json по этой ссылке:

https://drive.google.com/file/d/1S2_xOB9Bj6EqiFwuRNGV5JvrjPjZoQD0/view?usp=sharing

Вывод: карта с маркерами и **Без НИКАКИХ прямых линий. **.

Код:

onMapReady(@NonNull GoogleMap map) {
        googleMap = map;
        googleMap.getUiSettings().setMapToolbarEnabled(false);
        googleMap.getUiSettings().setZoomControlsEnabled(false);

        routePoints = new ArrayList<>();
        noRoutePoints = new ArrayList<>();

        String idTappaSelezionata = MainActivity.idUltimaTappaSelezionata;

        if (idTappaSelezionata != null) {
            mapView.setVisibility(View.GONE);

            StringRequest getPercorsoRequest = new StringRequest(Request.Method.POST, Config.GET_PERCORSO_URL,
                    response -> {
                        Logger.show("Mappa getData response: " + response + " | Url: " + Config.GET_PERCORSO_URL);

                        try {
                            JSONObject responseObject = new JSONObject(response);
                            JSONArray percorsoArray = responseObject.getJSONArray("percorso");

                            if (percorsoArray.length() == 0) {
                                clearRoutes();
                            } else {
                                parseAndDisplayRoute(percorsoArray);
                            }

                            mapView.setVisibility(View.VISIBLE);
                        } catch (JSONException e) {
                            // handle exception
                        }
                    },
                    error -> {
                        // handle error
                    }) {
                @Override
                protected Map<String, String> getParams() {
                    Map<String, String> params = new HashMap<>();
                    params.put("user_id", MainActivity.userLoggedId);
                    params.put("id_tappa", idTappaSelezionata);
                    params.put("id_via", MainActivity.idUltimaViaSelezionata);
                    return params;
                }
            };

            SingletonVolley.getInstance(getActivity()).addToRequestQueue(getPercorsoRequest);
        } else {
            showNoRouteDialog();
        }
    }

    private void clearRoutes() {
        getActivity().runOnUiThread(() -> {
            routePoints.clear();
            noRoutePoints.clear();
        });
    }

    private void parseAndDisplayRoute(JSONArray percorsoArray) throws JSONException {
        for (int i = 0; i < percorsoArray.length(); i++) {
            Gson gson = new Gson();
            String tmpPercorso = percorsoArray.getJSONObject(i).toString();
            Percorso newP = gson.fromJson(tmpPercorso, Percorso.class);

            if ("rosso".equals(newP.getColore())) {
                routePoints.add(new LatLng(newP.getLatitude(), newP.getLongitude()));
            } else if ("blu".equals(newP.getColore())) {
                noRoutePoints.add(new LatLng(newP.getLatitude(), newP.getLongitude()));
            }
        }

        getActivity().runOnUiThread(() -> {
            if (!routePoints.isEmpty()) {
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(routePoints.get(0), 14));
            }

            if (routePoints.size() > 1 && noRoutePoints.size() > 1) {
                addPolylines();
            }

            addMarker();
            setPolylineClickListener();
        });
    }

    private void addPolylines() {
        List<LatLng> percorso = PolyUtil.simplify(routePoints, 0.0001); // Adjusted tolerance

        PolylineOptions percorsoPolyline = new PolylineOptions()
                .addAll(percorso)
                .clickable(true)
                .width(10)
                .color(Color.RED);

        googleMap.addPolyline(percorsoPolyline);

       // List<LatLng> simplifiedNoRoute = PolyUtil.simplify(noRoutePoints, 0.0001); // Adjusted tolerance

        /*PolylineOptions polylineOptionsRosso = new PolylineOptions()
                .addAll(simplifiedRoute)
                .clickable(true)
                .width(10)
                .color(Color.RED);

        googleMap.addPolyline(polylineOptionsRosso);

        PolylineOptions polylineOptionsBlu = new PolylineOptions()
                .addAll(simplifiedNoRoute)
                .clickable(true)
                .width(10)
                .color(Color.BLUE);

        googleMap.addPolyline(polylineOptionsBlu);*/



        getExperiences(googleMap);
    }

    private void addMarker() {
        LatLng markerMe = routePoints.get(0);
        int customMarkerHeight = 100;
        int customMarkerWidth = 100;
        BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.me);
        Bitmap customMarkerBitmap = Bitmap.createScaledBitmap(bitmapDrawable.getBitmap(), customMarkerWidth, customMarkerHeight, false);
        BitmapDescriptor customMarkerMe = BitmapDescriptorFactory.fromBitmap(customMarkerBitmap);

        MarkerOptions markerOp = new MarkerOptions()
                .position(markerMe)
                .icon(customMarkerMe)
                .title("Marker " + getId());

        googleMap.addMarker(markerOp);
    }

    private void setPolylineClickListener() {
        googleMap.setOnPolylineClickListener(polyline -> {
            List<LatLng> path = polyline.getPoints();
            String navigationUri = "http://maps.google.com/maps?daddr = " + path.get(path.size() - 1).latitude + "," + path.get(path.size() - 1).longitude;
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(navigationUri));
            intent.setPackage("com.google.android.apps.maps");
            startActivity(intent);
        });
    }

    private void showNoRouteDialog() {
        mapView.setVisibility(View.GONE);

        String message = "Non è stato selezionato nessun percorso. Premere OK per scegliere un percorso.";
        androidx.appcompat.app.AlertDialog.Builder dialog = new androidx.appcompat.app.AlertDialog.Builder(getActivity());
        dialog.setTitle("Le Vie di Francesco");
        dialog.setMessage(message);

        dialog.setPositiveButton("OK", (dialogInterface, i) -> {
            ((MainActivity) getActivity()).caricaFragment("menu_home", new Vie(), "Vie");
        });
        dialog.setCancelable(false);
        dialog.show();
    }

Где моя беда?

Мне действительно нужна помощь... спасибо.

Lucifer85 26.07.2024 23:46

Спасибо, что поставили -1 на этот вопрос. Кто это сделал, очень, очень глуп.

Lucifer85 27.07.2024 11:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас проблема с данными. Это набор сегментов, который, если рассматривать его как единый список точек, приводит к таким «скачкам».

Пример «прыжка» происходит с точками «rosso» в точках с идентификаторами «968» и «15578» (которые представляют собой последовательные точки «rosso», разделенные разделом «blu» (подробнее об этом ниже):

43.775690,11.439900
43.769571,11.340214

Лучшим решением было бы обновить ваши данные в виде разных сегментов (например, GPX называет их «trkseg»s ) и обновить ваш код для поддержки нескольких сегментов трека.

Тест на близость

Однако если предположить, что данные не изменяются, то можно применить тест близости между точками для обнаружения «скачков» и построения нескольких полилиний.

Для этого используйте метод библиотеки SphericalUtil.computeDistanceBetween().

Я немного упростил ваш пример и изменил обработку «красных» точек, оставив «синие» точки исходными. Отдельный список segment используется для сохранения исходных списков (поскольку они могут понадобиться вам для других целей).

В качестве примера используется пороговое расстояние в 500,0 метров — это будет зависеть от данных.

Примечание. PolyUtil.simplify не имеет отношения к вашей проблеме и был удален здесь, но оставьте его, если хотите, по другим причинам.

private void addPolylines() {

    // "rosso"
    
    List<LatLng> percorso = routePoints;

    List<LatLng> segment = new ArrayList<>();
    LatLng prevPt = percorso.get(0);
    for (LatLng pt : percorso) {
        double d = SphericalUtil.computeDistanceBetween(prevPt,pt);

        if (d > 500.0) {
            PolylineOptions percorsoPolyline = new PolylineOptions()
                                                       .addAll(segment)
                                                       .clickable(true)
                                                       .width(10)
                                                       .color(Color.RED);

            googleMap.addPolyline(percorsoPolyline);
            segment.clear();
        }

        segment.add(pt);
        prevPt = pt;
    }
    if (segment.size() > 0) {
        PolylineOptions percorsoPolyline = new PolylineOptions()
                                                   .addAll(segment)
                                                   .clickable(true)
                                                   .width(10)
                                                   .color(Color.RED);

        googleMap.addPolyline(percorsoPolyline);
        segment.clear();
    }


    // "blu"
    
    percorso = noRoutePoints;

    PolylineOptions percorsoPolyline = new PolylineOptions()
                                               .addAll(percorso)
                                               .clickable(true)
                                               .width(10)
                                               .color(Color.BLUE);

    googleMap.addPolyline(percorsoPolyline);

}

И результат (с хорошим «россо» и плохим «синим»):


Тест цветовой секции

Обратите внимание, что ваши данные организованы в виде серии сегментов «rosso» и «blue», например:

[rosso data]
[blu data]
[rosso data]
[blu data]

Поэтому, когда вы достигаете конца раздела «россо», затем переходите к «синему», а затем обратно к «россо», происходит «прыжок» между последовательными точками «россо». Это могут быть сегменты вашего трека, но, как оказалось, даже в «blu» у вас есть несколько сегментов (читайте дальше).

В качестве альтернативы вы можете просто построить свои полилинии на основе этих группировок и обнаружить переходы:

private void parseAndDisplayRoute(JSONArray percorsoArray) throws JSONException {
    String lastColor = "";
    List<LatLng> segment = new ArrayList<LatLng>();

    LatLng prevPt = new LatLng(0.0,0.0);

    for (int i = 0; i < percorsoArray.length(); i++) {
        Gson gson = new Gson();
        String tmpPercorso = percorsoArray.getJSONObject(i).toString();
        Percorso newP = gson.fromJson(tmpPercorso, Percorso.class);


        LatLng newPt = new LatLng(newP.getLatitude(), newP.getLongitude());

        if (i == 0) {
            lastColor = newP.getColore();
            segment = new ArrayList<LatLng>();
            prevPt = newPt;
        }


        // detect segment transition based on "color" OR distance

        if (!lastColor.equals(newP.getColore())) {
            int color = (lastColor.equals("rosso") ? Color.RED : Color.BLUE);
            addPolylines(segment, color);
            segment.clear();
        }


        if ("rosso".equals(newP.getColore())) {
            routePoints.add(newPt);
            segment.add(newPt);
        } else if ("blu".equals(newP.getColore())) {
            noRoutePoints.add(newPt);
            segment.add(newPt);
        }

        lastColor = newP.getColore();
        prevPt = newPt;
    }

    if (segment.size() > 0) {
        int color = (lastColor.equals("rosso") ? Color.RED : Color.BLUE);
        addPolylines(segment, color);
        segment.clear();
    }

    if (!routePoints.isEmpty()) {
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(routePoints.get(0), 14));
    }

}

private void addPolylines(List<LatLng> pts, int color) {
    PolylineOptions percorsoPolyline = new PolylineOptions()
                                               .addAll(pts)
                                               .clickable(true)
                                               .width(10)
                                               .color(color);

    googleMap.addPolyline(percorsoPolyline);


}

Результат использования только «цветных» разделов — «синий» по-прежнему плох, поскольку в нем есть несколько сегментов...:

Раздел «Близость + цвет»

Итак, наконец, объединение двух методов (расстояние + переход цвета):

private void parseAndDisplayRoute(JSONArray percorsoArray) throws JSONException {
    String lastColor = "";
    List<LatLng> segment = new ArrayList<LatLng>();

    LatLng prevPt = new LatLng(0.0,0.0);

    for (int i = 0; i < percorsoArray.length(); i++) {
        Gson gson = new Gson();
        String tmpPercorso = percorsoArray.getJSONObject(i).toString();
        Percorso newP = gson.fromJson(tmpPercorso, Percorso.class);

        double d = 0.0;

        LatLng newPt = new LatLng(newP.getLatitude(), newP.getLongitude());

        if (i == 0) {
            lastColor = newP.getColore();
            segment = new ArrayList<LatLng>();
            prevPt = newPt;
        }


        d = SphericalUtil.computeDistanceBetween(prevPt,newPt);

        // detect segment transition based on "color" OR distance

        if (!lastColor.equals(newP.getColore()) || d > 500.0) {
            int color = (lastColor.equals("rosso") ? Color.RED : Color.BLUE);
            addPolylines(segment, color);
            segment.clear();
        }


        if ("rosso".equals(newP.getColore())) {
            routePoints.add(newPt);
            segment.add(newPt);
        } else if ("blu".equals(newP.getColore())) {
            noRoutePoints.add(newPt);
            segment.add(newPt);
        }

        lastColor = newP.getColore();
        prevPt = newPt;
    }

    if (segment.size() > 0) {
        int color = (lastColor.equals("rosso") ? Color.RED : Color.BLUE);
        addPolylines(segment, color);
        segment.clear();
    }

    if (!routePoints.isEmpty()) {
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(routePoints.get(0), 14));
    }


    //        addMarker();
    //        setPolylineClickListener();
}

private void addPolylines(List<LatLng> pts, int color) {
    PolylineOptions percorsoPolyline = new PolylineOptions()
                                               .addAll(pts)
                                               .clickable(true)
                                               .width(10)
                                               .color(color);

    googleMap.addPolyline(percorsoPolyline);


}


Примечания

Хорошо, когда вернусь домой, попробую, спасибо за любую помощь ❤️

Lucifer85 27.07.2024 17:35

Большое спасибо!!! я попробую изменить цвет фьезоле - понтассьеве

Lucifer85 28.07.2024 07:48

Другие вопросы по теме