deep copy at Esri::ArcGISRuntime::Graphic::setSymbol() ?

470
3
10-17-2019 07:50 AM
NorbertThoden
Occasional Contributor III

Hi!
We assign the symbol like this:

{

  ..

  QSharedPointer<Esri::ArcGISRuntime::SimpleFillSymbol> simpleFillSym = convert(m_fillStyle.value(), simpleLineSym);
  m_graphic->setSymbol(simpleFillSym.data());

}

So the simpleFillSym is destroyed directly at setSymbol() at "}".

It this safe, because setSymbol create a deep copy?

Thx

0 Kudos
3 Replies
JamesBallard1
Esri Regular Contributor

Hi Norbert Thoden‌.

In this case it is not a deep copy. What you're doing does work (as you've found), but that's only because we have some internal caching in our pimpl classes that prevent the internal symbol object from being deleted.

So yes, that will technically work but I would not rely upon that behavior. It is not a deep copy and I would not write code to assume this can be safely done.

NorbertThoden
Occasional Contributor III

Hi!
Waht do you think about this approach?

bool AbstractGraphicalObject::assignFillStyleToGraphic()
{
if (!m_graphic)
   return false;

const LineStyle &ls = m_lineStyle.value();
const FillStyle &fs = m_fillStyle.value();

if (!m_graphic->symbol())
{
   Esri::ArcGISRuntime::SimpleFillSymbol *sfs =     new Esri::ArcGISRuntime::SimpleFillSymbol(convert(fs.fillPattern()), fs.fillColor(), 

   new Esri::ArcGISRuntime::SimpleLineSymbol(convert(ls.linePattern()), ls.lineColor(), ls.lineWidth() *   m_scale.value(), m_graphic), m_graphic);
m_graphic->setSymbol(sfs);
}

Esri::ArcGISRuntime::SimpleFillSymbol *sfs = static_cast<Esri::ArcGISRuntime::SimpleFillSymbol*>(m_graphic->symbol());
sfs->setStyle(convert(fs.fillPattern()));
sfs->setColor(fs.fillColor());

Esri::ArcGISRuntime::SimpleLineSymbol *sls = static_cast<Esri::ArcGISRuntime::SimpleLineSymbol*>(sfs->outline());
if (!sls)
   return false;
sls->setStyle(convert(ls.linePattern()));
sls->setColor(ls.lineColor());
sls->setWidth(ls.lineWidth() * m_scale.value());

return true;
}

0 Kudos
JamesBallard1
Esri Regular Contributor

Norbert Thoden‌, speaking specifically to object lifetime and when it is safe to delete the graphics and symbols, then yes your code looks good. When the graphic is deleted then its symbol will get deleted along with it.

Another technique we use on the team is to have QObject parents that track multiple objects. For example we might add something like this:

QObject* m_graphicsParent = nullptr;

...

void resetGraphics()

{

  m_graphicsOverlay->clear(); // remove all graphics

  delete m_graphicsParent; // force all removed graphics to delete

  m_graphicsParent = new QObject(this);

  for (int i = 0; i < 1000; i++) // 1000 is arbitrary for this example

  {

    // create new graphics/symbols with the special parent

    auto* graphic = new Graphic(m_graphicsParent);

    // add symbols...

    m_graphicsOverlay->append(graphic);

  }

}

That way we can keep one parent for all related objects to force their deletion all at the same time when we're through with them.

0 Kudos