Dynamic labels on Polyline


How I can implement the dynamic behavior of polyline labels when the map is moved. To keep labels always in the middle of the visible line on the map.
What can be done?



The map itself does not support dynamic labeling. However, you can call GenerateLabels whenever you think it is necessary. I have played with labels for our Roads and Buildings so that outside of a specific zoom level, I set AvoidCollisions = True and display road labels on the longest segment only. Then when zooming in beyond that level, I set AvoidCollisions = False to make sure all Buildings (and at least most Road segments) have their labels displayed.

Of course, the most dynamic, (I have tried this, and depending on your map, is not very painful) is to re-GenerateLabels on every change of map extents (I do it in the BeforeLayers map event, just before the layers are drawn, where I can check the current scale and make decisions accordingly).

I hope that helps.



OK. Thanks, I will try. I hope the constant generation of labels will not be very loading processor. There are not so many streets. It would not be bad to generate them only for visible parts of the lines on the screen. That would be perfect. Because the generation of labels for the whole layer, if it makes a big one think about the program for a long time. In other GIS, this is much easier. I think they generate them on the fly, for visible parts on the screen. Well, thanks for the good thoughts, I will work on it.



Is there a method to calculate all currently displayed objects on the visible part of the TMap rectangle on the screen, for example, all polylines? For example, determine which ones are on the screen now and generate labels only for them.



Tried. No it’s wrong. I must dynamically calculate the length of the line between two points of the cropped visible parts of the screen. And on this site generate Labels. I think someone can help me with that. Determine the points where the lines are cut on the visible part of the rectangle, calculate these lines, let’s add them to the array and generate labels for them dynamically. This of course can be added to the functionality of MapWinGIS. But you can also implement it in the client itself, if you help me make the correct calculations. Thanks.



You can use Map.Extents to get the current view rectangle.
Then you can clip your polylines with this rectangle to get only the parts in view.
Next, you can use sf.Labels.AddLabel() to add the label at a specific location.

Will that work for you?



In theory, everything looks right. Now you need to try it in practice. As I experiment, I will unsubscribe. That I will succeed.
The truth is not quite clear how to use the Clip function … and copy all the polylines in a rectangle



This should work (C#):

const string filename = @"sf/clipByMapExtents.shp";
var handle = _axMap1.AddLayerFromFilename(filename, tkFileOpenStrategy.fosVectorLayer, true);
Assert.IsTrue(handle != -1, "Could not load layer: " + _axMap1.get_ErrorMsg(_axMap1.LastErrorCode));
var sf = _axMap1.get_Shapefile(handle);

// Zoom in:

// Make shape from map extents:
var clipShape = _axMap1.Extents.ToShape();
Assert.IsNotNull(clipShape, "Could not make shape from map extents");
// Make in-memory shapefile from shape:
var sfClip = new Shapefile();
if (!sfClip.CreateNewWithShapeID("", ShpfileType.SHP_POLYGON))
    Assert.Fail("Can't create shapefile. Error: " + sfClip.ErrorMsg[sfClip.LastErrorCode]);
// Set projection:
sfClip.GeoProjection = _axMap1.GeoProjection.Clone();
var shpIndex = sfClip.EditAddShape(clipShape);
Assert.IsTrue(shpIndex != -1, "Could not add shape: " + sfClip.ErrorMsg[sfClip.LastErrorCode]);

// Clip:
var sfResult = sf.Clip(false, sfClip, false);

Assert.AreNotEqual(sf.NumShapes, sfResult.NumShapes, "No shapes were clipped.");

Now you have your clipped shapefile for which you can make your labels.