Plotting points on maps in arcgis qt and getting transect length

  arcgis, c++, maps, polygon, qt

I am building an application in Qt utilising arcgis maps. The user must be able to click on the map and plot multiple points with straight lines joining them.The application must also display distance between the start point and end point I have seen the geodesic operations example(this has a fixed starting point I want that to be given by the user as well on mouse click) in ArcGIS Qt and I want to build a similar application with multiple points.

This is the header file

    #ifndef GEODESICOPERATIONS_H
#define GEODESICOPERATIONS_H
namespace Esri
{
namespace ArcGISRuntime
{
class Map;
class MapQuickView;
class Graphic;
}
}

#include "Point.h"
#include "Polyline.h"
#include <QQuickItem>

class GeodesicOperations : public QQuickItem
{
  Q_OBJECT

  Q_PROPERTY(QString distanceText READ distanceText NOTIFY distanceTextChanged)

public:
  explicit GeodesicOperations(QQuickItem* parent = nullptr);
  ~GeodesicOperations() override = default;

  void componentComplete() override;
  static void init();

signals:
  void distanceTextChanged();

private:
  Esri::ArcGISRuntime::Map* m_map = nullptr;
  Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr;
  Esri::ArcGISRuntime::Graphic* m_nycGraphic = nullptr;
  Esri::ArcGISRuntime::Graphic* m_pathGraphic = nullptr;
  Esri::ArcGISRuntime::Graphic* m_destinationGraphic = nullptr;
  QString m_distanceText;

private:
  Esri::ArcGISRuntime::Polyline pointsToPolyline(const QList<Esri::ArcGISRuntime::Point>& points);
  QString distanceText() const;
};

#endif // GEODESICOPERATIONS_H

This is the cpp file for the above header.

    #ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD

#include "GeodesicOperations.h"

#include "Map.h"
#include "MapQuickView.h"
#include "GraphicsOverlay.h"
#include "Graphic.h"
#include "SimpleMarkerSymbol.h"
#include "SimpleLineSymbol.h"
#include "GeometryEngine.h"
#include "SpatialReference.h"
#include "PolylineBuilder.h"
#include "Point.h"

using namespace Esri::ArcGISRuntime;

GeodesicOperations::GeodesicOperations(QQuickItem* parent /* = nullptr */):
  QQuickItem(parent)
{
}

    void GeodesicOperations::init()
    {
      // Register the map view for QML
      qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
      qmlRegisterType<GeodesicOperations>("Esri.Samples", 1, 0, "GeodesicOperationsSample");
    }
    
    void GeodesicOperations::componentComplete()
    {
      QQuickItem::componentComplete();
    
      // find QML MapView component
      m_mapView = findChild<MapQuickView*>("mapView");
    
      // Create a map using the imagery basemap
      m_map = new Map(BasemapStyle::ArcGISImageryStandard, this);
    
      // Set map to map view
      m_mapView->setMap(m_map);
    
      // Create a GraphicsOverlay
       GraphicsOverlay* graphicsOverlay = new GraphicsOverlay(this);
       m_mapView->graphicsOverlays()->append(graphicsOverlay);
    
       // Create Graphic Symbols
       SimpleMarkerSymbol* markerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, QColor("blue"), 10.0f /*size*/, this);
       SimpleLineSymbol* pathSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Dash, QColor("blue"), 5.0f /*width*/, this);
    
       // Create source graphic
       const Point nycPoint(73.8021,15.4561, SpatialReference::wgs84());
       m_nycGraphic = new Graphic(nycPoint,markerSymbol, this);
       //m_nycGraphic = new Graphic(this);
       //m_nycGraphic->setSymbol(markerSymbol);
       graphicsOverlay->graphics()->append(m_nycGraphic);
    
       // Create destination graphic
       m_destinationGraphic = new Graphic(this);
       m_destinationGraphic->setSymbol(markerSymbol);
       graphicsOverlay->graphics()->append(m_destinationGraphic);
    
       // Create path graphic
       m_pathGraphic = new Graphic(this);
       m_pathGraphic->setSymbol(pathSymbol);
       graphicsOverlay->graphics()->append(m_pathGraphic);
    
       // connect to mouse clicked signal
        connect(m_mapView, &MapQuickView::mouseClicked, this, [this, nycPoint](QMouseEvent& mouseEvent)
       //connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& mouseEvent)
        {
    
          // re-project the point to match the NYC graphic
          const Point clickedPoint = m_mapView->screenToLocation(mouseEvent.x(), mouseEvent.y());
          const Point destination = GeometryEngine::project(clickedPoint, m_nycGraphic->geometry().spatialReference());
    
          // update the destination graphic
          m_destinationGraphic->setGeometry(destination);
          //polylineBuilder->addPoint(m_destinationGraphic);
    
          // create line with start/end points
          const QList<Point> points = {nycPoint, destination};
          const Polyline polyline = pointsToPolyline(points);
    
          // densify the path as a geodesic curve and show it with the path graphic
          constexpr double maxSegmentLength = 1.0;
          const LinearUnit unitOfMeasurement(LinearUnitId::Kilometers);
          constexpr GeodeticCurveType curveType = GeodeticCurveType::NormalSection;
    
    //      PolylineBuilder *m_polyline_builder=new PolylineBuilder(SpatialReference(4326), this);
    //      m_polyline_builder->addPoint(destination);
    //      const Polyline polyline = m_polyline_builder->toPolyline();
    
          const Geometry pathGeometry = GeometryEngine::densifyGeodetic(polyline, maxSegmentLength, unitOfMeasurement, curveType);
    
          // update the graphic
          m_pathGraphic->setGeometry(pathGeometry);
    
          // calculate the path's geodetic length
          m_distanceText = QString::number(GeometryEngine::lengthGeodetic(pathGeometry, unitOfMeasurement, curveType), 'f', 2);
          emit distanceTextChanged();
        });
      }
    
    Polyline GeodesicOperations::pointsToPolyline(const QList<Point>& points)
    {
     PolylineBuilder polylineBuilder(SpatialReference(4326));
    for (const Point& point : points)
        polylineBuilder.addPoint(point);
    
      return polylineBuilder.toPolyline();
    }
    
    QString GeodesicOperations::distanceText() const
    {
      return m_distanceText;
    }
    
    /*connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent &mouseEvent)
     * { // get click location, create point, symbolize, display as grpahic
     * const Point clickedPoint = m_mapView->screenToLocation(mouseEvent.x(), mouseEvent.y());
     * const Geometry pointGeom = GeometryEngine::normalizeCentralMeridian(clickedPoint);
     * SimpleMarkerSymbol* pointMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, QColor("red"), 10, this);
     *  m_graphicOverlay->graphics()->append(new Graphic(pointGeom, pointMarkerSymbol));
     *  // add point to polyline builder, create polyline from builder, symbolize, display polyline graphic
     * m_polylineBuilder->addPoint(pointGeom);
     * const Polyline singleLine = m_polylineBuilder->toPolyline();
     * SimpleLineSymbol* lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Dash, QColor("blue"), 3, this);
     * m_graphicOverlay->graphics()->append(new Graphic(singleLine, lineSymbol));});‍‍‍‍‍‍‍‍‍‍‍‍‍‍
     */  

I found the comments(at the end of cpp file) to a similar question in the Esri forum although I am not exactly sure as to how to implement it.

Thanks

Source: Windows Questions C++

LEAVE A COMMENT