TileSchema > GetTilesInView

Jan 17, 2012 at 2:49 PM

Hi,

We are using Brutile Library in a field management software. In this software we generate our own pyramid of tiles. For this purpose, we use the TileSchema >> GetTilesInView method, but it's return too big List and the application crashes.

In order to solve the problem, we need a method GetTilesInView which return an IEnumerable.

Could you please add a method like this :

public IEnumerable<TileInfo> GetTilesInViewIEnumerable(Extent extent, int level)
{

TileRange range = TileTransform.WorldToTile(extent, level, this);


for (int x = range.FirstCol; x < range.FirstCol + range.ColCount; x++)
{
for (int y = range.FirstRow; y < range.FirstRow + range.RowCount; y++)
{
var info = new TileInfo();
info.Extent = TileTransform.TileToWorld(new TileRange(x, y), level, this);
info.Index = new TileIndex(x, y, Resolutions[level].Id);

if (WithinSchemaExtent(Extent, info.Extent))
{
yield return info;
}
}
}
}

Regards,

Pierre

Coordinator
Jan 18, 2012 at 9:33 PM

Hi Pierre,

So, how does it crash? You get an out of memory exception on infos.Add(info);? 

And with respect to performance, does your application run significantly faster with the yield?

I am not sure why I ever returned an IList instead of an IEnumerable, so I may simply replace the original method.

I am now trying to get an better understanding of the advantages and disadvantages of using yield.

Paul

Jan 19, 2012 at 7:10 AM

Yes we get an out of memory exception.

It's because we are not use this method at the appropriate level, but at a bigger level for large area in order to create our pyramid base level. 

The yield solution is better because it streams the output collection with no need to hold it in memory.

Thank you very much,

Pierre

Coordinator
Jan 19, 2012 at 8:35 AM
Pierre08 wrote:

The yield solution is better because it streams the output collection with no need to hold it in memory.

This suggest that you should always use a yield whenever possible, I wonder if this is true. I will try to read up a bit more about the pros and cons and then probably replace the current GetTilesInView with a IEnumerable + yield.

Paul

Developer
Jan 19, 2012 at 9:22 AM

If you use the yield approach, you only can go through the enumeration once!

@Pierre:
You can always rewrite your IEnumerable<TileInfo> solution as extension method and nothing needs to change

public static IEnumerable<TileInfo> EnumerateTilesInView(this TileSchema self, Extent extent, int level)
{
   // code as above, but replace 'this' with 'self'
   // might even work with ITileSchema
}

Hth FObermaier

Jan 19, 2012 at 9:43 AM

Hi FObermaier

With the last release, TileRange and other classes are internal, so we cannot make an extension method similar to GetTilesInView().

With the last sources, we cannot compile with visual studio 2008 (the version we use with .net 3.5) because of some default value parameters and solution saved with visual studio 2010. 

Rigth now, we use last sources with changes in order to compile with visual studio 2008 (and of course with the yield return). But it's annoying this kind of local fork to follow BruTile future improvements.

You can enumerate the IEnumerable as much as you want, the code returning the IEnumerable is executed each time.

 

Pierre

Developer
Jan 19, 2012 at 10:37 AM

I know that you can call the function as often as you want, but you can not pass the function result around or reuse it.
That was the point I was trying to make.

In the latest development version TileSchema is public.
http://brutile.codeplex.com/SourceControl/changeset/view/63e04734d44c#BruTile%2fTileSchema.cs

So if you compile BruTile yourself, you should be able to get away with an extension method.

Hth FObermaier

Coordinator
Jan 22, 2012 at 6:43 PM
FObermaier wrote:

I know that you can call the function as often as you want, but you can not pass the function result around or reuse it.
That was the point I was trying to make.

I did a quick test and it seems you can pass the results around. The code below works like any other list. Or did you mean something else?

using System;
using System.Collections.Generic;

namespace InvestigateYieldReturn
{
    class Program
    {
        static void Main()
        {
            var result = DoYourFoxyThing();

            foreach (var i in result)
            {
                Console.WriteLine(i);    
            }
            Console.WriteLine();  

            foreach (var i in result)
            {
                Console.WriteLine(i);
            }

            Console.ReadKey();
        }

        static IEnumerable<int> DoYourFoxyThing()
        {
            for (int i = 0; i < 10; i++)
            {
                yield return i;
            }
        }
    }
Developer
Jan 23, 2012 at 6:35 AM
Edited Jan 23, 2012 at 6:36 AM

Sorry my fault, maybe it's just that I don't like yield :).

For the record, I'd still prefer returning the list.

Mar 1, 2012 at 1:46 PM

Thanks Paul :)