Use an online service to find the address for a tapped point.
Use case
You might use a geocoder to find a customer's delivery address based on the location returned by their device's GPS.
How to use the sample
Tap the map to see the nearest address displayed in a callout.
How it works
- Create the
Map
with aBasemap
. - Create a
LocatorTask
using a URL. - Set the
ReverseGeocodeParameters
for theLocatorTask
and specify the geocode's attributes. - Get the matching results from the
GeocodeResult
usingReverseGeocodeWithParametersAsync
- Change the attributes of the
MapView
'sCalloutData
and display the location using aCallout
Relevant API
- GeocodeParameters
- LocatorTask
- ReverseGeocodeParameters
Offline data
Read more about how to set up the sample's offline data here.
Link | Local Location |
---|---|
pin PNG file | <userhome> /ArcGIS/Runtime/Data/symbol/pin.png |
About the data
This sample uses the World Geocoding Service.
Tags
address, geocode, locate, reverse geocode, search
Sample Code
// [WriteFile Name=ReverseGeocodeOnline, Category=Search]
// [Legal]
// Copyright 2020 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]
#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD
// sample headers
#include "ReverseGeocodeOnline.h"
// ArcGIS Maps SDK headers
#include "AttributeListModel.h"
#include "CalloutData.h"
#include "Envelope.h"
#include "GeocodeResult.h"
#include "Graphic.h"
#include "GraphicListModel.h"
#include "GraphicsOverlay.h"
#include "GraphicsOverlayListModel.h"
#include "LocatorTask.h"
#include "Map.h"
#include "MapQuickView.h"
#include "MapTypes.h"
#include "PictureMarkerSymbol.h"
#include "Point.h"
#include "ReverseGeocodeParameters.h"
#include "SimpleRenderer.h"
#include "SpatialReference.h"
// Qt headers
#include <QDir>
#include <QFuture>
#include <QUrl>
#include <QUuid>
using namespace Esri::ArcGISRuntime;
namespace
{
const QUrl url("https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer");
const QUrl pinUrl("qrc:/Samples/Search/ReverseGeocodeOnline/pin_circle_red.png");
} // namespace
ReverseGeocodeOnline::ReverseGeocodeOnline(QObject* parent /* = nullptr */):
QObject(parent),
m_map(new Map(BasemapStyle::ArcGISImagery, this))
{
m_graphicsOverlay = new GraphicsOverlay(this);
m_locatorTask = new LocatorTask(url, this);
}
ReverseGeocodeOnline::~ReverseGeocodeOnline() = default;
void ReverseGeocodeOnline::configureGraphic()
{
PictureMarkerSymbol* pinSymbol = new PictureMarkerSymbol(pinUrl, this);
pinSymbol->setHeight(40);
pinSymbol->setWidth(40);
pinSymbol->setOffsetY(pinSymbol->height() / 2);
SimpleRenderer* simpleRenderer = new SimpleRenderer(pinSymbol, this);
m_graphicsOverlay->setRenderer(simpleRenderer);
m_graphicsOverlay->graphics()->append(new Graphic(this));
m_graphic = m_graphicsOverlay->graphics()->at(0);
}
void ReverseGeocodeOnline::getAddress()
{
connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& e)
{
e.accept();
const Point clickedLocation = m_mapView->screenToLocation(e.position().x(), e.position().y());
ReverseGeocodeParameters reverseGeocodeParameters;
reverseGeocodeParameters.setOutputSpatialReference(m_mapView->spatialReference());
m_locatorTask->reverseGeocodeWithParametersAsync(clickedLocation, reverseGeocodeParameters).then(this, [this](const QList<GeocodeResult>& geocodeResults)
{
if (geocodeResults.empty())
return;
GeocodeResult geocode = geocodeResults.at(0);
const Point location = geocode.displayLocation();
m_mapView->setViewpointCenterAsync(location);
const QString address = geocode.label();
const int splitIndex = address.indexOf(",");
m_mapView->calloutData()->setTitle(address.left(splitIndex).trimmed());
m_mapView->calloutData()->setDetail(address.mid(splitIndex + 1).trimmed());
m_mapView->calloutData()->setLocation(location);
m_mapView->calloutData()->setVisible(true);
m_graphic->setGeometry(geocode.displayLocation());
m_graphic->attributes()->setAttributesMap(geocode.attributes());
constexpr double scale = 8000.0;
m_mapView->setViewpointCenterAsync(geocode.extent().center(), scale);
m_graphic->setVisible(true);
});
});
}
void ReverseGeocodeOnline::init()
{
// Register the map view for QML
qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
qmlRegisterType<ReverseGeocodeOnline>("Esri.Samples", 1, 0, "ReverseGeocodeOnlineSample");
qmlRegisterUncreatableType<CalloutData>("Esri.Samples", 1, 0, "CalloutData", "CalloutData is an uncreatable type");
}
MapQuickView* ReverseGeocodeOnline::mapView() const
{
return m_mapView;
}
CalloutData* ReverseGeocodeOnline::calloutData() const
{
return m_calloutData;
}
// Set the view (created in QML)
void ReverseGeocodeOnline::setMapView(MapQuickView* mapView)
{
if (!mapView || mapView == m_mapView)
return;
m_mapView = mapView;
m_mapView->setMap(m_map);
// center map in San Diego
const Point center(-13042254.715252, 3857970.236806, SpatialReference(3857));
m_mapView->setViewpointCenterAsync(center, 30000);
configureGraphic();
m_mapView->graphicsOverlays()->append(m_graphicsOverlay);
getAddress();
emit mapViewChanged();
}