Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2287 - 1

2
namespace GMap.NET.Projections
3
{
4
   using System;
5
using System.Collections.Generic;
6
 
7
   /// <summary>
8
   /// GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]
9
   /// PROJCS["LKS94 / Lithuania TM",GEOGCS["LKS94",DATUM["Lithuania_1994_ETRS89",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6126"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4669"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",24],PARAMETER["scale_factor",0.9998],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],AUTHORITY["EPSG","3346"],AXIS["Y",EAST],AXIS["X",NORTH]]
10
   /// </summary>
11
   public class LKS94rProjection : PureProjection
12
   {
13
      public static readonly LKS94rProjection Instance = new LKS94rProjection();
14
 
15
      static readonly double MinLatitude = 53.33;
16
      static readonly double MaxLatitude = 56.55;
17
      static readonly double MinLongitude = 20.22;
18
      static readonly double MaxLongitude = 27.11;
19
 
20
      static readonly double orignX = -5122000;
21
      static readonly double orignY = 10325013.240285;
22
 
23
      static readonly double scaleFactor = 0.9998;                      // scale factor                         
24
      static readonly double centralMeridian = 0.41887902047863912;// Center longitude (projection center) 
25
      static readonly double latOrigin = 0.0;                      // center latitude                   
26
      static readonly double falseNorthing = 0.0;                 // y offset in meters                 
27
      static readonly double falseEasting = 500000.0;          // x offset in meters                    
28
      static readonly double semiMajor = 6378137.0;                 // major axis
29
      static readonly double semiMinor = 6356752.3141403561; // minor axis
30
      static readonly double semiMinor2 = 6356752.3142451793;           // minor axis
31
      static readonly double metersPerUnit = 1.0;
32
      static readonly double COS_67P5 = 0.38268343236508977; // cosine of 67.5 degrees
33
      static readonly double AD_C = 1.0026000;               // Toms region 1 constant
34
 
35
      public override RectLatLng Bounds
36
      {
37
         get
38
         {
39
            return RectLatLng.FromLTRB(MinLongitude, MaxLatitude, MaxLongitude, MinLatitude);
40
         }
41
      }
42
 
43
      GSize tileSize = new GSize(256, 256);
44
      public override GSize TileSize
45
      {
46
         get
47
         {
48
            return tileSize;
49
         }
50
      }
51
 
52
      public override double Axis
53
      {
54
         get
55
         {
56
            return 6378137;
57
         }
58
      }
59
 
60
      public override double Flattening
61
      {
62
         get
63
         {
64
            return (1.0 / 298.257222101);
65
         }
66
      }
67
 
68
      public override GPoint FromLatLngToPixel(double lat, double lng, int zoom)
69
      {
70
         lat = Clip(lat, MinLatitude, MaxLatitude);
71
         lng = Clip(lng, MinLongitude, MaxLongitude);
72
 
73
         double[] lks = new double[] { lng, lat };
74
         lks = DTM10(lks);
75
         lks = MTD10(lks);
76
         lks = DTM00(lks);
77
 
78
         double res = GetTileMatrixResolution(zoom);
79
         return LksToPixel(lks, res);
80
      }
81
 
82
      static GPoint LksToPixel(double[] lks, double res)
83
      {
84
         return new GPoint((long)Math.Floor((lks[0] - orignX) / res), (long)Math.Floor((orignY - lks[1]) / res));
85
      }
86
 
87
      public override PointLatLng FromPixelToLatLng(long x, long y, int zoom)
88
      {
89
         PointLatLng ret = PointLatLng.Empty;
90
 
91
         double res = GetTileMatrixResolution(zoom);
92
 
93
         double[] lks = new double[] { (x * res) + orignX, orignY - (y * res) };
94
         lks = MTD11(lks);
95
         lks = DTM10(lks);
96
         lks = MTD10(lks);
97
 
98
         ret.Lat = Clip(lks[1], MinLatitude, MaxLatitude);
99
         ret.Lng = Clip(lks[0], MinLongitude, MaxLongitude);
100
 
101
         return ret;
102
      }
103
 
104
      double[] DTM10(double[] lonlat)
105
      {
106
         // Eccentricity squared : (a^2 - b^2)/a^2
107
         double es = 1.0 - (semiMinor2 * semiMinor2) / (semiMajor * semiMajor); // e^2
108
 
109
         // Second eccentricity squared : (a^2 - b^2)/b^2
110
         double ses = (Math.Pow(semiMajor, 2) - Math.Pow(semiMinor2, 2)) / Math.Pow(semiMinor2, 2);
111
 
112
         double ba = semiMinor2 / semiMajor;
113
         double ab = semiMajor / semiMinor2;
114
 
115
         double lon = DegreesToRadians(lonlat[0]);
116
         double lat = DegreesToRadians(lonlat[1]);
117
         double h = lonlat.Length < 3 ? 0 : lonlat[2].Equals(Double.NaN) ? 0 : lonlat[2];
118
         double v = semiMajor / Math.Sqrt(1 - es * Math.Pow(Math.Sin(lat), 2));
119
         double x = (v + h) * Math.Cos(lat) * Math.Cos(lon);
120
         double y = (v + h) * Math.Cos(lat) * Math.Sin(lon);
121
         double z = ((1 - es) * v + h) * Math.Sin(lat);
122
         return new double[] { x, y, z, };
123
      }
124
 
125
      double[] MTD10(double[] pnt)
126
      {
127
         // Eccentricity squared : (a^2 - b^2)/a^2
128
         double es = 1.0 - (semiMinor * semiMinor) / (semiMajor * semiMajor); // e^2
129
 
130
         // Second eccentricity squared : (a^2 - b^2)/b^2
131
         double ses = (Math.Pow(semiMajor, 2) - Math.Pow(semiMinor, 2)) / Math.Pow(semiMinor, 2);
132
 
133
         double ba = semiMinor / semiMajor;
134
         double ab = semiMajor / semiMinor;
135
 
136
         bool AtPole = false; // is location in polar region
137
         double Z = pnt.Length < 3 ? 0 : pnt[2].Equals(Double.NaN) ? 0 : pnt[2];
138
 
139
         double lon = 0;
140
         double lat = 0;
141
         double Height = 0;
142
         if(pnt[0] != 0.0)
143
         {
144
            lon = Math.Atan2(pnt[1], pnt[0]);
145
         }
146
         else
147
         {
148
            if(pnt[1] > 0)
149
            {
150
               lon = Math.PI / 2;
151
            }
152
            else
153
               if(pnt[1] < 0)
154
               {
155
                  lon = -Math.PI * 0.5;
156
               }
157
               else
158
               {
159
                  AtPole = true;
160
                  lon = 0.0;
161
                  if(Z > 0.0) // north pole
162
                  {
163
                     lat = Math.PI * 0.5;
164
                  }
165
                  else
166
                     if(Z < 0.0) // south pole
167
                     {
168
                        lat = -Math.PI * 0.5;
169
                     }
170
                     else // center of earth
171
                     {
172
                        return new double[] { RadiansToDegrees(lon), RadiansToDegrees(Math.PI * 0.5), -semiMinor, };
173
                     }
174
               }
175
         }
176
         double W2 = pnt[0] * pnt[0] + pnt[1] * pnt[1]; // Square of distance from Z axis
177
         double W = Math.Sqrt(W2); // distance from Z axis
178
         double T0 = Z * AD_C; // initial estimate of vertical component
179
         double S0 = Math.Sqrt(T0 * T0 + W2); // initial estimate of horizontal component
180
         double Sin_B0 = T0 / S0; // sin(B0), B0 is estimate of Bowring aux variable
181
         double Cos_B0 = W / S0; // cos(B0)
182
         double Sin3_B0 = Math.Pow(Sin_B0, 3);
183
         double T1 = Z + semiMinor * ses * Sin3_B0; // corrected estimate of vertical component
184
         double Sum = W - semiMajor * es * Cos_B0 * Cos_B0 * Cos_B0; // numerator of cos(phi1)
185
         double S1 = Math.Sqrt(T1 * T1 + Sum * Sum); // corrected estimate of horizontal component
186
         double Sin_p1 = T1 / S1; // sin(phi1), phi1 is estimated latitude
187
         double Cos_p1 = Sum / S1; // cos(phi1)
188
         double Rn = semiMajor / Math.Sqrt(1.0 - es * Sin_p1 * Sin_p1); // Earth radius at location
189
         if(Cos_p1 >= COS_67P5)
190
         {
191
            Height = W / Cos_p1 - Rn;
192
         }
193
         else
194
            if(Cos_p1 <= -COS_67P5)
195
            {
196
               Height = W / -Cos_p1 - Rn;
197
            }
198
            else
199
            {
200
               Height = Z / Sin_p1 + Rn * (es - 1.0);
201
            }
202
 
203
         if(!AtPole)
204
         {
205
            lat = Math.Atan(Sin_p1 / Cos_p1);
206
         }
207
         return new double[] { RadiansToDegrees(lon), RadiansToDegrees(lat), Height, };
208
      }
209
 
210
      double[] DTM00(double[] lonlat)
211
      {
212
         double e0, e1, e2, e3; // eccentricity constants               
213
         double e, es, esp;             // eccentricity constants               
214
         double ml0;                     // small value m                       
215
 
216
         es = 1.0 - Math.Pow(semiMinor / semiMajor, 2);
217
         e = Math.Sqrt(es);
218
         e0 = e0fn(es);
219
         e1 = e1fn(es);
220
         e2 = e2fn(es);
221
         e3 = e3fn(es);
222
         ml0 = semiMajor * mlfn(e0, e1, e2, e3, latOrigin);
223
         esp = es / (1.0 - es);
224
 
225
         // ...         
226
 
227
         double lon = DegreesToRadians(lonlat[0]);
228
         double lat = DegreesToRadians(lonlat[1]);
229
 
230
         double delta_lon = 0.0;  // Delta longitude (Given longitude - center)
231
         double sin_phi, cos_phi; // sin and cos value                          
232
         double al, als;                    // temporary values                         
233
         double c, t, tq;              // temporary values                              
234
         double con, n, ml;         // cone constant, small m                   
235
 
236
         delta_lon = AdjustLongitude(lon - centralMeridian);
237
         SinCos(lat, out sin_phi, out cos_phi);
238
 
239
         al = cos_phi * delta_lon;
240
         als = Math.Pow(al, 2);
241
         c = esp * Math.Pow(cos_phi, 2);
242
         tq = Math.Tan(lat);
243
         t = Math.Pow(tq, 2);
244
         con = 1.0 - es * Math.Pow(sin_phi, 2);
245
         n = semiMajor / Math.Sqrt(con);
246
         ml = semiMajor * mlfn(e0, e1, e2, e3, lat);
247
 
248
         double x = scaleFactor * n * al * (1.0 + als / 6.0 * (1.0 - t + c + als / 20.0 *
249
             (5.0 - 18.0 * t + Math.Pow(t, 2) + 72.0 * c - 58.0 * esp))) + falseEasting;
250
 
251
         double y = scaleFactor * (ml - ml0 + n * tq * (als * (0.5 + als / 24.0 *
252
             (5.0 - t + 9.0 * c + 4.0 * Math.Pow(c, 2) + als / 30.0 * (61.0 - 58.0 * t
253
             + Math.Pow(t, 2) + 600.0 * c - 330.0 * esp))))) + falseNorthing;
254
 
255
         if(lonlat.Length < 3)
256
            return new double[] { x / metersPerUnit, y / metersPerUnit };
257
         else
258
            return new double[] { x / metersPerUnit, y / metersPerUnit, lonlat[2] };
259
      }
260
 
261
      double[] DTM01(double[] lonlat)
262
      {
263
         // Eccentricity squared : (a^2 - b^2)/a^2
264
         double es = 1.0 - (semiMinor * semiMinor) / (semiMajor * semiMajor);
265
 
266
         // Second eccentricity squared : (a^2 - b^2)/b^2
267
         double ses = (Math.Pow(semiMajor, 2) - Math.Pow(semiMinor, 2)) / Math.Pow(semiMinor, 2);
268
 
269
         double ba = semiMinor / semiMajor;
270
         double ab = semiMajor / semiMinor;
271
 
272
         double lon = DegreesToRadians(lonlat[0]);
273
         double lat = DegreesToRadians(lonlat[1]);
274
         double h = lonlat.Length < 3 ? 0 : lonlat[2].Equals(Double.NaN) ? 0 : lonlat[2];
275
         double v = semiMajor / Math.Sqrt(1 - es * Math.Pow(Math.Sin(lat), 2));
276
         double x = (v + h) * Math.Cos(lat) * Math.Cos(lon);
277
         double y = (v + h) * Math.Cos(lat) * Math.Sin(lon);
278
         double z = ((1 - es) * v + h) * Math.Sin(lat);
279
         return new double[] { x, y, z, };
280
      }
281
 
282
      double[] MTD01(double[] pnt)
283
      {
284
         // Eccentricity squared : (a^2 - b^2)/a^2
285
         double es = 1.0 - (semiMinor2 * semiMinor2) / (semiMajor * semiMajor);
286
 
287
         // Second eccentricity squared : (a^2 - b^2)/b^2
288
         double ses = (Math.Pow(semiMajor, 2) - Math.Pow(semiMinor2, 2)) / Math.Pow(semiMinor2, 2);
289
 
290
         double ba = semiMinor2 / semiMajor;
291
         double ab = semiMajor / semiMinor2;
292
 
293
         bool At_Pole = false; // is location in polar region
294
         double Z = pnt.Length < 3 ? 0 : pnt[2].Equals(Double.NaN) ? 0 : pnt[2];
295
 
296
         double lon = 0;
297
         double lat = 0;
298
         double Height = 0;
299
         if(pnt[0] != 0.0)
300
         {
301
            lon = Math.Atan2(pnt[1], pnt[0]);
302
         }
303
         else
304
         {
305
            if(pnt[1] > 0)
306
            {
307
               lon = Math.PI / 2;
308
            }
309
            else
310
               if(pnt[1] < 0)
311
               {
312
                  lon = -Math.PI * 0.5;
313
               }
314
               else
315
               {
316
                  At_Pole = true;
317
                  lon = 0.0;
318
                  if(Z > 0.0) // north pole
319
                  {
320
                     lat = Math.PI * 0.5;
321
                  }
322
                  else
323
                     if(Z < 0.0) // south pole
324
                     {
325
                        lat = -Math.PI * 0.5;
326
                     }
327
                     else // center of earth
328
                     {
329
                        return new double[] { RadiansToDegrees(lon), RadiansToDegrees(Math.PI * 0.5), -semiMinor2, };
330
                     }
331
               }
332
         }
333
 
334
         double W2 = pnt[0] * pnt[0] + pnt[1] * pnt[1]; // Square of distance from Z axis
335
         double W = Math.Sqrt(W2);                      // distance from Z axis
336
         double T0 = Z * AD_C;                // initial estimate of vertical component
337
         double S0 = Math.Sqrt(T0 * T0 + W2); //initial estimate of horizontal component
338
         double Sin_B0 = T0 / S0;             // sin(B0), B0 is estimate of Bowring aux variable
339
         double Cos_B0 = W / S0;              // cos(B0)
340
         double Sin3_B0 = Math.Pow(Sin_B0, 3);
341
         double T1 = Z + semiMinor2 * ses * Sin3_B0; //corrected estimate of vertical component
342
         double Sum = W - semiMajor * es * Cos_B0 * Cos_B0 * Cos_B0; // numerator of cos(phi1)
343
         double S1 = Math.Sqrt(T1 * T1 + Sum * Sum); // corrected estimate of horizontal component
344
         double Sin_p1 = T1 / S1;  // sin(phi1), phi1 is estimated latitude
345
         double Cos_p1 = Sum / S1; // cos(phi1)
346
         double Rn = semiMajor / Math.Sqrt(1.0 - es * Sin_p1 * Sin_p1); // Earth radius at location
347
 
348
         if(Cos_p1 >= COS_67P5)
349
         {
350
            Height = W / Cos_p1 - Rn;
351
         }
352
         else
353
            if(Cos_p1 <= -COS_67P5)
354
            {
355
               Height = W / -Cos_p1 - Rn;
356
            }
357
            else
358
            {
359
               Height = Z / Sin_p1 + Rn * (es - 1.0);
360
            }
361
 
362
         if(!At_Pole)
363
         {
364
            lat = Math.Atan(Sin_p1 / Cos_p1);
365
         }
366
         return new double[] { RadiansToDegrees(lon), RadiansToDegrees(lat), Height, };
367
      }
368
 
369
      double[] MTD11(double[] p)
370
      {
371
         double e0, e1, e2, e3; // eccentricity constants               
372
         double e, es, esp;             // eccentricity constants               
373
         double ml0;                // small value m
374
 
375
         es = 1.0 - Math.Pow(semiMinor / semiMajor, 2);
376
         e = Math.Sqrt(es);
377
         e0 = e0fn(es);
378
         e1 = e1fn(es);
379
         e2 = e2fn(es);
380
         e3 = e3fn(es);
381
         ml0 = semiMajor * mlfn(e0, e1, e2, e3, latOrigin);
382
         esp = es / (1.0 - es);
383
 
384
         // ...
385
 
386
         double con, phi;
387
         double delta_phi;
388
         long i;
389
         double sin_phi, cos_phi, tan_phi;
390
         double c, cs, t, ts, n, r, d, ds;
391
         long max_iter = 6;
392
 
393
         double x = p[0] * metersPerUnit - falseEasting;
394
         double y = p[1] * metersPerUnit - falseNorthing;
395
 
396
         con = (ml0 + y / scaleFactor) / semiMajor;
397
         phi = con;
398
         for(i = 0; ; i++)
399
         {
400
            delta_phi = ((con + e1 * Math.Sin(2.0 * phi) - e2 * Math.Sin(4.0 * phi) + e3 * Math.Sin(6.0 * phi)) / e0) - phi;
401
            phi += delta_phi;
402
 
403
            if(Math.Abs(delta_phi) <= EPSLoN)
404
               break;
405
 
406
            if(i >= max_iter)
407
               throw new ArgumentException("Latitude failed to converge");
408
         }
409
 
410
         if(Math.Abs(phi) < HALF_PI)
411
         {
412
            SinCos(phi, out sin_phi, out cos_phi);
413
            tan_phi = Math.Tan(phi);
414
            c = esp * Math.Pow(cos_phi, 2);
415
            cs = Math.Pow(c, 2);
416
            t = Math.Pow(tan_phi, 2);
417
            ts = Math.Pow(t, 2);
418
            con = 1.0 - es * Math.Pow(sin_phi, 2);
419
            n = semiMajor / Math.Sqrt(con);
420
            r = n * (1.0 - es) / con;
421
            d = x / (n * scaleFactor);
422
            ds = Math.Pow(d, 2);
423
 
424
            double lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t +
425
                10.0 * c - 4.0 * cs - 9.0 * esp - ds / 30.0 * (61.0 + 90.0 * t +
426
                298.0 * c + 45.0 * ts - 252.0 * esp - 3.0 * cs)));
427
 
428
            double lon = AdjustLongitude(centralMeridian + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t +
429
                c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * esp +
430
                24.0 * ts))) / cos_phi));
431
 
432
            if(p.Length < 3)
433
               return new double[] { RadiansToDegrees(lon), RadiansToDegrees(lat) };
434
            else
435
               return new double[] { RadiansToDegrees(lon), RadiansToDegrees(lat), p[2] };
436
         }
437
         else
438
         {
439
            if(p.Length < 3)
440
               return new double[] { RadiansToDegrees(HALF_PI * Sign(y)), RadiansToDegrees(centralMeridian) };
441
            else
442
               return new double[] { RadiansToDegrees(HALF_PI * Sign(y)), RadiansToDegrees(centralMeridian), p[2] };
443
         }
444
      }
445
 
446
      #region -- levels info --
447
            /*
448
         * "layers":[
449
         * {"id":0,"name":"Lietuva","parentLayerId":-1,"defaultVisibility":true,
450
         * "subLayerIds":null,
451
         *
452
         * "minScale":10000000,"maxScale":900}],
453
         * "tables":[],"spatialReference":{"wkid":2600,"latestWkid":3346},
454
         * "singleFusedMapCache":true,"tileInfo":{"rows":256,"cols":256,"dpi":96,"format":"MIXED","compressionQuality":90,
455
         *
456
         * "origin":{"x":-5122000,"y":1.0325013240285E7},
457
         * "spatialReference":{"wkid":2600,"latestWkid":3346},
458
         *
459
         * "lods":[
460
         * {"level":0,"resolution":1587.5031750063501,"scale":6000000},
461
         * {"level":1,"resolution":793.7515875031751,"scale":3000000},
462
         * {"level":2,"resolution":529.1677250021168,"scale":2000000},
463
         * {"level":3,"resolution":264.5838625010584,"scale":1000000},
464
         * {"level":4,"resolution":132.2919312505292,"scale":500000},
465
         * {"level":5,"resolution":52.91677250021167,"scale":200000},
466
         * {"level":6,"resolution":26.458386250105836,"scale":100000},
467
         * {"level":7,"resolution":13.229193125052918,"scale":50000},
468
         * {"level":8,"resolution":6.614596562526459,"scale":25000},
469
         * {"level":9,"resolution":2.6458386250105836,"scale":10000},
470
         * {"level":10,"resolution":1.3229193125052918,"scale":5000},
471
         * {"level":11,"resolution":0.5291677250021167,"scale":2000},
472
         * {"level":12,"resolution":0.26458386250105836,"scale":1000}]},
473
         *
474
         * "initialExtent":
475
         * {"xmin":219818.60040028347,"ymin":5826291.964691277,
476
         * "xmax":747927.9899523959,"ymax":6407318.126743601,
477
         * "spatialReference":{"wkid":2600,"latestWkid":3346}},
478
         *
479
         * * "fullExtent":
480
         * {"xmin":38843.23844955949,"ymin":5663308.305390623,
481
         * "xmax":907736.6429030352,"ymax":6555485.089744193,
482
         *
483
         * "spatialReference":{"wkid":2600,"latestWkid":3346}},
484
         * "minScale":6000000,"maxScale":5000,"units":"esriMeters","supportedImageFormatTypes":"PNG32,PNG24,PNG,JPG,DIB,TIFF,EMF,PS,PDF,GIF,SVG,SVGZ,BMP",
485
         * "documentInfo":{"Title":"Lietuvos reljefinis žemėlapis","Author":"","Comments":"","Subject":"","Category":"","AntialiasingMode":"None","TextAntialiasingMode":"Force","Keywords":""},"capabilities":"Map","supportedQueryFormats":"JSON, AMF","exportTilesAllowed":false,"maxRecordCount":1000,"maxImageHeight":4096,"maxImageWidth":4096,"supportedExtensions":""});*/
486
      #endregion
487
 
488
      public static double GetTileMatrixResolution(int zoom)
489
      {
490
         double ret = 0;
491
 
492
         switch(zoom)
493
         {
494
            #region -- sizes --
495
            case 0:
496
            {
497
               ret = 1587.5031750063501;
498
            }    
499
            break;
500
 
501
            case 1:
502
            {
503
               ret = 793.7515875031751;
504
            }
505
            break;
506
 
507
            case 2:
508
            {
509
               ret = 529.1677250021168;
510
            }
511
            break;
512
 
513
            case 3:
514
            {
515
               ret = 264.5838625010584;
516
            }
517
            break;
518
 
519
            case 4:
520
            {
521
               ret = 132.2919312505292;
522
            }
523
            break;
524
 
525
            case 5:
526
            {
527
               ret = 52.91677250021167;
528
            }
529
            break;
530
 
531
            case 6:
532
            {
533
               ret = 26.458386250105836;
534
            }
535
            break;
536
 
537
            case 7:
538
            {
539
               ret = 13.229193125052918;
540
            }
541
            break;
542
 
543
            case 8:
544
            {
545
               ret = 6.614596562526459;
546
            }
547
            break;
548
 
549
            case 9:
550
            {
551
               ret = 2.6458386250105836;
552
            }
553
            break;
554
 
555
            case 10:
556
            {
557
               ret = 1.3229193125052918;
558
            }
559
            break;
560
 
561
            case 11:
562
            {
563
               ret = 0.5291677250021167;
564
            }
565
            break;
566
 
567
            case 12:
568
            {
569
               ret = 0.26458386250105836;
570
            }
571
            break;
572
            #endregion
573
         }
574
 
575
         return ret;
576
      }
577
 
578
      public override double GetGroundResolution(int zoom, double latitude)
579
      {
580
         return GetTileMatrixResolution(zoom);
581
      }
582
 
583
      Dictionary<int, GSize> extentMatrixMin;
584
      Dictionary<int, GSize> extentMatrixMax;                                  
585
 
586
      public override GSize GetTileMatrixMinXY(int zoom)
587
      {
588
         if(extentMatrixMin == null)
589
         {
590
            GenerateExtents();
591
         }  
592
         return extentMatrixMin[zoom];
593
      }
594
 
595
      public override GSize GetTileMatrixMaxXY(int zoom)
596
      {
597
         if(extentMatrixMax == null)
598
         {
599
            GenerateExtents();
600
         }
601
         return extentMatrixMax[zoom];
602
      }
603
 
604
      void GenerateExtents()
605
      {
606
         extentMatrixMin = new Dictionary<int, GSize>();
607
         extentMatrixMax = new Dictionary<int, GSize>();
608
         //RectLatLng Extent = RectLatLng.FromLTRB(219818.60040028347, 6407318.126743601, 747927.9899523959, 5826291.964691277);
609
 
610
         for(int i = 0; i <= 12; i++)
611
         {
612
            double res = GetTileMatrixResolution(i);
613
            //extentMatrixMin.Add(i, new GSize(FromPixelToTileXY(LksToPixel(new double[]{ Extent.Left, Extent.Top }, res))));
614
            //extentMatrixMax.Add(i, new GSize(FromPixelToTileXY(LksToPixel(new double[] { Extent.Right, Extent.Bottom }, res))));
615
 
616
            extentMatrixMin.Add(i, new GSize(FromPixelToTileXY(FromLatLngToPixel(Bounds.LocationTopLeft, i))));
617
            extentMatrixMax.Add(i, new GSize(FromPixelToTileXY(FromLatLngToPixel(Bounds.LocationRightBottom, i))));
618
         }
619
      }
620
   }
621
}