private void cmbEpsgs_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnImport.Enabled = false;
            if (_metadata != null)
            {
                if (_currentEpsg != -1)
                {
                    _metadata.SetEPSGEnvelope(_currentEpsg, this.CurrentEpsgExtent);
                    _metadata.SetOriginUpperLeft(_currentEpsg, this.CurrentEpsgOriginUpperLeft);
                    _metadata.SetOriginLowerLeft(_currentEpsg, this.CurrentEpsgOriginLowerLeft);
                }

                _currentEpsg                    = (int)cmbEpsgs.SelectedItem;
                this.CurrentEpsgExtent          = _metadata.GetEPSGEnvelope((int)cmbEpsgs.SelectedItem);
                this.CurrentEpsgOriginUpperLeft = _metadata.GetOriginUpperLeft((int)cmbEpsgs.SelectedItem);
                this.CurrentEpsgOriginLowerLeft = _metadata.GetOriginLowerLeft((int)cmbEpsgs.SelectedItem);

                panelExtent.Enabled = (_startupEpsg != null ?
                                       !(_startupEpsg.Contains(_currentEpsg) && this.CurrentEpsgExtent.Width > 0 && this.CurrentEpsgExtent.Height > 0)
                    : false);

                //numUL_x.Enabled = numUL_y.Enabled = numLL_x.Enabled = numLL_y.Enabled = panelExtent.Enabled;

                btnImport.Enabled = cmbEpsgs.SelectedIndex >= 0;
            }
        }
Пример #2
0
        private string TmsCapabilities(IServiceRequestContext context, TileServiceMetadata metadata, int srs)
        {
            IEnvelope box = metadata.GetEPSGEnvelope(srs);

            if (box == null)
            {
                return(String.Empty);
            }

            ISpatialReference sRef = SpatialReference.FromID("epsg:" + srs);

            StringBuilder sb = new StringBuilder();

            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            sb.Append("<TileMap version=\"1.0.0\" tilemapservice=\"" + context.ServiceRequest.OnlineResource + "\" >");
            sb.Append("<Title>" + context.ServiceMap.Name + "</Title>");
            sb.Append("<Abstract>gView Tile Cache</Abstract>");
            sb.Append("<SRS>EPSG:" + srs + "</SRS>");

            sb.Append("<BoundingBox minx=\"" + box.minx.ToString(_nhi) +
                      "\" miny=\"" + box.miny.ToString(_nhi) +
                      "\" maxx=\"" + box.maxx.ToString(_nhi) +
                      "\" maxy=\"" + box.maxy.ToString(_nhi) + "\" />");
            sb.Append("<Origin x=\"" + box.minx.ToString(_nhi) +
                      "\" y=\"" + box.miny.ToString(_nhi) + "\" />");

            sb.Append("<TileFormat width=\"" + metadata.TileWidth + "\" height=\"" + metadata.TileHeight + "\" mime-type=\"image/png\" extension=\"png\" />");
            sb.Append("<TileSets>");

            int level = 0;

            foreach (double scale in metadata.Scales)
            {
                double res = (double)scale / (metadata.Dpi / 0.0254);
                if (sRef.SpatialParameters.IsGeographic)
                {
                    GeoUnitConverter converter = new GeoUnitConverter();
                    res = converter.Convert(res, GeoUnits.Meters, GeoUnits.DecimalDegrees);
                }
                sb.Append("<TileSet href=\"" + context.ServiceRequest.OnlineResource + "/" + level + "\" ");
                sb.Append("units-per-pixel=\"" + res.ToString(_nhi) + "\" order=\"" + level + "\" />");
                level++;
            }
            sb.Append("</TileSets>");

            sb.Append("</TileMap>");
            return(sb.ToString());
        }
Пример #3
0
        private void WriteConfFile(IServiceRequestContext context, IServiceMap serviceMap, TileServiceMetadata metadata, string cacheFormat, int epsg, string format, GridOrientation orientation)
        {
            FileInfo configFileInfo = new FileInfo(_mapServer.TileCachePath + @"\" + serviceMap.Name + @"\_alllayers\" + cacheFormat + @"\" + TileServiceMetadata.EpsgPath(orientation, epsg) + @"\conf.json");

            IPoint    origin = orientation == GridOrientation.UpperLeft ? metadata.GetOriginUpperLeft(epsg) : metadata.GetOriginLowerLeft(epsg);
            IEnvelope bounds = metadata.GetEPSGEnvelope(epsg);

            if (origin == null || bounds == null)
            {
                return;
            }

            List <CompactTileConfig.LevelConfig> levels = new List <CompactTileConfig.LevelConfig>();

            for (int i = 0; i < metadata.Scales.Count; i++)
            {
                levels.Add(new CompactTileConfig.LevelConfig()
                {
                    Level = i,
                    Scale = metadata.Scales[i]
                });
            }

            CompactTileConfig config = new CompactTileConfig()
            {
                Epsg        = epsg,
                Dpi         = metadata.Dpi,
                Origin      = new double[] { origin.X, origin.Y },
                Extent      = new double[] { bounds.minx, bounds.miny, bounds.maxx, bounds.maxy },
                TileSize    = new int[] { metadata.TileWidth, metadata.TileHeight },
                Format      = format,
                Orientation = orientation.ToString(),
                Levels      = levels.ToArray()
            };

            if (configFileInfo.Exists)
            {
                configFileInfo.Delete();
            }

            if (!configFileInfo.Directory.Exists)
            {
                configFileInfo.Directory.Create();
            }

            File.WriteAllText(configFileInfo.FullName, JsonConvert.SerializeObject(config, Formatting.Indented));
        }
Пример #4
0
        private void WmtsCapabilities100(IServiceRequestContext context, TileServiceMetadata metadata)
        {
            gView.Framework.OGC.WMTS.Version_1_0_0.Capabilities capabilities = new Framework.OGC.WMTS.Version_1_0_0.Capabilities()
            {
                version = "1.0.0"
            };

            capabilities.NameSpaces = new System.Xml.Serialization.XmlSerializerNamespaces();
            capabilities.NameSpaces.Add("ows", "http://www.opengis.net/ows/1.1");
            capabilities.NameSpaces.Add("xlink", "http://www.w3.org/1999/xlink");
            capabilities.NameSpaces.Add("gml", "http://www.opengis.net/gml");

            #region ServiceIndentification

            capabilities.ServiceIdentification       = new gView.Framework.OGC.WMTS.Version_1_0_0.ServiceIdentification();
            capabilities.ServiceIdentification.Title = new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType()
                                                                                                                         {
                                                                                                                             Value = context.ServiceMap.Name
                                                                                                                         } };
            capabilities.ServiceIdentification.ServiceType = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType()
            {
                Value = "OGC WMTS"
            };
            capabilities.ServiceIdentification.ServiceTypeVersion = new string[] { "1.0.0" };

            #endregion

            string restFulUrl = context.ServiceRequest.OnlineResource.ToLower().Replace("/maprequest/wmts/", "/tilewmts/");

            #region OperationsMetadata

            capabilities.OperationsMetadata = new gView.Framework.OGC.WMTS.Version_1_0_0.OperationsMetadata();

            var getCapOperation = new gView.Framework.OGC.WMTS.Version_1_0_0.Operation()
            {
                name = "GetCapabilities"
            };
            getCapOperation.DCP               = new gView.Framework.OGC.WMTS.Version_1_0_0.DCP[] { new gView.Framework.OGC.WMTS.Version_1_0_0.DCP() };
            getCapOperation.DCP[0].Item       = new gView.Framework.OGC.WMTS.Version_1_0_0.HTTP();
            getCapOperation.DCP[0].Item.Items = new gView.Framework.OGC.WMTS.Version_1_0_0.RequestMethodType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.RequestMethodType() };

            getCapOperation.DCP[0].Item.Items[0].href                        = context.ServiceRequest.OnlineResource + "?SERVICE=WMTS&VERSION=1.0.0" + "&";
            getCapOperation.DCP[0].Item.Items[0].Constraint                  = new gView.Framework.OGC.WMTS.Version_1_0_0.DomainType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.DomainType() };
            getCapOperation.DCP[0].Item.Items[0].Constraint[0].name          = "GetEncoding";
            getCapOperation.DCP[0].Item.Items[0].Constraint[0].AllowedValues = new object[] { new gView.Framework.OGC.WMTS.Version_1_0_0.ValueType()
                                                                                              {
                                                                                                  Value = "KVP"                                                      /*"RESTful"*/
                                                                                              } };
            getCapOperation.DCP[0].Item.ItemsElementName = new gView.Framework.OGC.WMTS.Version_1_0_0.ItemsChoiceType[] { gView.Framework.OGC.WMTS.Version_1_0_0.ItemsChoiceType.Get };


            var getTileOperation = new gView.Framework.OGC.WMTS.Version_1_0_0.Operation()
            {
                name = "GetTile"
            };
            getTileOperation.DCP               = new gView.Framework.OGC.WMTS.Version_1_0_0.DCP[] { new gView.Framework.OGC.WMTS.Version_1_0_0.DCP() };
            getTileOperation.DCP[0].Item       = new gView.Framework.OGC.WMTS.Version_1_0_0.HTTP();
            getTileOperation.DCP[0].Item.Items = new gView.Framework.OGC.WMTS.Version_1_0_0.RequestMethodType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.RequestMethodType() };

            getTileOperation.DCP[0].Item.Items[0].href                        = restFulUrl;
            getTileOperation.DCP[0].Item.Items[0].Constraint                  = new gView.Framework.OGC.WMTS.Version_1_0_0.DomainType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.DomainType() };
            getTileOperation.DCP[0].Item.Items[0].Constraint[0].name          = "GetEncoding";
            getTileOperation.DCP[0].Item.Items[0].Constraint[0].AllowedValues = new object[] { new gView.Framework.OGC.WMTS.Version_1_0_0.ValueType()
                                                                                               {
                                                                                                   Value = "RESTful"
                                                                                               } };
            getTileOperation.DCP[0].Item.ItemsElementName = new gView.Framework.OGC.WMTS.Version_1_0_0.ItemsChoiceType[] { gView.Framework.OGC.WMTS.Version_1_0_0.ItemsChoiceType.Get };

            capabilities.OperationsMetadata.Operation = new gView.Framework.OGC.WMTS.Version_1_0_0.Operation[]
            {
                getCapOperation, getTileOperation
            };

            #endregion

            #region Contents

            capabilities.Contents = new gView.Framework.OGC.WMTS.Version_1_0_0.ContentsType();

            List <gView.Framework.OGC.WMTS.Version_1_0_0.LayerType>     layers     = new List <gView.Framework.OGC.WMTS.Version_1_0_0.LayerType>();
            List <gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrixSet> matrixSets = new List <gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrixSet>();

            ISpatialReference sRef4326 = SpatialReference.FromID("epsg:4326");

            foreach (var epsg in metadata.EPSGCodes)
            {
                IEnvelope extent = metadata.GetEPSGEnvelope(epsg);
                if (extent == null)
                {
                    continue;
                }
                IPoint origin = metadata.GetOriginUpperLeft(epsg);
                if (origin == null)
                {
                    continue;
                }

                ISpatialReference sRef       = SpatialReference.FromID("epsg:" + epsg);
                IEnvelope         extent4326 = GeometricTransformer.Transform2D(extent, sRef, sRef4326).Envelope;

                if (double.IsInfinity(extent4326.minx))
                {
                    extent4326.minx = -180D;
                }
                if (double.IsInfinity(extent4326.miny))
                {
                    extent4326.miny = -90D;
                }
                if (double.IsInfinity(extent4326.maxx))
                {
                    extent4326.maxx = 180D;
                }
                if (double.IsInfinity(extent4326.maxy))
                {
                    extent4326.maxy = 90D;
                }

                foreach (string cacheType in new string[] { "classic", "compact" })
                {
                    string epsgPath = _mapServer.TileCachePath + @"\" + context.ServiceMap.Name + @"\_alllayers\" + (cacheType == "compact" ? @"compact\" : "") +
                                      TileServiceMetadata.EpsgPath(GridOrientation.UpperLeft, epsg);

                    if (!new DirectoryInfo(epsgPath).Exists)
                    {
                        continue;
                    }

                    #region Layer

                    string layerName = context.ServiceMap.Name + " EPSG:" + epsg + " " + cacheType;
                    string layerId   = context.ServiceMap.Name.ToLower().Replace(" ", "_") + "_" + epsg + "_" + cacheType;

                    var layer = new gView.Framework.OGC.WMTS.Version_1_0_0.LayerType();

                    layer.Title = new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType()
                                                                                                    {
                                                                                                        Value = layerName
                                                                                                    } };
                    layer.Identifier = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType()
                    {
                        Value = layerId
                    };

                    List <gView.Framework.OGC.WMTS.Version_1_0_0.Style> styles = new List <Framework.OGC.WMTS.Version_1_0_0.Style>();
                    //styles.Add(new gView.Framework.OGC.WMTS.Version_1_0_0.Style()
                    //{
                    //    Title = new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType() { Value = "Default Style" } },
                    //    Identifier = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType() { Value = "default" }
                    //});
                    foreach (var styleVal in Enum.GetValues(typeof(ImageProcessingFilters)))
                    {
                        string name = Enum.GetName(typeof(ImageProcessingFilters), styleVal);
                        styles.Add(new Framework.OGC.WMTS.Version_1_0_0.Style()
                        {
                            Title = new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType()
                                                                                                      {
                                                                                                          Value = name
                                                                                                      } },
                            Identifier = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType()
                            {
                                Value = name.ToLower()
                            }
                        });
                    }

                    layer.Style = styles.ToArray();

                    #region BoundingBox

                    layer.BoundingBox = new gView.Framework.OGC.WMTS.Version_1_0_0.BoundingBoxType[]
                    {
                        new gView.Framework.OGC.WMTS.Version_1_0_0.BoundingBoxType()
                        {
                            crs         = "urn:ogc:def:crs:EPSG::" + epsg,
                            LowerCorner = PointToString(extent.LowerLeft, sRef),
                            UpperCorner = PointToString(extent.UpperRight, sRef)
                        }
                    };
                    layer.WGS84BoundingBox = new gView.Framework.OGC.WMTS.Version_1_0_0.WGS84BoundingBoxType[]
                    {
                        new gView.Framework.OGC.WMTS.Version_1_0_0.WGS84BoundingBoxType()
                        {
                            crs         = "urn:ogc:def:crs:OGC:2:84", // urn:ogc:def:crs:OGC:2:84
                            LowerCorner = PointToString(extent4326.LowerLeft, sRef4326),
                            UpperCorner = PointToString(extent4326.UpperRight, sRef4326)
                        }
                    };

                    #endregion

                    layer.TileMatrixSetLink = new gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrixSetLink[]
                    {
                        new gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrixSetLink()
                        {
                            TileMatrixSet = layerId + "_default_matrixset"
                        }
                    };

                    List <string> formats = new List <string>();
                    if (metadata.FormatJpg)
                    {
                        formats.Add("image/jpg");
                    }
                    if (metadata.FormatPng)
                    {
                        formats.Add("image/png");
                    }
                    layer.Format = formats.ToArray();

                    List <Framework.OGC.WMTS.Version_1_0_0.URLTemplateType> resourceURLs = new List <Framework.OGC.WMTS.Version_1_0_0.URLTemplateType>();
                    if (metadata.FormatJpg)
                    {
                        resourceURLs.Add(new Framework.OGC.WMTS.Version_1_0_0.URLTemplateType()
                        {
                            resourceType = Framework.OGC.WMTS.Version_1_0_0.URLTemplateTypeResourceType.tile,
                            format       = "image/jpg",
                            template     = restFulUrl + "/" + cacheType + "/ul/" + epsg + "/{Style}/{TileMatrix}/{TileRow}/{TileCol}.jpg"
                        });
                    }
                    if (metadata.FormatPng)
                    {
                        resourceURLs.Add(new Framework.OGC.WMTS.Version_1_0_0.URLTemplateType()
                        {
                            resourceType = Framework.OGC.WMTS.Version_1_0_0.URLTemplateTypeResourceType.tile,
                            format       = "image/png",
                            template     = restFulUrl + "/" + cacheType + "/ul/" + epsg + "/{Style}/{TileMatrix}/{TileRow}/{TileCol}.png"
                        });
                    }
                    layer.ResourceURL = resourceURLs.ToArray();

                    layers.Add(layer);

                    #endregion

                    #region Matrix Set

                    double matrixSetWidth  = extent.Width;
                    double matrixSetHeight = extent.Height;

                    var matrixSet = new gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrixSet();

                    matrixSet.Title = new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType[] { new gView.Framework.OGC.WMTS.Version_1_0_0.LanguageStringType()
                                                                                                        {
                                                                                                            Value = layerName + " Default Matrix Set"
                                                                                                        } };
                    matrixSet.Identifier = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType()
                    {
                        Value = layerId + "_default_matrixset"
                    };
                    matrixSet.SupportedCRS = "urn:ogc:def:crs:EPSG::" + epsg;

                    matrixSet.TileMatrix = new gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrix[metadata.Scales.Count];

                    #region DPI

                    double inchMeter = 0.0254;                    /* 0.0254000508001016;*/
                    double dpi       = inchMeter * 1000D / 0.28D; // wmts 0.28mm -> 1 Pixel;
                    double dpm       = dpi / inchMeter;

                    #endregion

                    for (int s = 0, to = metadata.Scales.Count; s < to; s++)
                    {
                        string scalePath = _mapServer.TileCachePath + @"\" + context.ServiceMap.Name + @"\_alllayers\" + (cacheType == "compact" ? @"compact\" : "") +
                                           TileServiceMetadata.ScalePath(GridOrientation.UpperLeft, epsg, metadata.Scales[s]);

                        if (!new DirectoryInfo(scalePath).Exists)
                        {
                            break;
                        }

                        double resolution = metadata.Scales[s] / (metadata.Dpi / inchMeter);

                        matrixSet.TileMatrix[s]            = new gView.Framework.OGC.WMTS.Version_1_0_0.TileMatrix();
                        matrixSet.TileMatrix[s].Identifier = new gView.Framework.OGC.WMTS.Version_1_0_0.CodeType()
                        {
                            Value = s.ToString()
                        };
                        matrixSet.TileMatrix[s].TopLeftCorner = PointToString(origin, sRef);
                        matrixSet.TileMatrix[s].TileWidth     = metadata.TileWidth.ToString();
                        matrixSet.TileMatrix[s].TileHeight    = metadata.TileHeight.ToString();

                        double tileWidth  = metadata.TileWidth * resolution;
                        double tileHeight = metadata.TileHeight * resolution;

                        int matrixWidth  = (int)Math.Round(matrixSetWidth / tileWidth + 0.5);
                        int matrixHeight = (int)Math.Round(matrixSetHeight / tileHeight + 0.5);

                        matrixSet.TileMatrix[s].MatrixWidth      = matrixWidth.ToString();
                        matrixSet.TileMatrix[s].MatrixHeight     = matrixHeight.ToString();
                        matrixSet.TileMatrix[s].ScaleDenominator = resolution * dpm;
                    }

                    matrixSets.Add(matrixSet);

                    #endregion
                }
            }

            capabilities.Contents.DatasetDescriptionSummary = layers.ToArray();
            capabilities.Contents.TileMatrixSet             = matrixSets.ToArray();

            #endregion

            XsdSchemaSerializer <gView.Framework.OGC.WMTS.Version_1_0_0.Capabilities> ser = new XsdSchemaSerializer <gView.Framework.OGC.WMTS.Version_1_0_0.Capabilities>();
            string xml = ser.Serialize(capabilities, null);

            xml = xml.Replace(@"<ows:DatasetDescriptionSummary xsi:type=""LayerType"">", "<Layer>");
            xml = xml.Replace(@"</ows:DatasetDescriptionSummary>", "</Layer>");

            context.ServiceRequest.Response = xml;
        }
Пример #5
0
        private void cmbEpsg_SelectedIndexChanged(object sender, EventArgs e)
        {
            lstScales.Items.Clear();

            if (_metadata == null)
            {
                return;
            }

            ISpatialReference sRef = SpatialReference.FromID("epsg:" + cmbEpsg.SelectedItem.ToString());

            if (sRef == null)
            {
                return;
            }

            IEnvelope extent = _metadata.GetEPSGEnvelope((int)cmbEpsg.SelectedItem);

            if (extent == null)
            {
                return;
            }

            double width  = extent.Width;
            double height = extent.Height;

            double dpu = 1.0;

            if (sRef.SpatialParameters.IsGeographic)
            {
                GeoUnitConverter converter = new GeoUnitConverter();
                dpu = converter.Convert(1.0, GeoUnits.Meters, GeoUnits.DecimalDegrees);
            }

            foreach (double scale in _metadata.Scales)
            {
                double tileWidth  = (double)_metadata.TileWidth * (double)scale / (96.0 / 0.0254);
                double tileHeight = (double)_metadata.TileHeight * (double)scale / (96.0 / 0.0254);

                tileWidth  *= dpu;
                tileHeight *= dpu;

                int tx = (int)Math.Floor(width / tileWidth) + 1;
                int ty = (int)Math.Floor(height / tileHeight) + 1;

                lstScales.Items.Add(new ListViewItem(new string[] { scale.ToString(_nhi), ty.ToString(), tx.ToString(), (tx * ty).ToString() }));
                lstScales.Items[lstScales.Items.Count - 1].Checked = true;
            }

            if (!Envelope.IsNull(this.CurrentExtent) &&
                cmbEpsg.SelectedItem != null)
            {
                ISpatialReference oldSRef = SpatialReference.FromID(lblEpsg.Text.Replace("(", "").Replace(")", ""));
                ISpatialReference newSRef = SpatialReference.FromID("epsg:" + cmbEpsg.SelectedItem.ToString());

                IGeometry geom = GeometricTransformer.Transform2D(this.CurrentExtent, oldSRef, newSRef);
                if (geom != null)
                {
                    this.CurrentExtent = geom.Envelope;
                }
            }
            lblEpsg.Text = "(EPSG:" + (cmbEpsg.SelectedItem != null ? cmbEpsg.SelectedItem.ToString() : "0") + ")";
        }
Пример #6
0
        static int Main(string[] args)
        {
            try
            {
                PlugInManager.InitSilent = true;

                Action          action = Action.None;
                string          server = String.Empty, service = String.Empty, cacheFormat = "normal";
                int             epsg = 0, maxParallelRequests = 1;
                GridOrientation orientation = GridOrientation.UpperLeft;
                IEnvelope       bbox        = null;
                List <int>      scales      = new List <int>();

                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i] == "-server")
                    {
                        server = args[++i];
                    }
                    if (args[i] == "-service")
                    {
                        service = args[++i];
                    }
                    if (args[i] == "-info")
                    {
                        action = Action.Info;
                    }
                    if (args[i] == "-render")
                    {
                        action = Action.Render;
                    }
                    if (args[i] == "-compact")
                    {
                        cacheFormat = "compact";
                    }
                    if (args[i] == "-epsg")
                    {
                        epsg = int.Parse(args[++i]);
                    }
                    if (args[i] == "-orientation")
                    {
                        switch (args[++i].ToLower())
                        {
                        case "ul":
                        case "upperleft":
                            orientation = GridOrientation.UpperLeft;
                            break;

                        case "ll":
                        case "lowerleft":
                            orientation = GridOrientation.LowerLeft;
                            break;
                        }
                    }
                    if (args[i] == "-bbox")
                    {
                        bbox = Envelope.FromBBox(args[++i]);
                    }
                    if (args[i] == "-scales")
                    {
                        scales.AddRange(args[++i].Split(',').Select(v => int.Parse(v)));
                    }
                    if (args[i] == "-threads")
                    {
                        maxParallelRequests = int.Parse(args[++i]);
                    }
                }

                if (action == Action.None ||
                    String.IsNullOrWhiteSpace(server) ||
                    String.IsNullOrWhiteSpace(service))
                {
                    Console.WriteLine("USAGE:");
                    Console.WriteLine("gView.Cmd.RenderTileCache <-info|-render> -server <server> -service <service>");
                    Console.WriteLine("       optional paramters: -epsg <epsg-code>                            [default: first]");
                    Console.WriteLine("                           -compact ... create a compact tile cache");
                    Console.WriteLine("                           -orientation <ul|ll|upperleft|lowerleft>     [default: upperleft]");
                    Console.WriteLine("                           -bbox <minx,miny,maxx,maxy>                  [default: fullextent]");
                    Console.WriteLine("                           -scales <scale1,scale2,...>                  [default: empty => all scales");
                    Console.WriteLine("                           -threads <max-parallel-requests>             [default: 1]");

                    return(1);
                }

                #region Read Metadata

                var metadata = new TileServiceMetadata().FromService(server, service);
                if (metadata == null)
                {
                    throw new Exception("Can't read metadata from server. Are you sure taht ervice is a gView WMTS service?");
                }

                #endregion

                if (action == Action.Info)
                {
                    #region TileSize

                    Console.WriteLine($"TileSize [Pixel]: { metadata.TileWidth } x { metadata.TileHeight }");

                    #endregion

                    #region ImageFormat

                    Console.Write("ImageFormats:");
                    Console.Write(metadata.FormatJpg ? " jpg" : "");
                    Console.Write(metadata.FormatPng ? " png" : "");
                    Console.WriteLine();

                    #endregion

                    #region Scales

                    Console.WriteLine("Scales:");
                    if (metadata.Scales != null)
                    {
                        foreach (var scale in metadata.Scales)
                        {
                            Console.WriteLine($"  1 : { scale }");
                        }
                    }

                    #endregion

                    #region Origin

                    Console.Write("Origin:");
                    Console.Write(metadata.UpperLeft ? " upperleft" : "");
                    Console.Write(metadata.LowerLeft ? " lowerleft" : "");
                    Console.WriteLine();

                    if (metadata.EPSGCodes != null)
                    {
                        foreach (var epsgCode in metadata.EPSGCodes)
                        {
                            if (metadata.UpperLeft)
                            {
                                var ul = metadata.GetOriginUpperLeft(epsgCode);
                                Console.WriteLine($"  EPSG:{ epsgCode } upperleft: { ul.X }, { ul.Y }");
                            }
                            if (metadata.LowerLeft)
                            {
                                var ll = metadata.GetOriginUpperLeft(epsgCode);
                                Console.WriteLine($"  EPSG:{ epsgCode } lowerleft: { ll.X }, { ll.Y }");
                            }
                        }
                    }

                    #endregion

                    #region Extents

                    Console.WriteLine("BBox:");
                    if (metadata.EPSGCodes != null)
                    {
                        foreach (var epsgCode in metadata.EPSGCodes)
                        {
                            var envelope = metadata.GetEPSGEnvelope(epsgCode);
                            if (envelope != null)
                            {
                                Console.WriteLine($"  EPSG:{ epsgCode }: { envelope.minx }, { envelope.miny }, { envelope.maxx }, { envelope.maxy }");
                            }
                        }
                    }

                    #endregion
                }
                else if (action == Action.Render)
                {
                    var startTime = DateTime.Now;

                    List <double> preRenderScales = new List <double>();
                    if (scales.Count > 0)
                    {
                        preRenderScales.AddRange(scales.Where(s => metadata.Scales.Contains(s)).Select(s => (double)s));
                    }

                    var tileRender = new TileRenderer(metadata,
                                                      epsg > 0 ? epsg : metadata.EPSGCodes.First(),
                                                      cacheFormat: cacheFormat,
                                                      orientation: orientation,
                                                      bbox: bbox,
                                                      preRenderScales: preRenderScales.Count > 0 ? preRenderScales : null,
                                                      maxParallelRequests: maxParallelRequests);

                    tileRender.Renderer(server, service);

                    Console.WriteLine();
                    Console.WriteLine($"Finished: { Math.Round((DateTime.Now - startTime).TotalSeconds) }sec");
                }

                return(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception:");
                Console.WriteLine(ex.Message);

                return(1);
            }
        }