ThinkGeo.com    |     Documentation    |     Premium Support

ECW / Raster

Hi,



some more question about raster layer:

If I use a lot of raster files (20+) from one directory / in an overlay I like to display only the files which are in the current extent of my map.

This should reduce memory and speed up performance.



How to set a maximum of Raster to be displayed?



Do you have a code snippet, please?!



Hardy

Hi Hartwig, 
  
 I hope following statements will be helpful: 
  
  
RectangleShape maxExtent = new RectangleShape(-40, 40, 40, -40);
            EcwRasterLayer ecw1 = new EcwRasterLayer(@"…\SampleData\World.ecw");
            ecw1.Open();
            RectangleShape ecw1Box = ecw1.GetBoundingBox();

            if (ecw1Box.Intersects(rect))
            { 
                //ToDo: implement appending this layer.
            }


 
  
 Thanks, 
  
 Lee

Lee,



I think there must be an event to hook up (after zooming, extent chaged, before overlay drawing)  when to check if bounding box intersects the map’s bounding box and to set the ECW invisible.



What time is best to prevent ECW from drawing?



Regards

Hardy

Hi, 
  
 I think that overriding EcwRasterLayer and EcwRasterSource is better way as following statements snippet: 
  
     class CustomizeEcwRasterLayer : EcwRasterLayer
    {
        public CustomizeEcwRasterLayer(string pathName)
        {
            ImageSource = new CustomizeEcwRasterSource(pathName);
        }
    }

    class CustomizeEcwRasterSource : EcwRasterSource
    {
        public CustomizeEcwRasterSource(string Path)
            : base(Path)
        { 
            
        }
        public RectangleShape LimitedBoundingBox
        {
            get;
            set;
        }

        protected override GeoImage GetImageCore(RectangleShape worldExtent, int canvasWidth, int canvasHeight)
        {
            GeoImage image = null;
            if (LimitedBoundingBox != null)
            {
                if (LimitedBoundingBox.Intersects(GetBoundingBox()))
                {
                    image = base.GetImageCore(worldExtent, canvasWidth, canvasHeight);
                }
            }
            return image;
        }
    }
 
 
  
 Thanks,

Hi,



I have found a working solution:

When the Map will draw the Overlays I’m checking if bounding boxes intersects. If not the ecw will be set to invisible.

That’s working well.



Regards

Hardy

Hi Hartwig, 
  
 Actually we did the same thing in the Layer.Draw(…) method, we just get the images in current boundingbox for drawing, could you give more description on this topic on what extent you would like to clip the image? A specific boundingbox or the extent of the map? 
  
 Thanks, 
 Johnny

Hi Johnny,

for me it’s important to check the current map/view extent.

If we have a customer with 100+ ECW’s in one Overlay the performance will be poor when all ECW’s are loaded.

So I define a maximum (4 tiles or 9 tiles for example).



When the user zooms to a feature I will check the bounding boxes.

If a tile is in the view I will set visibility = true and increment my counter +=1. If my counter will become maximum every other tile will be invisible.

So the map is dealing only with 4 or 9 tiles than 100+ and that’s ok for the user because a tile in general is 2 x 2 Km.



Hope my explanation is ok for you.



Regards

Hardy

Hi Hardy,



Thanks for your description, please try the code as following:


public class MultiEcwRasterLayer : RasterLayer
{
    private List<string> filePathNames;
    private Dictionary<EcwRasterLayer, RectangleShape> rasterLayers;
 
    public MultiEcwRasterLayer(IEnumerable<string> ecwFilePathNames)
    {
        this.rasterLayers = new Dictionary<EcwRasterLayer, RectangleShape>();
        this.filePathNames = new List<string>(ecwFilePathNames);
    }
 
    protected override RectangleShape GetBoundingBoxCore()
    {
        RectangleShape bbox = new RectangleShape();
        foreach (var item in rasterLayers)
        {
            bbox.ExpandToInclude(item.Value);
        }
 
        return bbox;
    }
 
    protected override void OpenCore()
    {
        base.OpenCore();
 
        foreach (string filePath in filePathNames)
        {
            EcwRasterLayer ecwRasterLayer = new EcwRasterLayer(filePath);
            ecwRasterLayer.Open();
 
            RectangleShape boundingBox = ecwRasterLayer.GetBoundingBox();
            this.rasterLayers.Add(ecwRasterLayer, boundingBox);
        }
    }
 
    protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
    {
        foreach (var ecwLayer in this.rasterLayers)
        {
            var layerBbox = ecwLayer.Value;
 
            // todo: I guess you can do more check here to improve the performance
            if (ecwLayer.Value.Intersects(canvas.CurrentWorldExtent))
            {
                ecwLayer.Key.Draw(canvas, labelsInAllLayers);
            }
        }
    }
}

Thanks,

Johnny


Hi Johnny,



I think you idea is a good alternative.

I have still done a solution which is working well:

1. Loading ECWs and set them invisible by default

Also set the Attribute “Attribution” from Overlay where ECW-Layers are in to the maximum tile counter (4 for example)



2. Handling the OverlayDrawing event

Private Sub TheMap_OverlayDrawing(sender As Object, e As OverlayDrawingWinformsMapEventArgs) Handles TheMap.OverlayDrawing
            Dim theOverlay As LayerOverlay = e.Overlay



’looking for the maximum tile counter
            If theOverlay.Attribution <> “” And theOverlay.IsVisible Then
                Dim maxLayer As Integer = theOverlay.Attribution
                For Each LayerCandidate In theOverlay.Layers

’is Layer intersecting?
                    If TheMap.CurrentExtent.Intersects(LayerCandidate.GetBoundingBox) Then
                        If maxLayer > 0 Then
                            LayerCandidate.IsVisible = True
                            OverlayTreeIsDirty = True
                            maxLayer -= 1
                        Else
                            LayerCandidate.IsVisible = False
                        End If
                    Else
                        LayerCandidate.IsVisible = False
                    End If
                Next
            End If
    End Sub



So, thank you for your support.

It’s working fine.



Regards

Hardy







Cool, Hardy, I guess your solution is good as well. Anything else please feel free to let us know. 
  
 Regards, 
 Johnny

Hi Hartwig, 
  
 I’m glad to hear that. About the 2nd point, I think “Intersects” is better than the other way, the result of “Intersection” include internal geometry objects and intersecting geometry objects. 
  
 Thanks,