示例#1
0
        //
        //  build a root node for the layer then add child nodes to that root before adding the root
        //  to the topNode
        //

        private static void CreateTreeLayers(TreeNode parentTree, Layer thisLayer, int layerNumber)
        {
            string thisLayerName;

            DebugUtil.WriteLine();
            DebugUtil.WriteLine("++++++      New Layer: " + thisLayer.GetName()
                                + ". Layer Number: " + layerNumber
                                + ". Feature Count: " + thisLayer.GetFeatureCount(1).ToString()
                                + "      +++++");
            DebugUtil.WriteLine();

            // build sub-trees by layer.  Under that there will be sub-treas for Features and Fields
            TreeNode thisLayerTree = new TreeNode();

            // create a new root node for this layer and name it
            thisLayerName      = thisLayer.GetName();
            thisLayerTree.Name = thisLayerName;
            thisLayerTree.Text = thisLayerName;
            //TreeUtil.AddChildNode(thisLayerTree, "Feature Count = " + thisLayer.GetFeatureCount(1).ToString());

            // get the features
            CreateTreeFeatures(thisLayerTree, thisLayer);

            // add this layer to the parent tree
            parentTree.Nodes.Add(thisLayerTree);
        }
示例#2
0
        //
        // add a childnode with the text contained in "caption"
        // add another childnode under that (grandchild) to that that contains the data in "value"
        // of "value" is emptry, then skip that part
        //
        public static void AddChildNode(TreeNode parent, string caption, string value)
        {
            TreeNode thisChild, thisGrandChild;

            // add caption as a child node
            thisChild      = new TreeNode();
            thisChild.Name = caption;
            thisChild.Text = caption;

            if (value != null && value != "")
            {
                // add values as a Grand Child
                thisGrandChild      = new TreeNode();
                thisGrandChild.Name = value;
                thisGrandChild.Text = value;
                thisChild.Nodes.Add(thisGrandChild);
            }
            parent.Nodes.Add(thisChild);

#if false
            //generates a lot of output and is redundant if you are printing from your app
            DebugUtil.WriteLine("Child Node added. Caption:  " + caption);
            if (value != "")
            {
                DebugUtil.WriteLine("   Value: " + value + ".");
            }
#endif
        }
示例#3
0
 private static void PrintDriversGdal()
 {
     if (DebugUtil._debug)
     {
         var num = Gdal.GetDriverCount();
         for (var i = 0; i < num; i++)
         {
             var driver = Gdal.GetDriver(i);
             DebugUtil.WriteLine(string.Format("GDAL {0}: {1}-{2}", i, driver.ShortName, driver.LongName));
         }
     }
 }
示例#4
0
 private static void PrintDriversOgr()
 {
     if (DebugUtil._debug)
     {
         var num = Ogr.GetDriverCount();
         for (var i = 0; i < num; i++)
         {
             var driver = Ogr.GetDriver(i);
             DebugUtil.WriteLine(string.Format("OGR {0}: {1}", i, driver.name));
         }
     }
 }
示例#5
0
        //  simple function that only opens the driver and returns a pointer to the provider
        private static DataSource OpenMap(String fileName)
        {
            // save the dataset name
            _S57FileName = fileName;

            // register all the drivers so we can find the one we need - this is slow if debug output is on
            Ogr.RegisterAll();

            // open the specified fileName with update set to R/O (=0)
            ds = Ogr.Open(fileName, 0);
            if (ds == null)
            {
                MessageBox.Show("Ogr.Open returned a zero.  Make sure your file pathname is correct.");
                _S57DataSource = null;
                _S57FileName   = "";
            }
            else
            {
                DebugUtil.WriteLine("DataSource is: " + ds.ToString());
                DebugUtil.WriteLine("DataSource Name is: " + ds.name.ToString());
                _S57DataSource     = ds;
                _S57DataSourceName = ds.name;

                Driver drv = ds.GetDriver();
                _S57Driver = drv;

                if (drv == null)
                {
                    MessageBox.Show("S-57 driver is null.  Make sure your drivers are in the correct directory and GDAL_DRV points to them.");
                    ds = null;
                }
                else
                {
                    DebugUtil.WriteLine("Driver is: " + drv.ToString());
                }
            }

            return(ds);
        }
示例#6
0
        /* --------------------------------------------------------------------
         *      Reading the Field Definitions.
         *
         *  These define how to interpret the Features (next section).  They do
         *  do not need to be added to the tree, but are used to interpret the
         *  Features.
         *
         * --------------------------------------------------------------------*/

        protected static void CreateTreeFeatures(TreeNode parentLayerTree, Layer thisLayer)
        {
            FeatureDefn featureDefn;

            //
            // These are fields from the DSID layer.  They have odd names, but we need this data.
            //
            string[] DSIDList = { "DSID_EXPP", "DSID_INTU", "DSID_DSNM", "DSID_EDTN", "DSID_UPDN", "DSID_UADT", "DSID_ISDT", "DSID_STED", "DSID_PRSP", "DSID_PSDN",
                                  "DSID_PRED", "DSID_PROF", "DSID_AGEN", "DSID_COMT", "DSSI_DSTR", "DSSI_AALL", "DSSI_NALL", "DSSI_NOMR", "DSSI_NOCR", "DSSI_NOGR","DSSI_NOLR",
                                  "DSSI_NOIN", "DSSI_NOCN", "DSSI_NOED", "DSSI_NOFA", "DSPM_HDAT", "DSPM_VDAT", "DSPM_SDAT", "DSPM_CSCL", "DSPM_DUNI", "DSPM_HUNI","DSPM_PUNI",
                                  "DSPM_COUN", "DSPM_COMF", "DSPM_SOMF", "DSPM_COMT" };

            // This is the list of feature fields used to contain names.  Not all objects are nameed.  Some that are not named have useful comments.
            // This is order dependenet.
            string[] featureNameList = { "OBJNAM", "CATSEA", "CATLND" };

            Feature   feature;
            TreeNode  featureTree;
            FieldDefn fieldDefn;
            int       objIndex;                 // index used to search within fields
            string    fieldName;                // name of a specific field
            string    fieldValue;               // value for a specific field

#if false
            // there is litte point in adding the field defintions to the tree or the output files other than diagnostics
            // if you want to turn this on change or remove the #if/#endif.  FYI it makes bot the file and the tree much larger
            // and therefore slower to build and display.

            FieldDefn fieldDefn;        // variable for local fields

            // DebugUtil.WriteLine("   ***  Field Definitions  ***");
            for (int iAttr = 0; iAttr < featureDefn.GetFieldCount(); iAttr++)
            {
                // get the collection of field information
                fieldDefn = featureDefn.GetFieldDefn(iAttr);

                // add a new local root node to hold this field and give it this field name

                thisFieldRoot = new TreeNode(fieldDefn.GetName());

                TreeUtil.AddChildNode(thisFieldRoot, "Field Name", fieldDefn.GetName());
                TreeUtil.AddChildNode(thisFieldRoot, "Name Ref", fieldDefn.GetNameRef());
                TreeUtil.AddChildNode(thisFieldRoot, "Type Name", fieldDefn.GetTypeName());
                TreeUtil.AddChildNode(thisFieldRoot, "Field Type", fieldDefn.GetFieldType().ToString());
                TreeUtil.AddChildNode(thisFieldRoot, "Width", fieldDefn.GetWidth().ToString());
                TreeUtil.AddChildNode(thisFieldRoot, "Precision", fieldDefn.GetPrecision().ToString());
                fieldDefn.GetTypeName();
                thisLayerRoot.Nodes.Add(thisFieldRoot);

                DebugUtil.WriteLine("   " + "NameRef: " + fieldDefn.GetNameRef() + ": " +
                                    "Type: " + fieldDefn.GetFieldType() +
                                    "Type Name: " + fieldDefn.GetFieldTypeName(fieldDefn.GetFieldType()) + " (" +
                                    fieldDefn.GetWidth() + "." +
                                    fieldDefn.GetPrecision() + ")");
            }
#endif

            /* -------------------------------------------------------------------- */
            /*      Reading the Features                                            */
            /* -------------------------------------------------------------------- */

            // Get the FeatureDefn pointer for this layer
            featureDefn = thisLayer.GetLayerDefn();

            // get the feature list for this layer
            feature = new Feature(featureDefn);

            while ((feature = thisLayer.GetNextFeature()) != null)
            {
                // create the subtree and name it
                featureTree = new TreeNode();

                // get the field name.  Most lights have names as do some bouys, bridges and other landmarks.  The featureNameList controls the fields
                // we look for names in.  Most feature do NOT have names.
                fieldName = "";
                foreach (string field in featureNameList)
                {
                    if ((objIndex = featureDefn.GetFieldIndex(field)) >= 0)
                    {
                        // if the name is already found, do not reassign it
                        if (fieldName == "")
                        {
                            fieldDefn = featureDefn.GetFieldDefn(objIndex);
                            fieldName = DecodeField(feature, fieldDefn, objIndex);
                            if (fieldName != null && fieldName != "")
                            {
                                featureTree.Name = fieldName;
                                featureTree.Text = featureTree.Name;
                            }
                        }
                    }
                }

                // if no name is found above, assign it "unnamed" unless the layer is DSID
                if (fieldName == "" & thisLayer.GetName() != "DSID")
                {
                    fieldName        = "Unnamed";
                    featureTree.Name = fieldName;
                    featureTree.Text = featureTree.Name;
                }

                // DSID has to be handled differently. It has not displayable data and has it's own fieldlist
                if (thisLayer.GetName() == "DSID")
                {
                    foreach (string field in DSIDList)
                    {
                        if ((objIndex = featureDefn.GetFieldIndex(field)) >= 0)
                        {
                            fieldDefn  = featureDefn.GetFieldDefn(objIndex);
                            fieldValue = DecodeField(feature, fieldDefn, objIndex);
                            // field values are never 0
                            if (fieldValue != null && fieldValue != "")
                            {
                                TreeUtil.AddChildNode(parentLayerTree, field, fieldValue);
                            }
                        }
                    }
                }
                else
                {
                    // The fieldList contains the names of the fields are interested in.  We do not want all fields as many of them are
                    // irrelevant to diplaying the image such as the agency names and quality of the data, etc.

                    foreach (string field in fieldList)
                    {
                        // check each feature for the key attributes and add them to the tree if they exist.
                        if ((objIndex = featureDefn.GetFieldIndex(field)) >= 0)
                        {
                            if (feature.IsFieldSet(objIndex))
                            {
                                fieldDefn  = featureDefn.GetFieldDefn(objIndex);
                                fieldValue = DecodeField(feature, fieldDefn, objIndex);
                                // valid field values are never 0 or empty
                                if (fieldValue != null && fieldValue != "")
                                {
                                    TreeUtil.AddChildNode(featureTree, field, fieldValue);
                                }
                            }
                        }
                    }
                }

                // get the details of the fields.  This is mostly diagnostic code, but it does populate the tree with positional information
                CreateTreeFields(ref featureTree, feature, featureDefn);

                // add the subtree
                parentLayerTree.Nodes.Add(featureTree);
                feature.Dispose();
            }
        }
示例#7
0
        /* -------------------------------------------------------------------- */
        /*      Reading the Fields in this Feature                              */
        /* -------------------------------------------------------------------- */

        public static void CreateTreeFields(ref TreeNode thisFeatureTree, Feature feature, FeatureDefn featureDefn)
        {
            // field definition as we iterate through the fields
            FieldDefn iFieldDefn;
            int       nameIndex;
            int       objlIndex;
            string    nameString;
            string    objlString;

            // To get the name and the S-57 Type code (OBJL), we have to look forward into the fields.  This piece of code
            // is mostly here to show how that is done as will need this when rendering these objects.  You could easily add
            // shapes or color, but it is not necessary here.  The name and the code is nice for the debug file though so we can
            // see what each feature is.

            // OBJL field should always exist - the exception are the meta data fields such as DSID which has no code.
            objlIndex = featureDefn.GetFieldIndex("OBJL");
            if (objlIndex > 0)
            {
                objlString = DecodeField(feature, featureDefn.GetFieldDefn(objlIndex), objlIndex);
            }
            else
            {
                objlString = "No Code";
            }

            // name field may not exist.  we could get either the info or text description if they exist
            nameIndex = featureDefn.GetFieldIndex("OBJNAM");
            if (nameIndex > 0)
            {
                nameString = DecodeField(feature, featureDefn.GetFieldDefn(nameIndex), nameIndex);
            }
            else
            {
                nameString = "Not Named";
            }

            DebugUtil.WriteLine();
            DebugUtil.WriteLine(string.Format("   *** Feature: {0}, Name: {1}, S-57 Code: {2}", featureDefn.GetName(), nameString, objlString));
            DebugUtil.WriteLine();

            // get the styles, if any
            if (feature.GetStyleString() != null)
            {
                DebugUtil.WriteLine("  Style = " + feature.GetStyleString());
            }

            // this gets the sub-geometries.  not all features have sub-geometries
            Geometry geom = feature.GetGeometryRef();

            if (geom != null)
            {
                DebugUtil.WriteLine("   Geometry Name: " + geom.GetGeometryName() + " Sub-geometry Count: " + geom.GetGeometryCount());

                Geometry sub_geom;
                for (int i = 0; i < geom.GetGeometryCount(); i++)
                {
                    sub_geom = geom.GetGeometryRef(i);
                    if (sub_geom != null)
                    {
                        string subGeoString;
                        DebugUtil.Write("   sub-geometry " + i + ": ");
                        switch (sub_geom.GetGeometryType())
                        {
                        case wkbGeometryType.wkbLineString:
                        case wkbGeometryType.wkbPoint25D:
                            sub_geom.ExportToWkt(out subGeoString);
                            DebugUtil.WriteLine(subGeoString);
                            TreeUtil.AddChildNode(thisFeatureTree, subGeoString);
                            break;

                        default:
                            DebugUtil.WriteLine("Unhandled subgeometry type: " + sub_geom.GetGeometryType());
                            TreeUtil.AddChildNode(thisFeatureTree, "Unhandled sub-geomtry type", sub_geom.GetGeometryType().ToString());
                            break;
                        }
                    }
                }

                // a bit confusing, but if it has no sub geometries, use the base geometry.  mostly applies to the type POINT
                if (geom.GetGeometryCount() == 0)
                {
                    string geom_wkt;
                    geom.ExportToWkt(out geom_wkt);
                    DebugUtil.WriteLine("   geom_wkt: " + geom_wkt);
                    TreeUtil.AddChildNode(thisFeatureTree, geom_wkt);
                }
            }  // if geo != null

            for (int iField = 0; iField < feature.GetFieldCount(); iField++)
            {
                iFieldDefn = featureDefn.GetFieldDefn(iField);

                // not all fields have usable information, skip those that don't.
                if (feature.IsFieldSet(iField))  // IsFieldSet is a handy way to see if the field has any actual information
                {
                    DebugUtil.Write("   ");
                    DebugUtil.Write("Field Name: " + iFieldDefn.GetName() + ", ");
                    DebugUtil.Write("Type Name: " + iFieldDefn.GetFieldTypeName(iFieldDefn.GetFieldType()) + ", ");
                    DebugUtil.Write("Field Type: " + iFieldDefn.GetFieldType() + ", ");
                    DebugUtil.Write("Value: " + DecodeField(feature, iFieldDefn, iField));
                    DebugUtil.WriteLine();
                }  // if isField
            }
        }
示例#8
0
        /// <summary>
        /// Iterates through the layers of the map and builds a tree based on the layer information
        /// </summary>
        /// <param name="ds"></param>
        /// <returns>"TreeNode"</returns>
        ///
        public static TreeNode CreateTree()
        {
            DebugUtil.WriteLine();
            DebugUtil.WriteLine("*******************************************************************************************************");
            DebugUtil.WriteLine("****                                      Building Tree                                            ****");
            DebugUtil.WriteLine("*******************************************************************************************************");
            DebugUtil.WriteLine();


            TreeNode topNode  = new TreeNode();
            TreeNode metaTree = new TreeNode();
            Layer    layer;
            string   srs_wkt;
            Envelope thisEnvelope = new Envelope();
            string   coordinateString;

            // add the name of the chart as the name of this root
            topNode.Text = Path.GetFileName(ds.name);
            topNode.Name = Path.GetFileName(ds.name);

            // Meta Tree
            metaTree.Text = "Meta Data";
            metaTree.Name = "Meta Data";

            // get layer 0 (should be "DSID) for the meta data
            layer = ds.GetLayerByIndex(0);

            /* -------------------------------------------------------------------- */
            /* Get the spatial reference.  It is consistent for the entire map so we*/
            /* only need to do it once.                                             */
            /* -------------------------------------------------------------------- */

            OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef();
            // this should not be null
            if (sr != null)
            {
                sr.ExportToPrettyWkt(out srs_wkt, 1);
                TreeUtil.AddChildNode(metaTree, "Spatial Reference", srs_wkt);
                DebugUtil.WriteLine("Spatial Reference: " + srs_wkt);
            }
            else
            {
                TreeUtil.AddChildNode(metaTree, "Spatial Reference", "Spatial Reference Uknown");
                srs_wkt = "SRS: Unknown.";
            }

            // get Envelope for this layer
            layer.GetExtent(thisEnvelope, 1);

            // Get the Extents for the map.  Again, they are consistent for the entire map, so we only need to do this once.
            if (thisEnvelope != null)
            {
                coordinateString = String.Format("MaxX = {0}, MaxY = {1}, MinX = {2}, MinY = {3}.", thisEnvelope.MaxX, thisEnvelope.MaxY, +thisEnvelope.MinX, thisEnvelope.MinY);
                DebugUtil.WriteLine("Extents: " + coordinateString);
                TreeUtil.AddChildNode(metaTree, "Envelope: ", coordinateString);
            }

            // add metaTree to topNode
            topNode.Nodes.Add(metaTree);

            // go through all the layers starting at zero
            for (int i = 0; i < ds.GetLayerCount(); i++)
            {
                layer = ds.GetLayerByIndex(i);
                if (layer != null)
                {
                    // most of the work is done here
                    CreateTreeLayers(topNode, layer, i);
                }
                else
                {
                    DebugUtil.WriteLine("***********    Critical Error     *************");
                    DebugUtil.WriteLine("Layer: " + i + " is null and does not exist.");
                    MessageBox.Show("Critical Error: " + "Layer: " + i + " is null and does not exist.");
                }
            }

            DebugUtil.WriteLine("   TopNode node count is " + topNode.Nodes.Count + ".");

            // save the tree to a file.  this is controlled by the debug flags.  note that the file can get very large
            TreeUtil.OpenPrintRecursive("TreeNode.txt");
            TreeUtil.PrintRecursive(topNode);

            // close the debug files
            DebugUtil.Close();
            TreeUtil.Close();

            return(topNode);
        }
示例#9
0
        /// <summary>
        /// Render is where most of the work is done.  It builds a list of graphics items to be displayed and calls the S-52 rendorer to actually display them.
        /// We could pass the layer, but that would mean that the S-52 code would have to decipher the layers.  It seems easier just to build a list and let S-52
        /// only take care of the colors, symbol, and tiling.
        ///
        /// The goal is to create one list for each layer in the S57 record and have S52 render that layer.
        ///
        /// S-52 will return a map of the collective layers to display.  This can then either be displayed or tiled or both.
        /// </summary>
        /// <param name="angle"></param>
        /// <returns></returns>
        public static Map Render(DataSource ds)
        {
            // the the cursor to the little swirling circle
            Cursor.Current = Cursors.WaitCursor;

            S57Layer layerCollection = new S57Layer();

            SharpMap.Data.FeatureDataSet fds = new FeatureDataSet();

            VectorLayer vectorLayer;
            Map         map = new Map();

            int featureCount;
            //int iFeatureCount;
            int    fieldIndex;
            string fieldValue;

            SharpMap.Data.Providers.Ogr dataProvider;
            //SharpMap.Layers.Layer thisLayer;

            OSGeo.OGR.Feature     thisFeature;
            OSGeo.OGR.FeatureDefn featureDefn;
            OSGeo.OGR.FieldDefn   fieldDefn;
            OSGeo.OGR.Layer       thisLayer;

            Geometry geometry;
            Geometry sub_geometry;
            string   WKTGeometry;

            DebugUtil.WriteLine("****************************************************************************");
            DebugUtil.WriteLine("***                        Render                                        ***");
            DebugUtil.WriteLine("****************************************************************************");

            // get the datasource that is currently open
            // ds = S57.DataSource;

            // we are only displaying the layers that our config data says to.
            int count = S57.myS57Objects.GetCount();

            for (int i = 0; i < count; i++)
            {
                if (myS57Objects.GetDisplayFlag(i))
                {
                    layerCollection.layerName = myS57Objects.S57ObjectsList[i].ObjectName;
                }
            }

            for (int iLayer = 0; iLayer < ds.GetLayerCount(); iLayer++)
            {
                thisLayer = DataSource.GetLayerByIndex(iLayer);
                DebugUtil.WriteLine("***  Layer = " + thisLayer.GetName() + "Layer Number: " + iLayer);

                featureCount = thisLayer.GetFeatureCount(0);  // a value of zero will get current feature count.  a value of 1 will force a feature count and is slow
                DebugUtil.WriteLine("***  Feature Count: " + featureCount);

                // FeatureDefn pointer
                featureDefn = thisLayer.GetLayerDefn();
                DebugUtil.WriteLine("***  Feature Definition Name: " + featureDefn.GetName() + "Field Count: " + featureDefn.GetFieldCount());

                // allocate a feature set for this layer based on featureDefn
                thisFeature = new Feature(featureDefn);
                DebugUtil.WriteLine("*** thisFeature Definition Reference: " + thisFeature.GetDefnRef());

                // get a SharpMap dataprovider for this vector layer.  this is needed before we
                // can render the file
                dataProvider = new SharpMap.Data.Providers.Ogr(S57.FileName, iLayer);

                // make sure the dataprovider is open
                if (!dataProvider.IsOpen)
                {
                    dataProvider.Open();
                }

                //featureCount = thisLayer.GetFeatureCount(0);
                //for (iFeatureCount = 0; iFeatureCount < featureCount; iFeatureCount++)

                // reset the current feature to 0 then read all the features
                thisLayer.ResetReading();
                while ((thisFeature = thisLayer.GetNextFeature()) != null)
                {
                    if (thisFeature == null)
                    {
                        MessageBox.Show("thisFeature is null and can not be processed.");
                        System.Environment.Exit(-1);
                    }
                    DebugUtil.WriteLine("Field count from thisFeature: " + thisFeature.GetFieldCount().ToString());

                    // Get the fields we want using the fieldList.  This avoids process fields that have nothing to do with display.
                    foreach (string thisField in fieldList)
                    {
                        // check each feature for the key attributes and add them to the tree if they exist.
                        if ((fieldIndex = thisFeature.GetFieldIndex(thisField)) >= 0)
                        {
                            DebugUtil.WriteLine("Field = " + thisField + ".  Field Index = " + fieldIndex);
                            fieldDefn  = featureDefn.GetFieldDefn(fieldIndex);
                            fieldValue = DecodeField(thisFeature, fieldDefn, fieldIndex);

                            // valid field values are never 0 or empty
                            if (fieldValue != null && fieldValue != "" && fieldValue != "0")
                            {
                                // this gets the sub-geometries.  not all features have sub-geometries
                                geometry = thisFeature.GetGeometryRef();

                                // only render things that actually have geometries
                                if (geometry != null)
                                {
                                    // a bit confusing, but if it has no sub geometries, use the base geometry.  mostly applies to the type POINT
                                    if (geometry.GetGeometryCount() == 0)
                                    {
                                        geometry.ExportToWkt(out WKTGeometry);
                                        vectorLayer = new VectorLayer(thisLayer.GetName(), dataProvider);
                                        DebugUtil.WriteLine("Rendering: " + WKTGeometry);
                                        //vectorLayer = S52.Render(ref vectorLayer, dataProvider, thisFeature, fieldDefn, WKTGeometry);
                                        vectorLayer = S52.Render(thisLayer.GetName(), fds);
                                        map.Layers.Add(vectorLayer);
                                        //vectorLayer.Dispose();
                                    }
                                    else
                                    {
                                        for (int i = 0; i < geometry.GetGeometryCount(); i++)
                                        {
                                            sub_geometry = geometry.GetGeometryRef(i);
                                            if (sub_geometry != null)
                                            {
                                                sub_geometry.ExportToWkt(out WKTGeometry);
                                                vectorLayer = new VectorLayer(thisLayer.GetName(), dataProvider);
                                                DebugUtil.WriteLine("Rendering: " + WKTGeometry);
                                                //vectorLayer = S52.Render(ref vectorLayer, dataProvider, thisFeature, fieldDefn, WKTGeometry);
                                                vectorLayer = S52.Render(thisLayer.GetName(), fds);
                                                map.Layers.Add(vectorLayer);
                                                //vectorLayer.Dispose();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // free the feature collection for this layer
                //thisFeature.Dispose();
            }

            map.ZoomToExtents();

            //Matrix mat = new Matrix();
            //mat.RotateAt(angle, map.WorldToImage(map.Center));
            //map.MapTransform = mat;

            // change back to the defaul cursor
            Cursor.Current = Cursors.Default;
            return(map);
        }