Label Not Consistently Moving With Symbol On GraphicsOverlay

1229
5
03-25-2020 07:20 AM
KyleGruber
Occasional Contributor II

Runtime Team,

(Using Esri.ArcGISRuntime 100.6/WPF)

I have an application where I'm showing various assets (vehicles, people, etc) moving around a map.  To accomplish this, I'm using a GraphicsOverlay with a UniqueValueRenderer.  Everything seems to be working well, except when I'm zoomed in on an asset (zoom level doesn't seem to make a difference), the defined label is not always moving along with the symbol.  This seems that it may have something to do with label weights, and the label waiting to be in an area where it has enough room to render.  I need this label to always be moving along with the graphic, even if it is showing up on top of other labels defined in the map, I'm guessing this may be something I'm missing in the label definition?

Label Lagging Behind

See in the image how the label G15 is significantly behind the symbol.  Eventually, it will seemingly randomly catch up to it.

 StringBuilder gphLabelsBuilder = new StringBuilder();
            gphLabelsBuilder.AppendLine("{");
            //     Define a labeling expression that will show the unit attribute value
            gphLabelsBuilder.AppendLine("\"labelExpressionInfo\": {");
            gphLabelsBuilder.AppendLine("\"expression\": \"return $feature.Header;\"},");
            //     Align labels horizontally
            gphLabelsBuilder.AppendLine("\"labelPlacement\": \"esriServerPointLabelPlacementAboveCenter\",");
            //     Use a green bold text symbol
            gphLabelsBuilder.AppendLine("\"symbol\": {");
            gphLabelsBuilder.AppendLine("\"color\": [0,0,0,255],");
            gphLabelsBuilder.AppendLine("\"font\": {\"size\": 10, \"weight\": \"bold\"},");
            gphLabelsBuilder.AppendLine("\"haloColor\": [255,255,255,255],");
            gphLabelsBuilder.AppendLine("\"haloSize\": 1,");
            gphLabelsBuilder.AppendLine("\"type\": \"esriTS\"}");
            gphLabelsBuilder.AppendLine("}");
            GraphicOverlay.LabelsEnabled = true;
            GraphicOverlay.LabelDefinitions.Add(LabelDefinition.FromJson(gphLabelsBuilder.ToString()));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 This is how the label is being defined, the GraphicOverlay object is of type GraphicsOverlay with the rendering mode dynamic.

Hopefully an obvious property I'm missing in the label definition JSON?

EDIT:  If it matters, I'm updating the graphic location by grabbing the Graphic from the GraphicsOverlay by its unique identifier (FirstOrDefault with Label), and setting the Geometry property to a new MapPoint created with the new coordinates.

Furthermore, I would like to ask if this is the best practice for displaying rapidly changing data on a map?  All examples I've been able to find on anything relatively close to this use case seem to use GraphicsOverlays/Symbols, but I wanted to see if there's a known better practice.

0 Kudos
5 Replies
Nicholas-Furness
Esri Regular Contributor

Take a look at the label definition I came up with for a custom cluster layer implementation: clusterlayer-plugin-ios/AGSLabelDefinition+TextSymbol.swift at runtime-100 · nixta/clusterlayer-plug... 

In particular, I wonder if "deconflictionStrategy":"none" might help?

See also: labelingInfo | ArcGIS for Developers 

0 Kudos
KyleGruber
Occasional Contributor II

Thanks Nicholas!  Checking if deconflictionStrategy makes a difference, if not, I'll dig further into the custom cluster layer label definition.

0 Kudos
Nicholas-Furness
Esri Regular Contributor

I hadn't read your whole question though: Yes. GraphicsOverlays and Graphics are a good way to do rapidly updating ad-hoc data on the map.

You might also consider a dedicated point graphic for the label and symbolize it with a TextSymbol rather than using labeling. But I do suspect you'll get some mileage out of the deconflictionStrategy.

KyleGruber
Occasional Contributor II

Nicholas,

Thank you so much for the help and recommendations.  The issue appears to be fixed (it needs further testing, but so far I've gone way longer without reproducing the issue than I ever have).  Using deconflictionStrategy doesn't appear to be the full story, as just adding that didn't seem to have any effect.  Unfortunately, I have now thrown out the kitchen sink and I'm now generating the label using the guide here:

https://community.esri.com/community/developers/native-app-developers/arcgis-runtime-sdk-for-net/blo... 

which I just now noticed appears to be using labelPosition in place of deconflictionStrategy (not sure if they're the same thing but they have the same enum values (Dynamic/None/Static)?

{
   "labelExpressionInfo":{
      "expression":"return $feature.Header;"
   },
   "allowOverrun":false,
   "labelPosition":"none",
   "labelExpression":null,
   "ArcadeExpression":"return $feature.Header;",
   "labelPlacement":"esriServerPointLabelPlacementAboveCenter",
   "minScale":0,
   "maxScale":0,
   "name":null,
   "priority":0,
   "removeDuplicates":"none",
   "removeDuplicatesDistance":0,
   "repeatLabel":false,
   "repeatLabelDistance":0,
   "stackLabel":false,
   "stackAlignment":"textSymbol",
   "useCodedValues":false,
   "where":null,
   "symbol":{
      "angle":0,
      "backgroundColor":[
         0,
         0,
         0,
         0
      ],
      "borderLineColor":[
         0,
         0,
         0,
         0
      ],
      "borderLineSize":0,
      "color":[
         0,
         0,
         0,
         255
      ],
      "font":{
         "decoration":"none",
         "size":7.5,
         "style":"normal",
         "weight":"bold"
      },
      "haloColor":[
         255,
         255,
         255,
         255
      ],
      "haloSize":0.75,
      "horizontalAlignment":"center",
      "kerning":false,
      "type":"esriTS",
      "verticalAlignment":"top",
      "xoffset":0,
      "yoffset":0
   }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
KyleGruber
Occasional Contributor II

After further testing, none of the above resolved the issue.

What resolved the issue was making the GraphicsOverlay rendering static as opposed to dynamic.  This requires creating a new symbol for every graphic (otherwise changing for instance the angle of one symbol changes it for them all) instead of caching and reusing a single symbol in-memory, but otherwise seems to work perfectly.

So, to sum everything up, I have no idea why the label drift issue occurs with dynamic rendering mode in a GraphicsOverlay, but it only seems to be an issue with dynamic rendering.

Of course, I have further questions on this... is this information still true for 100.6+?

Graphics rendering modes—ArcGIS Runtime SDK for .NET | ArcGIS for Developers 

I can't seem to find this specific information in the latest guide for .NET.  If this still holds true, this is telling me I should be using dynamic rendering mode for my use case, but that the results can potentially differ based on the GPU capabilities of the machine.  While the machine I was testing on has a high-end GPU, like many people right now I'm doing all my work remotely, so I was connected via RDP into the machine which at least WPF tells the application to use all CPU rendering.

0 Kudos