How to label Features in FeatureCollectionTable

1037
3
Jump to solution
04-16-2018 08:39 AM
VishnuB
New Contributor III

How to label features in FeatureCollectionTable? I am using ArcGIS Runtime for Qt. Kindly share a sample code if possible.

Thanks in advance.

0 Kudos
1 Solution

Accepted Solutions
TroyFoster
Occasional Contributor
  1. add a field name to your FeatureCollectionTable, this is the field you want to label from, in my case I had a QString NAME_FIELD.

    QList<Field> fieldNames;
    fieldNames.push_back(Field::createText(NAME_FIELD, NAME_FIELD, NAME_LENGTH));
    labelFeatureTable = new FeatureCollectionTable(fieldNames, GeometryType::Point, spatialReference, this);

  2. Create a renderer for the FeatureCollectionTable, my table is point based so the renderer has a simple marker symbol, which is hidden to the user

    // empty point which is the anchor marker for the label
    SimpleMarkerSymbol *simpleSym = new SimpleMarkerSymbol(this);
    simpleSym->setSize(0.0);

  3. Create a symbol for your text labels, this is what goes into the label definition

    TextSymbol* textSym = new TextSymbol("text", color, 12, HorizontalAlignment::Left, VerticalAlignment::Middle, this);

  4. Do the json magic to do label definitions

    FeatureLayer *labelLayer = labelFeatureTable->featureLayer();
    if (labelLayer != NULL)
    {
    LabelDefinitionListModel* labelDefinitions =
    labelLayer->labelDefinitions();
    if (labelDefinitions != NULL)
    {
    QJsonObject obj;

    QJsonDocument textDoc = QJsonDocument::fromJson(
    textSym->toJson().toUtf8());

    // https://developers.arcgis.com/web-map-specification/objects/labelingInfo/
    obj.insert(QString("symbol"), textDoc.object());

    QString labelExpression = QString("$feature.") + NAME_FIELD;
    QJsonObject labelExpressionObj;

    labelExpressionObj.insert(QString("expression"), labelExpression);
    obj.insert(QString("labelExpressionInfo"), labelExpressionObj);
    obj.insert(QString("deconflictionStrategy"), QString("none"));
    obj.insert(QString("labelPlacement"),
    QString("esriServerPointLabelPlacementAboveRight"));
    obj.insert(QString("maxScale"), 0);
    obj.insert(QString("minScale"), 0);
    obj.insert(QString("useCodedValues"), true);
    QJsonDocument newDoc(obj);

    Esri::ArcGISRuntime::LabelDefinition* newlabelDef =
    Esri::ArcGISRuntime::LabelDefinition::fromJson(
    newDoc.toJson(QJsonDocument::Indented));

    if (newlabelDef != NULL)
    {

    labelLayer->labelDefinitions()->append(newlabelDef);

    }
    else
    {
    cout << "newlabelDef == NULL" << endl;
    }
    }
    else
    {
    cout << "labelDefinitions == NULL" << endl;

    }
    }
    else
    {
    cout << "labelLayer == NULL" << endl;
    }

Apparently my indentation did not carry over but hopefully this helps.  I had some issues when I first started programming this so that is why I NULL check everything.  I used QJsonObject so I wouldnt need to be careful escaping quote characters in text based json.

View solution in original post

3 Replies
TroyFoster
Occasional Contributor
  1. add a field name to your FeatureCollectionTable, this is the field you want to label from, in my case I had a QString NAME_FIELD.

    QList<Field> fieldNames;
    fieldNames.push_back(Field::createText(NAME_FIELD, NAME_FIELD, NAME_LENGTH));
    labelFeatureTable = new FeatureCollectionTable(fieldNames, GeometryType::Point, spatialReference, this);

  2. Create a renderer for the FeatureCollectionTable, my table is point based so the renderer has a simple marker symbol, which is hidden to the user

    // empty point which is the anchor marker for the label
    SimpleMarkerSymbol *simpleSym = new SimpleMarkerSymbol(this);
    simpleSym->setSize(0.0);

  3. Create a symbol for your text labels, this is what goes into the label definition

    TextSymbol* textSym = new TextSymbol("text", color, 12, HorizontalAlignment::Left, VerticalAlignment::Middle, this);

  4. Do the json magic to do label definitions

    FeatureLayer *labelLayer = labelFeatureTable->featureLayer();
    if (labelLayer != NULL)
    {
    LabelDefinitionListModel* labelDefinitions =
    labelLayer->labelDefinitions();
    if (labelDefinitions != NULL)
    {
    QJsonObject obj;

    QJsonDocument textDoc = QJsonDocument::fromJson(
    textSym->toJson().toUtf8());

    // https://developers.arcgis.com/web-map-specification/objects/labelingInfo/
    obj.insert(QString("symbol"), textDoc.object());

    QString labelExpression = QString("$feature.") + NAME_FIELD;
    QJsonObject labelExpressionObj;

    labelExpressionObj.insert(QString("expression"), labelExpression);
    obj.insert(QString("labelExpressionInfo"), labelExpressionObj);
    obj.insert(QString("deconflictionStrategy"), QString("none"));
    obj.insert(QString("labelPlacement"),
    QString("esriServerPointLabelPlacementAboveRight"));
    obj.insert(QString("maxScale"), 0);
    obj.insert(QString("minScale"), 0);
    obj.insert(QString("useCodedValues"), true);
    QJsonDocument newDoc(obj);

    Esri::ArcGISRuntime::LabelDefinition* newlabelDef =
    Esri::ArcGISRuntime::LabelDefinition::fromJson(
    newDoc.toJson(QJsonDocument::Indented));

    if (newlabelDef != NULL)
    {

    labelLayer->labelDefinitions()->append(newlabelDef);

    }
    else
    {
    cout << "newlabelDef == NULL" << endl;
    }
    }
    else
    {
    cout << "labelDefinitions == NULL" << endl;

    }
    }
    else
    {
    cout << "labelLayer == NULL" << endl;
    }

Apparently my indentation did not carry over but hopefully this helps.  I had some issues when I first started programming this so that is why I NULL check everything.  I used QJsonObject so I wouldnt need to be careful escaping quote characters in text based json.

VishnuB
New Contributor III

Thanks for your reply.

Labels got displayed, but in my case the labels will be always moving and when one label overlaps with other, only one label is displayed and rest of the overlapped labels will be hidden. Is it possible to change the position of the labels if it gets overlapped while moving?

0 Kudos
TroyFoster
Occasional Contributor

deconflictionStrategy has a few different options, I recommend going into the documentation for the json magic https://developers.arcgis.com/web-map-specification/objects/labelingInfo/ and seeing what the different options are and experimenting with them.  I think there also is a priority argument where you can specify which labels should be preferably displayed over others.  For that you would want to set up another field in your table and then have multiple labelDefinitions using a where statement for each one.

0 Kudos