مفاهیم پیشرفته

به دست آوردن داده ها

راه های زیادی برای به دست آوردن داده های مکان جمع آوری شده وجود دارد. در اینجا ما دو تکنیک برای به دست آوردن داده برای استفاده با ویژگی snap to roads در Roads API را توضیح می دهیم.

GPX

GPX یک فرمت باز مبتنی بر XML برای به اشتراک گذاری مسیرها، مسیرها و ایستگاه های بین راهی است که توسط دستگاه های GPS گرفته شده است. این مثال از تجزیه کننده XmlPull استفاده می کند، یک تجزیه کننده سبک وزن XML که هم برای سرور جاوا و هم برای محیط های موبایل در دسترس است.

/**
 * Parses the waypoint (wpt tags) data into native objects from a GPX stream.
 */
private List<LatLng> loadGpxData(XmlPullParser parser, InputStream gpxIn)
        throws XmlPullParserException, IOException {
    // We use a List<> as we need subList for paging later
    List<LatLng> latLngs = new ArrayList<>();
    parser.setInput(gpxIn, null);
    parser.nextTag();

    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }

        if (parser.getName().equals("wpt")) {
            // Save the discovered latitude/longitude attributes in each <wpt>.
            latLngs.add(new LatLng(
                    Double.valueOf(parser.getAttributeValue(null, "lat")),
                    Double.valueOf(parser.getAttributeValue(null, "lon"))));
        }
        // Otherwise, skip irrelevant data
    }

    return latLngs;
}

در اینجا برخی از داده های خام GPX بارگذاری شده بر روی نقشه آمده است.

داده های خام GPX روی نقشه

خدمات مکان یابی اندروید

بهترین راه برای گرفتن داده های GPS از دستگاه Android بسته به مورد استفاده شما متفاوت است. نگاهی به کلاس آموزش اندروید در مورد دریافت به‌روزرسانی‌های موقعیت مکانی و همچنین نمونه‌های مکان Google Play در GitHub بیندازید.

پردازش مسیرهای طولانی

از آنجایی که ویژگی Snap to Roads مکان را بر اساس مسیر کامل استنتاج می کند، نه نقاط منفرد، شما باید هنگام پردازش مسیرهای طولانی مراقب باشید (یعنی مسیرهای بیش از 100 امتیاز در هر درخواست).

برای اینکه درخواست های فردی را به عنوان یک مسیر طولانی در نظر بگیرید، باید مقداری همپوشانی داشته باشید، به طوری که امتیازات نهایی درخواست قبلی به عنوان اولین نقاط درخواست بعدی درج شود. تعداد امتیازهایی که باید لحاظ شود به دقت داده های شما بستگی دارد. برای درخواست های کم دقت باید امتیاز بیشتری در نظر بگیرید.

این مثال از Java Client for Google Maps Services برای ارسال درخواست‌های صفحه‌بندی شده استفاده می‌کند و سپس داده‌ها، از جمله نقاط درون‌یابی، را دوباره به لیست برگشتی متصل می‌کند.

/**
 * Snaps the points to their most likely position on roads using the Roads API.
 */
private List<SnappedPoint> snapToRoads(GeoApiContext context) throws Exception {
    List<SnappedPoint> snappedPoints = new ArrayList<>();

    int offset = 0;
    while (offset < mCapturedLocations.size()) {
        // Calculate which points to include in this request. We can't exceed the API's
        // maximum and we want to ensure some overlap so the API can infer a good location for
        // the first few points in each request.
        if (offset > 0) {
            offset -= PAGINATION_OVERLAP;   // Rewind to include some previous points.
        }
        int lowerBound = offset;
        int upperBound = Math.min(offset + PAGE_SIZE_LIMIT, mCapturedLocations.size());

        // Get the data we need for this page.
        LatLng[] page = mCapturedLocations
                .subList(lowerBound, upperBound)
                .toArray(new LatLng[upperBound - lowerBound]);

        // Perform the request. Because we have interpolate=true, we will get extra data points
        // between our originally requested path. To ensure we can concatenate these points, we
        // only start adding once we've hit the first new point (that is, skip the overlap).
        SnappedPoint[] points = RoadsApi.snapToRoads(context, true, page).await();
        boolean passedOverlap = false;
        for (SnappedPoint point : points) {
            if (offset == 0 || point.originalIndex >= PAGINATION_OVERLAP - 1) {
                passedOverlap = true;
            }
            if (passedOverlap) {
                snappedPoints.add(point);
            }
        }

        offset = upperBound;
    }

    return snappedPoints;
}

در اینجا داده های بالا پس از اجرای درخواست های Snap to roads آمده است. خط قرمز، داده های خام و خط آبی، داده های برداشته شده است.

نمونه ای از داده هایی که در جاده ها ضبط شده است

استفاده بهینه از سهمیه

پاسخ به درخواست snap to roads شامل فهرستی از شناسه‌های مکان است که به نقاطی که ارائه کرده‌اید نگاشت می‌شود، اگر interpolate=true تنظیم کنید، به‌طور بالقوه دارای امتیاز اضافی است.

به منظور استفاده موثر از سهمیه مجاز خود برای درخواست محدودیت سرعت، فقط باید شناسه مکان های منحصر به فرد را در درخواست خود جستجو کنید. این مثال از Java Client برای خدمات Google Maps استفاده می‌کند تا محدودیت‌های سرعت را از فهرست شناسه‌های مکان جستجو کند.

/**
 * Retrieves speed limits for the previously-snapped points. This method is efficient in terms
 * of quota usage as it will only query for unique places.
 *
 * Note: Speed limit data is only available for requests using an API key enabled for a
 * Google Maps APIs Premium Plan license.
 */
private Map<String, SpeedLimit> getSpeedLimits(GeoApiContext context, List<SnappedPoint> points)
        throws Exception {
    Map<String, SpeedLimit> placeSpeeds = new HashMap<>();

    // Pro tip: Save on quota by filtering to unique place IDs.
    for (SnappedPoint point : points) {
        placeSpeeds.put(point.placeId, null);
    }

    String[] uniquePlaceIds =
            placeSpeeds.keySet().toArray(new String[placeSpeeds.keySet().size()]);

    // Loop through the places, one page (API request) at a time.
    for (int i = 0; i < uniquePlaceIds.length; i += PAGE_SIZE_LIMIT) {
        String[] page = Arrays.copyOfRange(uniquePlaceIds, i,
                Math.min(i + PAGE_SIZE_LIMIT, uniquePlaceIds.length));

        // Execute!
        SpeedLimit[] placeLimits = RoadsApi.speedLimits(context, page).await();
        for (SpeedLimit sl : placeLimits) {
            placeSpeeds.put(sl.placeId, sl);
        }
    }

    return placeSpeeds;
}

در اینجا داده های بالا با محدودیت سرعت مشخص شده در هر شناسه مکان منحصر به فرد آمده است.

علائم محدودیت سرعت روی نقشه

تعامل با سایر API ها

یکی از مزایای بازگرداندن شناسه‌های مکان در پاسخ‌های فوری به جاده‌ها این است که می‌توانید از شناسه مکان در بسیاری از APIهای پلتفرم Google Maps استفاده کنید. این مثال از Java Client برای خدمات Google Maps استفاده می کند تا مکانی را که از عکس فوق به درخواست جاده بازگردانده شده است، جغرافیایی کند.

/**
 * Geocodes a snapped point using the place ID.
 */
private GeocodingResult geocodeSnappedPoint(GeoApiContext context, SnappedPoint point) throws Exception {
    GeocodingResult[] results = GeocodingApi.newRequest(context)
            .place(point.placeId)
            .await();

    if (results.length > 0) {
        return results[0];
    }
    return null;
}

در اینجا نشانگر محدودیت سرعت با آدرس API Geocoding مشروح شده است.

آدرس جغرافیایی کد شده روی یک نشانگر نشان داده شده است

کد نمونه

ملاحظات

کد پشتیبانی کننده از این مقاله به عنوان یک برنامه اندرویدی برای اهداف توضیحی موجود است. در عمل نباید کلیدهای API سمت سرور خود را در یک برنامه اندرویدی توزیع کنید زیرا کلید شما نمی تواند در برابر دسترسی غیرمجاز شخص ثالث ایمن شود. در عوض، برای ایمن کردن کلیدهای خود، باید کد API را به عنوان یک پراکسی سمت سرور مستقر کنید و از برنامه Android خود بخواهید درخواست‌ها را از طریق پروکسی ارسال کند، تا اطمینان حاصل شود که درخواست‌ها مجاز هستند.

دانلود کنید

کد را از GitHub دانلود کنید.