ThinkGeo.com    |     Documentation    |     Premium Support

Displaying terrain with Web Edition

Is it possible to  display a geo-referenced terrain image as a layer on a custom  map?






Google has this  capability, see attached.  We need it for a real estate web site we are  developing (mapexsa.com) for  Nicaragua.




 We currently have a  1:50,000 shp elevation file, which we could display.  But by themselves  elevation lines are difficult for the eye to  dicepher.







 I have two  questions:







 1)  Do you have a  method or extension I can use to create these images from a contour shp  file?







 2) If not, and I was  able to generate these independently, is there a way to incorporate these images  into our map in a layer?  I am thinking that we would create an image library  and fetch the tiles as needed.  Is this possible?







 




Thanks,




 




Al  Vigil




AI Vigil,


Here are answers for your questions, I hope it will be helpful to your scenario.


1. Do you have a method or extension I can use to create these images from a contour shp file?


Currently we don't have these methods or extensions, but we'll carefully consider your requirement and decide whether to add these new features to our products in the future.


2. If not, and I was able to generate these independently, is there a way to incorporate these images into our map in a layer? I am thinking that we would create an image library and fetch the tiles as needed. Is this possible?


Are these images raster images? If so, you could add them to a single overlay, and they will be displayed correctly if they have the right map-matching information.


Regards,


Ivan



Ivan, 
  
 These would be Google-compatible geo-referenced tiff files. 
  
 But when you say I could add as a single overlay, do you mean I have to export the entire country as one single file?  This file would be in  the multi giga-byte in size.  Is this feasible?  My question is, is there a way to tile the file, so that we have smaller files that are uploaded as needed? 
  
 Thanks, 
  
 Al Vigil

Ivan, 
  
 These would be Google-compatible geo-referenced tiff files. 
  
 But when you say I could add as a single overlay, do you mean I have to export the entire country as one single file?  This file would be in  the multi giga-byte in size.  Is this feasible?  My question is, is there a way to tile the file, so that we have smaller files that are uploaded as needed? 
  
 Thanks, 
  
 Al Vigil

Al, 
  
  Ivan did not mean as one single file for a single overlay. In one overlay, many files can be added as the architecture of Map Suite permits it. You can think as an overlay as a layer group to put your layers in. Since all your ge-referenced tiif files are similar, it would make sense to treat them as a group and put them in one overlay. 
  Can you direct us to some more information or web sites on those geo-referenced tiff files you plan on using for Nicaragua? Ivan or someone of the Web team will respond to your question in more detail later on but first I want to make sure they have as much information as possible to give you the best answer for your case. Thank you.

I will send you a file of the type we plan to use.  We can create a tiled library of these images, however I find no way to upload a file here.  Please advice.  These files can be created with a program called Global Mapper.  The tile and resolution can be adjusted to fit the requirements of the task at hand, as the color and other attributes.  I will be sending you a jpg file with a companion World file that is used to position it geographically.  This type of file would be my preference as opposed to a geo-referenced tiff file as smaller sizes are possible, but we can go either way. 
  
 Can Web Edition handle the World companion file?  I will send both as soon as you tell me how to upload. 
  
 Geo-referenced tiff files are an industry standard.  See en.wikipedia.org/wiki/GeoTIFF, orfor World files see en.wikipedia.org/wiki/World_file for description of these. 
  
 Thanks, 
  
  
 Al Vigil

AI,


Thank you for your feedback. Here are answers for your questions.


1. however I find no way to upload a file here. Please advice.


When you edit your post, you can see an "Attachment" section as below.



2. Can Web Edition handle the World companion file? 


Yes, we provide some code snippet for your reference.


GeoTiffRasterLayer layer1 = new GeoTiffRasterLayer(MapPath("~/Data/TiffFile1.tiff"), "your worldFile") { UpperThreshold = Double.MaxValue, LowerThreshold = 0 };
GeoTiffRasterLayer layer2 = new GeoTiffRasterLayer(MapPath("~/Data/TiffFile2.tiff"), "your worldFile") { UpperThreshold = Double.MaxValue, LowerThreshold = 0 };
LayerOverlay tiffOverlay = new LayerOverlay("TiffOverlay");
tiffOverlay.IsBaseOverlay = false;
tiffOverlay.Layers.Add(layer1);
tiffOverlay.Layers.Add(layer2);
Map1.CustomOverlays.Add(tiffOverlay);


Regards,


Ivan



 Attached would be a typical tile we would use.  There would be many thousands of these. We need a way of organizing them into directories and file names.  Do you have any suggestions on how to implement this arrangement?


From the code I can see that you would be able to display this file if it is the only one, but what if there are tens of thousands of these? We do not know a priori what files we need.  Only when the user demands the terrain file do we find out.  At this point we need to determine the directory and the tile files names knowing only the screen view port coordinates.  Once we know this then the problem reduces to calling a method that accepts the view port coordinates, determines the directory and file names and adds the layer to the map, as shown in the sample code you sent me.


You must have solved this problem already, as that is how the ThinkGeo image cache is arranged.  Can you give me some insight into how to do this for our own set of images?



ThinkGeoTopoOverlay.zip (21.8 KB)

Al,


 I used your attached geoTiff and I loaded it with the outline of Nicaragua as background to give me a scope of your case. And I can see that indeed you can use thousands of such images for the entire country. I think that we have a solution that would dynamically load the images according to where on the map the user is zoomed in. So that not all the images would have to be loaded at the same time which would be very unefficient. We have a technique that consists of created an index of all the images with their bounding box and using that index the appropriate image will be loaded and unloaded based on the current extent. We, actually have a product, WorldMapKit that uses that approach. The web team will follow up on this issue for you to give you the complete solution. Thank you for your interest in Map Suite.




Val, 
  
 This is good news.  I will wait for the web team to respond with a solution. 
  
 Thanks 
  
 Al Vigil

Hi AI,


Because GeoTiffRasterLayer has some performance issue, we should use GdiPlusRasterLayer to implement your scenario. Here I provide a solution which may meet your requirement, the steps are below:


1. Generate boundingbox index file for your GeoTiff files


// You need to generate the index file in another application
string[] files = Directory.GetFiles(@"C:/Data/", "*.tif", SearchOption.TopDirectoryOnly);
Dictionary<string, RectangleShape> boundingBoxEntities = new Dictionary<string, RectangleShape>();
foreach (string file in files)
{
    GeoTiffRasterLayer layer = new GeoTiffRasterLayer(file);
    layer.LibraryType = GeoTiffLibraryType.ManagedLibTiff;
    layer.UpperThreshold = double.MaxValue;
    layer.LowerThreshold = 0;
    layer.Open();
    RectangleShape rectangle = layer.GetBoundingBox();
    layer.Close();
    boundingBoxEntities.Add(layer.Name, rectangle);
}

// Serialize the boundingBoxEntities to a index file named "index.dat"


2. Use a customized layer to load files, please check the following sample code for your reference


public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            Map1.MapUnit = GeographyUnit.Meter;

            LayerOverlay geoTiffOverlay = new LayerOverlay("GeoTiff");
            IndexDdiPlusRasterLayer indexLayer = new IndexDdiPlusRasterLayer(Server.MapPath(@"~/Datas/"), Server.MapPath(@"~/Datas/index.dat"));
            geoTiffOverlay.Layers.Add(indexLayer);
            Map1.CustomOverlays.Add(geoTiffOverlay);

            Map1.CurrentExtent = new RectangleShape(-13939426.6371, 6701997.4056, -7812401.86, 2626987.386962);
        }
    }
}

public class IndexDdiPlusRasterLayer : Layer
{
    private Dictionary<string, RectangleShape> boundingBoxEntities;
    private Collection<GdiPlusRasterLayer> staticLayers;

    public IndexDdiPlusRasterLayer(string dataFolder, string indexFilePath)
    {
        // Deserialize the index file to generate boundingBoxEntities
        boundingBoxEntities = new Dictionary<string, RectangleShape>();

        staticLayers = new Collection<GdiPlusRasterLayer>();
        string[] files = Directory.GetFiles(dataFolder, "*.tif", SearchOption.TopDirectoryOnly);
        foreach (string file in files)
        {
            // Get the fileName by examine "file"
            string fileName = "";

            GdiPlusRasterLayer gdiPlusLayer = new GdiPlusRasterLayer(file, boundingBoxEntities[fileName]);
            gdiPlusLayer.UpperThreshold = double.MaxValue;
            gdiPlusLayer.LowerThreshold = 0;
            staticLayers.Add(gdiPlusLayer);
        }
    }

    protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
    {
        RectangleShape extent = canvas.CurrentWorldExtent;
        object image = canvas.NativeImage;
        GeographyUnit unit = canvas.MapUnit;
        bool isInDrawing = canvas.IsDrawing;

        if (isInDrawing)
        {
            canvas.EndDrawing();
        }

        foreach (GdiPlusRasterLayer layer in staticLayers)
        {
            if (boundingBoxEntities[layer.Name].Intersects(extent))
            {
                canvas.BeginDrawing(image, extent, unit);
                layer.Open();
                layer.Draw(canvas, labelsInAllLayers);
                canvas.EndDrawing();
            }
        }

        if (isInDrawing)
        {
            canvas.BeginDrawing(image, extent, unit);
        }
    }
}


By the way, the following link provides another solution (using customized WMS Services) which may helpful to you.


gis.thinkgeo.com/Support/Dis...fault.aspx


Please let us know if you have further questions.


Regards,


Ivan