ThinkGeo.com    |     Documentation    |     Premium Support

Custom line dash style (power line, rail road)

Hey,

I’m trying to create custom dash style for lines but can’t find too much information on how to go about it. I tried to use LineDashStyle.Custom and then add a few LineStyles to CustomLineStyles collection. Seems that all styles are applied “at once” and I just can’t come up with satisfactory results… :frowning:

I’d need to implement the following:

style2
style1

Any help? Thanks.

Seems like I managed to solve this by myself. I’ll post the code here in case someone else needs something similar.

layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyle.CreateSimpleLineStyle(
    GeoColors.Black, 3, LineDashStyle.Solid,
    GeoColors.Black, 3, LineDashStyle.Solid,
    GeoColors.Black, 12, LineDashStyle.Custom,
    true);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.DashPattern.Clear();
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.DashPattern.Add(0.05f);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.DashPattern.Add(1.6f);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.StartCap = DrawingLineCap.Flat;
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.EndCap = DrawingLineCap.Flat;

style4

layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyle.CreateSimpleLineStyle(
    GeoColors.Transparent, 0, LineDashStyle.Solid,
    GeoColors.White, 3, LineDashStyle.Dash,
    GeoColors.Black, 6, LineDashStyle.Solid,
    true);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.InnerPen.DashPattern.Clear();
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.InnerPen.DashPattern.Add(1f);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.InnerPen.DashPattern.Add(1f);
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.InnerPen.StartCap = DrawingLineCap.Flat;
layer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.InnerPen.EndCap = DrawingLineCap.Flat;

style3

Hey @Mikko_Viitala,

Glad you were able to figure out the dash styles on your own and thank you for posting your solution! I think it would be fitting for us to update our samples to include more detail on how to do more complex LineStyles for future reference.

To expand on this a bit more, you really only need the inner and outer pen to achieve your results, no need for the center pen as you’ve already figured out. Additionally, I would recommend using the normal LineStyle constructor when it comes to more complex line styles, like dash lines, since it gives you better control over how each pen is drawn. Below is some example code that achieves similar results:

var lineStyle = new LineStyle(
    outerPen: new GeoPen(GeoColors.Black, 16)
    {
        DashStyle = LineDashStyle.Custom,
        DashPattern = { 0.2f, 5f },
        StartCap = DrawingLineCap.Flat,
        EndCap = DrawingLineCap.Flat
    },
    innerPen: new GeoPen(GeoColors.Black, 4)
);

image

var lineStyle = new LineStyle(
    outerPen: new GeoPen(GeoColors.Black, 12),
    innerPen: new GeoPen(GeoColors.White, 6)
    {
        DashStyle = LineDashStyle.Custom,
        DashPattern = { 3f, 3f },
        StartCap = DrawingLineCap.Flat,
        EndCap = DrawingLineCap.Flat
    }
);

image

Thanks,
Kyle

1 Like

Thanks. Seems like I took the harder way around :smiley:

Another issue I faced is clustering so maybe I ask it here even it’s not related to original topic.

I have an overlay which has multiple layers on it containing multilines. Now to get clustering working I’m extracting center point of each feature, put those on separate layer, and do cluster styling based on those points. Is there any way to cluster the original multilines without the extra effort?

Hey @Mikko_Viitala,

No worries, considering where you started out, you still achieved the same result. And sometimes, that’s all you need.

For your follow-up question, I think you are going in the right direction since only points are supported for clustering and you are dealing with multiple layers at a time with a potential of overlapping areas.

Alternatively, you could extend the ClusterPointStyle class and override the DrawCore method that converts any features that would be drawn to the center point of that feature instead. Something like:

public class CenterPointClusterStyle : ClusterPointStyle
{
    public CenterPointClusterStyle(PointStyle pointStyle, TextStyle textStyle)
        : base(pointStyle, textStyle) { }

    protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
    {
        var centerPointFeatures = new Collection<Feature>();
        foreach (var feature in features)
        {
            var centerFeature = new Feature(feature.GetShape().GetCenterPoint(), feature.ColumnValues);
            centerPointFeatures.Add(centerFeature);
        }
        base.DrawCore(centerPointFeatures, canvas, labelsInThisLayer, labelsInAllLayers);
    }
}

The only limitation to this is that it only applies to a single layer at a time. Since you have multiple layers in your overlay, this might not be what you are looking for. But this might give you an idea of how to solve this more efficiently without having to create brand new point layers.

Thanks,
Kyle

1 Like