I like to create a cube on a graphicsOverlay in a sceneView (3D) - but without success.
I just can see the plane area drapped on the surface.
I don´t use QML but widget based approach.
What i did:
Create a scene, sceneView connect them and so...
d->m_graphicsLayer->setSceneProperties(Esri::ArcGISRuntime::LayerSceneProperties(Esri::ArcGISRuntime::SurfacePlacement::Draped)); const Esri::ArcGISRuntime::SpatialReference &sr = d->m_mapImpl->getEsriSpatialReference(); // create 4 point for rectangle const Esri::ArcGISRuntime::Viewpoint &vp = d->m_mapGeoView->currentViewpoint(Esri::ArcGISRuntime::ViewpointType::CenterAndScale); const Esri::ArcGISRuntime::Point &mapCenter = static_cast<Esri::ArcGISRuntime::Point>(vp.targetGeometry()); ... SituationMap::PositionCont posContTrans = ...; Esri::ArcGISRuntime::PolygonBuilder builder(sr, this); int z = 1000; builder.addPoint(Esri::ArcGISRuntime::Point(posContTrans[0].x(), posContTrans[0].y(), z, sr)); builder.addPoint(Esri::ArcGISRuntime::Point(posContTrans[1].x(), posContTrans[1].y(), z, sr)); builder.addPoint(Esri::ArcGISRuntime::Point(posContTrans[2].x(), posContTrans[2].y(), z, sr)); builder.addPoint(Esri::ArcGISRuntime::Point(posContTrans[3].x(), posContTrans[3].y(), z, sr)); qCritical() << " posContTrans=" << posContTrans[0]; qCritical() << " posContTrans=" << posContTrans[1]; qCritical() << " posContTrans=" << posContTrans[2]; qCritical() << " posContTrans=" << posContTrans[3]; Esri::ArcGISRuntime::SimpleFillSymbol* sls = new Esri::ArcGISRuntime::SimpleFillSymbol(Esri::ArcGISRuntime::SimpleFillSymbolStyle::Solid, Qt::red, this); Esri::ArcGISRuntime::SimpleRenderer *renderer = new Esri::ArcGISRuntime::SimpleRenderer(sls, this); Esri::ArcGISRuntime::RendererSceneProperties props = renderer->sceneProperties(); props.setExtrusionMode(Esri::ArcGISRuntime::ExtrusionMode::BaseHeight); props.setExtrusionExpression(QLatin1String("height")); renderer->setSceneProperties(props); d->m_graphicsLayer->setRenderer(renderer); Esri::ArcGISRuntime::Graphic *graphic = new Esri::ArcGISRuntime::Graphic( Esri::ArcGISRuntime::Polygon(builder.toGeometry())Create , this); QVariantMap att = graphic->attributes()->attributesMap(); att[QLatin1String("height")] = 1000000; d->m_graphicsLayer->graphics()->append(graphic);
I tried the RenderingMode::Static and also Dynamic.. No height is visible.
What is missing?
Can someone help me?
Thx
Norbert
Solved! Go to Solution.
... and I think the issue in your original code block is with this segment of the code:
QVariantMap att = graphic->attributes()->attributesMap();
att[QLatin1String("height")] = 1000000;
the QVariantMap is not returned by reference - therefore you need to call
graphic->attributes()->setAttributesMap(att);
to apply the height attribute to your graphics.
Hi Norbert,
I think the attribute you use in your extrusion expression needs to be in brackets - e.g.
props.setExtrusionExpression(QLatin1String("[height]"));
If you haven't already taken a look at our "ExtrudeGraphics" sample that might help give you some ideas as well (arcgis-runtime-samples-qt/ArcGISRuntimeSDKQt_CppSamples/Scenes/ExtrudeGraphics at master · Esri/arcg... ). The sample is written with a QtQuick UI but the C++ business logic should be essentially the same.
Please let me know if you are still having issues.
Thanks,
Luke
Hi Luke!
Your answer was very quick - amazing 🙂
Thanks for pointing me to the copyAndPaste error. But unfortunately the behaviour does not change (Static and Dynamic)
Yes, i took the logic from the ExtrudeGraphicsExample(QML)...
There are a couple of known issues for 3D, especially related to Graphics, RedneringMode and so on.
Do you have another hint?
Is there another example?
Thx
Hi Norbert,
Here's a snippet of our ExtrudeGraphics sample re-written for widgets UI. In theory it is possible to copy the toolkit etc. into your Qt kit and run those samples without running the PostInstaller but it is not recommended.
Does this code work for you?
Untitled10::Untitled10(QWidget *parent /*=nullptr*/):
QMainWindow(parent),
m_sceneView(nullptr)
{
// Create a scene using the topographic BaseMap
Scene* scene = new Scene(Basemap::topographic(this), this);
// create a new elevation source from Terrain3D rest service
ArcGISTiledElevationSource* elevationSource = new ArcGISTiledElevationSource(
QUrl("http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"), this);
// add the elevation source to the scene to display elevation
scene->baseSurface()->elevationSources()->append(elevationSource);
// Create a scene view, and pass in the scene
m_sceneView = new SceneGraphicsView(scene, this);
// set the sceneView as the central widget
setCentralWidget(m_sceneView);
// create a camera
Camera camera(28.4, 83.9, 10010.0, 10.0, 80.0, 300.0);
// set the viewpoint
m_sceneView->setViewpointCameraAndWait(camera);
// graphics location
double lon = camera.location().x() - 0.03;
double lat = camera.location().y() + 0.2;
GraphicsOverlay* graphicsOverlay = new GraphicsOverlay(this);
// set renderer with extrusion property
SimpleRenderer* renderer = new SimpleRenderer(this);
RendererSceneProperties props = renderer->sceneProperties();
props.setExtrusionMode(ExtrusionMode::BaseHeight);
props.setExtrusionExpression("[height]");
renderer->setSceneProperties(props);
SimpleFillSymbol* sfs = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("red"), this);
renderer->setSymbol(sfs);
graphicsOverlay->setRenderer(renderer);
// setup graphic locations
QList<Point> pointsList;
for (auto i = 0; i <= 100; i++)
{
Point point(i / 10 * (0.01 * 2) + lon, i % 10 * (0.01 * 2) + lat, m_sceneView->spatialReference());
pointsList.append(point);
}
foreach (auto point, pointsList)
{
// create a random z value
int randNum = rand() % 6 + 1;
double z = 1000 * randNum;
// create a list of points
QList<Point> points;
points << Point(point.x(), point.y(), z)
<< Point(point.x() + 0.01, point.y(), z)
<< Point(point.x() + 0.01, point.y() + 0.01, z)
<< Point(point.x(), point.y() + 0.01, z);
// create a new graphic
Graphic* graphic = new Graphic(createPolygonFromPoints(points), this);
// add a height attribute to the graphic using the attribute list model
// the extrusion will be applied to this attribute. See the expression above
graphic->attributes()->insertAttribute("height", z);
// add the graphic to the graphic overlay
graphicsOverlay->graphics()->append(graphic);
}
m_sceneView->graphicsOverlays()->append(graphicsOverlay);
}
// helper to create polygon from points
Esri::ArcGISRuntime::Polygon Untitled10::createPolygonFromPoints(QList<Point> points)
{
Esri::ArcGISRuntime::Polygon polygon;
if (points.length() == 0)
return polygon;
// create a polygon builder
PolygonBuilder* pb = new PolygonBuilder(m_sceneView->spatialReference(), this);
foreach (auto point, points)
{
// add each point to the builder object
pb->addPoint(point);
}
return polygon = pb->toGeometry();
}
I try to get the QML example ExtrudGraphics running, but:
I don`t like to finish the postInstaller to not influence our project develpment.
And therefore i´m not able to run the example:
I get:
qrc:/Samples/Scenes/Surface_Placement/Surface_Placement.qml:18:1: module "Esri.ArcGISRuntime" is not installed qrc:/Samples/Scenes/Surface_Placement/Surface_Placement.qml:19:1: module "Esri.ArcGISExtras" is not installed qrc:/Samples/Scenes/Surface_Placement/Surface_Placement.qml:18:1: module "Esri.ArcGISRuntime" is not installed qrc:/Samples/Scenes/Surface_Placement/Surface_Placement.qml:19:1: module "Esri.ArcGISExtras" is not installed
How can i set the import/module path/dir for this?
... and I think the issue in your original code block is with this segment of the code:
QVariantMap att = graphic->attributes()->attributesMap();
att[QLatin1String("height")] = 1000000;
the QVariantMap is not returned by reference - therefore you need to call
graphic->attributes()->setAttributesMap(att);
to apply the height attribute to your graphics.
Yeah, great - thats it!
Luke, thanks a lot
And have a nice weekend
Many greetings from Germany
Norbert
Hi!
In the example code your wrote:
att[QLatin1String("height")] = 1000000;
Are values like 10.5 or 10,5 supported?
My experience is that the the ".5" is not used.
If i have a building consisting of 3 floors with an equal height of 2,5m the resulting cubes look not equal:
Do you have any information the the resolution of the values to the attribute "height" / "[height]"?
Or is there maybe a possibility to change the unit from meter to millimeter or similar?
Thank you!
Hi Norbert,
I've just done a small test using polygons with ExtrusionMode::AbsoluteHeight and the height attribute set to be different by 0.5 metres. It seems to be working ok for me (see screenshot).
I'm also printing out the attributes map to check the heights are being set correctly for each polygon
qDebug() << graphic->attributes()->attributesMap(); which gives me the output: QMap(("height", QVariant(double, 10.5))) QMap(("height", QVariant(double, 11))) QMap(("height", QVariant(double, 11.5))) QMap(("height", QVariant(double, 12))) Would you be able to share a simple example form your code?
Thanks,
Luke
Hi!
Thanks!
I am using "props.setExtrusionMode(Esri::ArcGISRuntime::ExtrusionMode::BaseHeight);"
I will switch to Absolute and let you know the results....