graphics with height / extruded graphics

1262
11
Jump to solution
06-02-2017 05:39 AM
NorbertThoden
Occasional Contributor III

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

0 Kudos
1 Solution

Accepted Solutions
LukeSmallwood
Esri Contributor

... 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.

View solution in original post

11 Replies
LukeSmallwood
Esri Contributor

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

NorbertThoden
Occasional Contributor III

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

0 Kudos
LukeSmallwood
Esri Contributor

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();
}
0 Kudos
NorbertThoden
Occasional Contributor III

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?

0 Kudos
LukeSmallwood
Esri Contributor

... 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.

NorbertThoden
Occasional Contributor III

Yeah, great - thats it!

Luke, thanks a lot

And have a nice weekend

Many greetings from Germany

Norbert

0 Kudos
NorbertThoden
Occasional Contributor III

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!

0 Kudos
LukeSmallwood
Esri Contributor

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

NorbertThoden
Occasional Contributor III

Hi!

Thanks!

I am using "props.setExtrusionMode(Esri::ArcGISRuntime::ExtrusionMode::BaseHeight);"

I will switch to Absolute and let you know the results....