WMS project and other considerations

Dec 30, 2010 at 8:35 AM

Hi everybody.

First of all, I want to acknowledge shade1974. With your help I’ve been able to finish my project.

Next, I want to show some problems or questions that I have found working with DotSpatial. Please, be patient, I’m a newbie in C# and DotSpatial (also in english, what else?) and maybe the code that I’ve include here is not the best.

Info/identification tool

- Suppose you have identified with this tool a point of a vector layer. The info of that point is shown in the right part of the FeatureIdentifier window. Now, suppose you click on the map in a place where there are no features at all. In this case, the left part of the FeatureIdentifier window is updated and shows no features, but the right part of this window continues showing the information of the first identified point.

- Is it possible to change by code the attribute field (of the identified features) shown by default in the left part of the FeatureIdentifier Window?

map.ZoomToMaxExtent( )

- In my proyect I use WMS images as a background of the map. So, in the Form_Load procedure I have put the following code. (in the comments of this code are described two problems that I have found):


          map.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
          int mapWidthPix, mapHeightPix;
          mapWidthPix = map.MapFrame.View.Width;
          mapHeightPix = map.MapFrame.View.Height;
          if (( (double)mapWidthPix / (double)mapHeightPix ) >= (360.0 / 180.0))
              map.ViewExtents.MinX = - (mapWidthPix * 180.0) / (mapHeightPix * 2.0);
              map.ViewExtents.MaxX = (mapWidthPix * 180.0) / (mapHeightPix * 2.0);
              map.ViewExtents.MinY = -90.0;
              map.ViewExtents.MaxY = 90.0;
              map.ViewExtents.MinX = -180.0;
              map.ViewExtents.MaxX = 180.0;
              map.ViewExtents.MinY = -(mapHeightPix * 360.0) / (mapWidthPix * 2.0);
              map.ViewExtents.MaxY = (mapHeightPix * 360.0) / (mapWidthPix * 2.0);
          // gwtWMSImage() returns a jpg in C:\Documents and Settings\santiagol\WMS.jpg
          getWMSImage(mapWidthPix, mapHeightPix, map.ViewExtents.MinX, map.ViewExtents.MinY, map.ViewExtents.MaxX, map.ViewExtents.MaxY);
          InRamImageData WMSImage = new InRamImageData();
          WMSImage.Name = "WMS";
          WMSImage.Open(@"C:\Documents and Settings\santiagol\WMS.jpg");
          WMSImage.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
          IRasterBounds rb = new RasterBounds();
          double xCellSize, yCellSize;
          xCellSize = (map.ViewExtents.MaxX - map.ViewExtents.MinX) / (double)mapWidthPix;
          yCellSize = (map.ViewExtents.MaxY - map.ViewExtents.MinY) / (double)mapHeightPix;
          double[] affine = new double[] { map.ViewExtents.MinX + (xCellSize / 2.0), xCellSize, 0, map.ViewExtents.MaxY - (yCellSize / 2.0), 0, -yCellSize };
          rb.AffineCoefficients = affine;
          WMSImage.Bounds = rb;
          IMapImageLayer myImgLayer = map.Layers.Add(WMSImage);
          // At this point, I have noticed to problems:
          // - After executing map.Layers.Add(), the map.ViewExtents are changed and I have
          //   to adjust the ViewExtents again.
          // - If I put here map.ZoomToMaxExtent(), it doesn't shows the full extent of
          //   the map (-180,-90,180,90). It shows only a little part of the full extent,
          //   in fact this extent is the map.ViewExtents that I got after executing
          //   map.Layers.Add().
          if (((double)mapWidthPix / (double)mapHeightPix) >= (360.0 / 180.0))
              map.ViewExtents.MinX = -(mapWidthPix * 180.0) / (mapHeightPix * 2.0);
              map.ViewExtents.MaxX = (mapWidthPix * 180.0) / (mapHeightPix * 2.0);
              map.ViewExtents.MinY = -90.0;
              map.ViewExtents.MaxY = 90.0;
              map.ViewExtents.MinX = -180.0;
              map.ViewExtents.MaxX = 180.0;
              map.ViewExtents.MinY = -(mapHeightPix * 360.0) / (mapWidthPix * 2.0);
              map.ViewExtents.MaxY = (mapHeightPix * 360.0) / (mapWidthPix * 2.0);

IfeatureLayer.SelectAll( )

- I have put a piece of code and the problem is described as in comment in it:


          map.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
          ... ...
          FeatureSet fsp = new FeatureSet(FeatureType.Point);
          fsp.Name = "Puntos";
          fsp.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
          fsp.DataTable.Columns.Add(new DataColumn("TIPO", typeof(int)));
          fsp.DataTable.Columns.Add(new DataColumn("TEXTO1", typeof(string)));
          fsp.DataTable.Columns.Add(new DataColumn("TEXTO2", typeof(string)));
          for (int i = 0; i < 10; i++)
              punto.X = (rnd.NextDouble() * (maxXExtent - minXExtent)) + minXExtent;
              punto.Y = (rnd.NextDouble() * (maxYExtent - minYExtent)) + minYExtent;
              IFeature currentFeatp = fsp.AddFeature(punto);
              if (((int)Math.Abs(punto.X) % 3) == 0) currentFeatp.DataRow["TIPO"] = 1;
              else if (((int)Math.Abs(punto.X) % 3) == 1) currentFeatp.DataRow["TIPO"] = 2;
              else currentFeatp.DataRow["TIPO"] = 3;
              currentFeatp.DataRow["TEXTO1"] = "hello_" + i.ToString();
              currentFeatp.DataRow["TEXTO2"] = "bye_" + i.ToString();
          IMapFeatureLayer mflp = map.Layers.Add(fsp);
          ... ...
          ILayer lp = map.Layers[indCapaPuntos];
          IFeatureLayer flp = lp as IFeatureLayer;
          if (flp == null) return;
          // flp.selectAll() doesn't select all the elements. Some of the elements are not 
          // selected by this function. I have noticed that the elements that are near the 
          // geographic envelope of the layer are not selected, but I haven't been able to
          // quantify how "near". To select all the elements, finally I have used the
          // SelectByAttribute() method with a filter (in the example below, the value -1
          // is unused in my data).
          flp.SelectByAttribute("TIPO <> -1");


At last, a final question. I have implemented a way to add WMS maps to a DotSpatial project. I don’t mind to share the code. How can I do it?

Best regards and happy new year,


Dec 30, 2010 at 1:30 PM

I think this would be a good addition Santiago.  If you are not listed as a developer already, request to become one and i will make you a developer so that you can push your WMS code up.  Please remember that the current projects are set up to work for both 3.5 and 4.0 as well as x86 and x64.  If you have any code that is cannot work in all of these configurations then we don't want to add it directly to our existing projects, but could create a WMS "plug-in" or "app" which would allow for WMS layers to be activated by adding a button on the toolbar.  See the ShapeEditorApp as an example for how to make a plug-in app.  The main thing required is a plugin attribute on both your application and the specific app implementation class.  Then you can either implement IPlugIn or inherit from the existing Extension class I think.  If the code is all pure .Net code, then we can add it in directly into the DotSpatial.Controls project.  You could inherit from MapImagelayer and create a MapWmsImageLayer which could have the address as a property and then people could add the layer pretty easily to their map.  The mechanics of it can be left up to you initially.  My only concern is that we don't want to break the 3.5/4.0 and x86 and x64 builds.