Hello everyone,
I'm working on a project where I need to draw zigzag lines of a fixed length on a map. The zigzag pattern needs to dynamically adjust based on the zoom level of the map.
Currently, I've implemented this functionality using a PolylineBuilder to construct the zigzag pattern and re-drawing the line every time the zoom level changes, by handling the MapView.ViewpointChanged event.
While this approach works, I’ve encountered significant performance issues when trying to draw and manage several hundred zigzag lines simultaneously. The frequent re-drawing process slows down the application considerably.
I'm looking for suggestions or best practices to improve the efficiency of this process. Specifically:
Is there a way to optimize the re-drawing of multiple polylines based on zoom level?
Are there any advanced techniques or patterns in the Esri ArcGIS Runtime SDK for .NET that could help minimize performance overhead?
Any guidance, examples, or advice would be greatly appreciated!
Here is the code I used to draw and update the zigzag lines:
private void DrawZigZag(string id, double originLatitude, double originLongitude, double rotationAngle)
{
// Get the current map scale for scaling
double mapScale = this.mapMainService.mapView.MapScale;
double scalingFactor = Math.Max(1, mapScale / 500000); // Adjust divisor for sensitivity
// Zigzag appearance configuration
double totalDistanceKm = 150 * 1.852; // Total length (150 nautical miles converted to kilometers)
double zigzagLongitudeDisplacement = 0.01 * scalingFactor; // Horizontal displacement
double segmentDistanceKm = 1.0 * scalingFactor; // Vertical increment
double zigzagLatitudeIncrement = segmentDistanceKm / 111.0; // Convert km to degrees (approximation)
// Convert rotation angle to radians (for CW rotation)
double angleRadians = Math.PI * (-rotationAngle) / 180.0;
double cosAngle = Math.Cos(angleRadians);
double sinAngle = Math.Sin(angleRadians);
// Create a PolylineBuilder
PolylineBuilder pb = new PolylineBuilder(SpatialReferences.Wgs84);
// Starting point (relative coordinates)
double startX = 0.0;
double startY = 0.0;
// Calculate the number of segments
double totalSegments = totalDistanceKm / segmentDistanceKm;
List<MapPoint> points = new List<MapPoint>(); // To store all points for center calculation
// Generate zigzag points
for (int i = 0; i < totalSegments; i++)
{
double x = startX;
double y = startY;
if (i % 2 == 0)
{
x += zigzagLongitudeDisplacement;
}
else
{
x -= zigzagLongitudeDisplacement;
}
y += zigzagLatitudeIncrement;
// Rotate the point
double rotatedX = x * cosAngle - y * sinAngle;
double rotatedY = x * sinAngle + y * cosAngle;
// Convert to geographic coordinates
double rotatedLongitude = originLongitude + rotatedX;
double rotatedLatitude = originLatitude + rotatedY;
// Add the rotated point to the polyline
pb.AddPoint(new MapPoint(rotatedLongitude, rotatedLatitude));
// Update starting coordinates for the next iteration
startX = x;
startY = y;
}
// Create a polyline
Polyline polyline = pb.ToGeometry();
// Create a symbol for the polyline
var lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.Red, 2);
// Create attributes for label
List<KeyValuePair<string, object?>> attributes = new List<KeyValuePair<string, object?>>()
{
new KeyValuePair<string, object?>("name", id.ToString()[..10]),
new KeyValuePair<string, object?>("name", id.ToString()[..10])
};
// Create a graphic and add it to the overlay
Graphic polylineGraphic = new Graphic(polyline, attributes, lineSymbol)
{
};
this.GraphicsOverlay.Graphics.Add(polylineGraphic);
}
public void UpdateZigZags()
{
// Clear all graphics to redraw
this.GraphicsOverlay.Graphics.Clear();
// Redraw each zigzag with the updated scale
foreach (var kvp in this.zigZagLines)
{
var id = kvp.Key;
var (latitude, longitude, rotation) = kvp.Value;
DrawZigZag(id, latitude, longitude, rotation);
}
}
Thank you in advance!