I have been following the the two very beginning tutorials, the first being display a map and the second being add a point, line and polyline. I tweaked just a little so that rather than hard coding the points in from the start I allow for a mouse click which would add a new graphic point at that location. I have the mouse event and the location recognized and have created a graphic symbol (a point) at that location. What I'm stuck on is now having that point display on the map. I'm not quite sure what notifier I need to use so that the map can know there was a change and then display that change.
display_a_map.cpp
void Display_a_map::mapClickHandler(QMouseEvent &event)
{
Point clickedPoint = m_mapView->screenToLocation(event.x(), event.y());
GraphicsOverlay* overlay = new GraphicsOverlay(this);
createGraphics(overlay, clickedPoint.x(), clickedPoint.y());
m_mapView->graphicsOverlays()->append(overlay);
//Point graphic created. Now needs to be displayed
}
void Display_a_map::createGraphics(GraphicsOverlay *overlay)
{
const Point dume_beach(-118.80657463861, 34.0005930608889, SpatialReference::wgs84());
//const Point dume_beach(pointX, pointY, SpatialReference::wgs84());
// Create symbols for the point
SimpleLineSymbol* point_outline = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor(Qt::blue), 3, this);
SimpleMarkerSymbol* point_symbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, QColor(Qt::blue), 10, this);
point_symbol->setOutline(point_outline);
// Create a graphic to display the point with its symbology
Graphic* point_graphic = new Graphic(dume_beach, point_symbol, this);
// Add point graphic to the graphics overlay
overlay->graphics()->append(point_graphic);
}
Solved! Go to Solution.
Hello @johnmarker ,
No notifier is necessary in this situation as your m_mapView is bound to your MapQuickView in QML which will automatically update once a graphic is added to your overlay which you already appended to your m_mapView (this assumes you are using the tutorial code/default template for Qt Quick C++ provided by the sdk install). ArcGIS basemaps are mostly Web Mercator and not WGS84 so I am guessing this is an unintended projection issue. You could specify the spatial reference of the Point "dume_beach" e.g.
const Point dume_beach(pointX, pointY, SpatialReference::webMercator());
but this is not needed because the point will honor the spatial reference from your basemap once added to the overlay. So the following would work just as well in your case:
const Point dume_beach(pointX, pointY);
Sincerely,
Jared
Hello @johnmarker ,
No notifier is necessary in this situation as your m_mapView is bound to your MapQuickView in QML which will automatically update once a graphic is added to your overlay which you already appended to your m_mapView (this assumes you are using the tutorial code/default template for Qt Quick C++ provided by the sdk install). ArcGIS basemaps are mostly Web Mercator and not WGS84 so I am guessing this is an unintended projection issue. You could specify the spatial reference of the Point "dume_beach" e.g.
const Point dume_beach(pointX, pointY, SpatialReference::webMercator());
but this is not needed because the point will honor the spatial reference from your basemap once added to the overlay. So the following would work just as well in your case:
const Point dume_beach(pointX, pointY);
Sincerely,
Jared
Yeah that worked thanks. Out of curiosity then, why in those tutorials do the use a spatial refence of WGS84?
@johnmarker That is a great question. I don't have a specific answer as to why that decision was made but it does demonstrate that the geometry is reprojected on the fly. The problem in your case is that Point returned from:
m_mapView->screenToLocation(event.x(), event.y());
is in the spatial reference of your map which is web mercator and not wgs84. I can definitely see how this might be misleading though. I am currently fielding some input from other members of the runtime team to see if there is anything else I can add to this.
Sincerely,
Jared
@JaredCaccamo I appreciate it.
I have tried to do the same thing I just did with the Point graphic, but with the Polyline and it is not displaying. I have made sure the spatial reference was correct too.
void Display_a_map::mapClickHandler(QMouseEvent &event)
{
Point clickedPoint = m_mapView->screenToLocation(event.x(), event.y());
GraphicsOverlay* overlay = new GraphicsOverlay(this);
if(event.button() == Qt::LeftButton)
{
createPoint(overlay, clickedPoint.x(), clickedPoint.y());
}
else if( event.button() == Qt::RightButton)
{
createPolyline(overlay, clickedPoint.x(), clickedPoint.y());
}
m_mapView->graphicsOverlays()->append(overlay);
}
void Display_a_map::createPolyline(GraphicsOverlay* overlay, double pointX, double pointY)
{
const Point clickedPoint(pointX, pointY);
PolylineBuilder* polyline_builder = new PolylineBuilder(SpatialReference::webMercator());
polyline_builder->addPoint(clickedPoint);
// Create a symbol for the line
SimpleLineSymbol* line_symbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor(Qt::blue), 10, this);
// Create a graphic to display the line with its symbology
Graphic* polyline_graphic = new Graphic(polyline_builder->toPolyline(), line_symbol, this);
// Add line graphic to the graphics overlay
overlay->graphics()->append(polyline_graphic);
}
Hello @johnmarker ,
The primary problem is that your polyline_builder only ever contains one point when added as a graphic since it is destructed once
Display_a_map::createPolyline
goes out of scope. If you make a it a member variable of your class Display_a_map, then you would be able to add subsequent clicks to the builder and then the polyline should show as it has more than one point. Also might I suggest to pass the clickPoint as a parameter to createPoint and createPolyline rather then creating the point, breaking into parts(x and y), then creating the point again. E.g.:
void createPolyline(GraphicsOverlay* overlay, const Point& clickedPoint)
{...}
Sincerely,
Jared
@JaredCaccamo That makes sense with it going out of scope and will be an easy fix.