Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.projection / org.gvsig.projection.cresques / org.gvsig.projection.cresques.impl / src / main / java / org / cresques / impl / geo / Mercator.java @ 42543

History | View | Annotate | Download (12.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.cresques.impl.geo;
25

    
26
import org.cresques.cts.ICoordTrans;
27
import org.cresques.cts.IDatum;
28
import org.cresques.cts.IProjection;
29
import org.cresques.geo.ViewPortData;
30
import org.cresques.px.Extent;
31

    
32
import java.awt.FontMetrics;
33
import java.awt.Graphics2D;
34
import java.awt.geom.AffineTransform;
35
import java.awt.geom.Point2D;
36
import java.awt.geom.Rectangle2D;
37
import java.util.TreeMap;
38

    
39

    
40
/**
41
 * Proyeccion Mercator
42
 * @author "Luis W. Sevilla" <sevilla_lui@gva.es>* @author administrador
43
 */
44
public class Mercator extends Projection {
45
    static String name = "Mercator";
46
    static String abrev = "Mer";
47
    private static TreeMap projPool = new TreeMap();
48
    public static final Mercator hayford = new Mercator(Ellipsoid.hayford);
49
    public static final Mercator wgs84 = new Mercator(Ellipsoid.wgs84);
50
    private double a;
51
    private double f;
52
    private double b;
53
    private double Eps2;
54
    private double EE2;
55
    private double EE3;
56
    private double Epps2;
57

    
58
    public Mercator(Ellipsoid eli) {
59
        super(eli);
60
        grid = new Graticule(this);
61

    
62
        double[] p = eli.getParam();
63
        a = p[1];
64
        f = 1 / p[2];
65
        b = p[3];
66

    
67
        Eps2 = p[5];
68
        EE2 = Eps2 * Eps2;
69
        EE3 = EE2 * Eps2;
70
        Epps2 = p[7];
71
    }
72

    
73
    @Override
74
    public String getAbrev() {
75
        return abrev;
76
    }
77

    
78
    public static Mercator getProjection(Ellipsoid eli) {
79
        Mercator ret = null;
80

    
81
        if (projPool.containsKey(eli.getName())) {
82
            ret = (Mercator) Mercator.projPool.get(eli.getName());
83
        } else {
84
            if (eli == Ellipsoid.hayford) {
85
                ret = hayford;
86
            } else if (eli == Ellipsoid.wgs84) {
87
                ret = wgs84;
88
            } else {
89
                ret = new Mercator(eli);
90
            }
91

    
92
            projPool.put(eli.getName(), ret);
93
        }
94

    
95
        return ret;
96
    }
97

    
98
    /**
99
     *
100
     * @param eli
101
     * @param name
102
     * @return 
103
     */
104
    public static IProjection getProjectionByName(IDatum eli, String name) {
105
        if (name.indexOf("ME") < 0) {
106
            return null;
107
        }
108

    
109
        return getProjection((Ellipsoid) eli);
110
    }
111

    
112
    /**
113
     *
114
     * @param x
115
     * @param y
116
     * @return 
117
     */
118
    @Override
119
    public Point2D createPoint(double x, double y) {
120
        return new ProjPoint(this, x, y);
121
    }
122

    
123
    /**
124
     *
125
     * @param mPt
126
     * @return
127
     */
128
    @Override
129
    public Point2D toGeo(Point2D mPt) {
130
        GeoPoint gPt = new GeoPoint();
131

    
132
        return toGeo((ProjPoint) mPt, gPt);
133
    }
134

    
135
    /**
136
     *
137
     * @param mPt
138
     * @param gPt
139
     * @return
140
     */
141
    public GeoPoint toGeo(ProjPoint mPt, GeoPoint gPt) {
142
        double t = Math.pow(Math.E, (-mPt.getY() / a));
143

    
144
        double x1;
145
        double x = ((Math.PI / 2) - (2 * Math.atan(t)));
146

    
147
        do {
148
            x1 = x;
149
            x = (Math.PI / 2) -
150
                (2 * Math.atan(t * (Math.pow((1 -
151
                                             (Math.sqrt(Eps2) * Math.sin(x))) / (1 +
152
                                             (Math.sqrt(Eps2) * Math.sin(x))),
153
                                             (Math.sqrt(Eps2) / 2)))));
154
        } while ((x - x1) > 0.0000000001);
155

    
156
        double lat = (Math.PI / 2) -
157
                     (2 * Math.atan(t * (Math.pow((1 -
158
                                                  (Math.sqrt(Eps2) * Math.sin(x))) / (1 +
159
                                                  (Math.sqrt(Eps2) * Math.sin(x))),
160
                                                  (Math.sqrt(Eps2) / 2)))));
161

    
162
        double lng = mPt.getX() / a;
163
        gPt.setLocation((lng * 180.0) / Math.PI, (lat * 180.0) / Math.PI);
164
        gPt.proj = Geodetic.getProjection(((Projection) mPt.proj).eli);
165

    
166
        return gPt;
167
    }
168

    
169
    /**
170
     *
171
     * @param gPt
172
     * @param mPt
173
     * @return
174
     */
175
    @Override
176
    public Point2D fromGeo(Point2D gPt, Point2D mPt) {
177
        double sl = Math.sin(((GeoPoint) gPt).Latitude.ToRadians());
178
        double cl = Math.cos(((GeoPoint) gPt).Latitude.ToRadians());
179
        double tl = (1 + sl) / (1 - sl);
180

    
181
        // Calcula Easting
182
        double x = a * ((GeoPoint) gPt).Longitude.ToRadians();
183

    
184
        // Calcula Northing
185
        double y = Math.pow(((1 - (Math.sqrt(Eps2) * sl)) / (1 +
186
                            (Math.sqrt(Eps2) * sl))), (Math.sqrt(Eps2)));
187
        y = a / 2 * (Math.log(tl * y));
188
        ((ProjPoint) mPt).setLocation(x, y);
189
        ((ProjPoint) mPt).proj = this;
190

    
191
        return mPt;
192
    }
193

    
194
    // Calcula el step en funci?n del zoom
195
    private void generateGrid(Graphics2D g, Extent extent, AffineTransform mat) {
196
        // calculo del step en funci?n del zoom
197
        Point2D pt1 = extent.getMin();
198

    
199
        double step = 3.0;
200
        double x = pt1.getX();
201
        double dist = 0.0;
202
        ProjPoint ppt1;
203
        ProjPoint ppt2;
204
        GeoPoint gp1;
205
        GeoPoint gp2;
206
        ppt1 = (ProjPoint) createPoint(x, pt1.getY());
207
        ppt2 = (ProjPoint) createPoint(x + 100, pt1.getY() - 100);
208
        gp1 = (GeoPoint) ppt1.toGeo();
209
        gp2 = (GeoPoint) ppt2.toGeo();
210

    
211
        /*        GeoPoint gp1, gp2;
212
                gp1 = (GeoPoint) createPoint( x, (int) pt1.getY());
213
                mat.transform(gp1, gp1);
214
                gp2 = (GeoPoint) createPoint(gp1.getX()+100, gp1.getY()-100);
215
                try {
216
                        mat.inverseTransform(gp2, gp2);
217
                } catch (NoninvertibleTransformException e) {
218
                        // TODO Auto-generated catch block
219
                        e.printStackTrace();
220
                }
221
                dist = (gp2.getX()-x);
222
                System.err.println("distX = " + dist);
223

224
                if (dist > 30.0) {                         step = 30.0;
225
                } else if (dist > 18.0) {         step = 18.0;
226
                } else if (dist > 12.0) {        step = 12.0;
227
                } else if (dist > 6.0) {        step = 6.0;
228
                } else if (dist > 3.0) {        step = 3.0;
229
                } else if (dist > 2.0) {        step = 2.0;
230
                } else if (dist > 1.0) {        step = 1.0;
231
                } else if (dist > .5) {                step =.5;
232
                } else if (dist > .25) {        step =.25;
233
                } else if (dist > 1.0/60*5.0) { step = 1.0/60*5.0;
234
                } else {                                        step = 1.0/60*2.0;
235
                }
236
                        //step = 1.0;
237
                */
238
        generateGrid(g, extent, mat, step);
239
    }
240

    
241
    private void generateGrid(Graphics2D g, Extent extent, AffineTransform mat,
242
                              double step) {
243
        grid = new Graticule(this);
244

    
245
        Point2D pt1 = extent.getMin();
246
        Point2D pt2 = extent.getMax();
247
        Point2D.Double ptx = new Point2D.Double(0.0, 0.0);
248
        GeoPoint gp1;
249
        GeoPoint gp2;
250
        ProjPoint up1 = (ProjPoint) createPoint(0, 0);
251
        ProjPoint up2 = (ProjPoint) createPoint(0, 0);
252
        Geodetic geoProj = Geodetic.getProjection((Ellipsoid) getDatum());
253
        double xAxis;
254
        double yAxis;
255

    
256
        // Calculos para el texto
257
        FontMetrics fm = g.getFontMetrics();
258
        int fmWidth = 0;
259
        int fmHeight = fm.getAscent();
260
        String tit = "";
261
        String fmt = "%G?%N";
262

    
263
        if (step < 1.0) {
264
            fmt = "%G?%M'%N";
265
        }
266

    
267
        // Lineas Horzontales
268
        gp1 = (GeoPoint) toGeo(new ProjPoint(pt1));
269
        gp2 = (GeoPoint) toGeo(new ProjPoint(pt2));
270
        xAxis = gp1.getX();
271
        yAxis = gp2.getY();
272
        System.err.println(name + ": ViewPort Extent = (" + gp1 + "," + gp2 +
273
                           ")");
274

    
275
        double xMin = (int) gp1.getX() - 1.0;
276
        xMin -= (xMin % step);
277

    
278
        double xMax = (int) gp2.getX() + 1.0;
279
        double yMin = (int) gp1.getY() - 1.0;
280
        yMin -= (yMin % step);
281

    
282
        double yMax = (int) gp2.getY() + 1.0;
283

    
284
        if (xMin < -180.0) {
285
            xMin = -180.0;
286
        }
287

    
288
        if (xMax > 180.0) {
289
            xMax = 180.0;
290
        }
291

    
292
        if (yMin < -80.0) {
293
            yMin = -80.0;
294
        }
295

    
296
        if (yMax > 80.0) {
297
            yMax = 80.0;
298
        }
299

    
300
        if (xAxis < -180.0) {
301
            xAxis = -180.0;
302
        }
303

    
304
        if (yAxis > 80.0) {
305
            yAxis = 80.0;
306
        }
307

    
308
        for (double y = yMin; y <= yMax; y += step) {
309
            gp1 = (GeoPoint) geoProj.createPoint(xAxis, y);
310
            gp2 = (GeoPoint) geoProj.createPoint(xMax, y);
311
            fromGeo(gp1, up1);
312
            fromGeo(gp2, up2);
313
            mat.transform(up1, up1);
314
            mat.transform(up2, up2);
315
            grid.addLine(up1, up2);
316

    
317
            tit = coordToString(y, fmt, true);
318

    
319
            //fmWidth = fm.stringWidth(tit);
320
            ptx.setLocation(up1.getX() + 3, up1.getY() - 2);
321
            grid.addText(tit, ptx);
322
        }
323

    
324
        // Lineas Verticales
325
        for (double x = xMin; x <= xMax; x += step) {
326
            gp1 = (GeoPoint) geoProj.createPoint(x, yMin);
327
            gp2 = (GeoPoint) geoProj.createPoint(x, yAxis);
328
            fromGeo(gp1, up1);
329
            fromGeo(gp2, up2);
330
            mat.transform(up1, up1);
331
            mat.transform(up2, up2);
332
            grid.addLine(up1, up2);
333

    
334
            tit = coordToString(x, fmt, false);
335

    
336
            //fmWidth = fm.stringWidth(tit);
337
            ptx.setLocation(up2.getX() + 3, up2.getY() + fmHeight);
338
            grid.addText(tit, ptx);
339
        }
340
    }
341

    
342
    @Override
343
    public void drawGrid(Graphics2D g, ViewPortData vp) {
344
        generateGrid(g, vp.getExtent(), vp.getMat());
345
        grid.setColor(gridColor);
346
        grid.draw(g, vp);
347
    }
348

    
349
    /* (non-Javadoc)
350
     * @see org.cresques.cts.IProjection#getScale(double, double, double, double)
351
     */
352
    @Override
353
    public double getScale(double minX, double maxX, double width, double dpi) {
354
        Projection prj = Geodetic.getProjection((Ellipsoid) getDatum());
355
        GeoPoint pt1 = (GeoPoint) prj.createPoint(1.0, 0.0);
356
        GeoPoint pt2 = (GeoPoint) prj.createPoint(2.0, 0.0);
357
        ProjPoint ppt1 = (ProjPoint) createPoint(0.0, 0.0);
358
        ProjPoint ppt2 = (ProjPoint) createPoint(0.0, 0.0);
359
        fromGeo(pt1, ppt1);
360
        fromGeo(pt2, ppt2);
361

    
362
        //scale = ppt2.getX()-ppt1.getX();
363
        double scale = (((maxX - minX) / (ppt2.getX() - ppt1.getX())) *
364
        //scale = ((extent.maxX()-extent.minX())/ getWidth());// *
365
        (dpi / 2.54 * 100.0 * 1852.0 * 60.0)) / width;
366

    
367
        return scale;
368
    }
369

    
370
    @Override
371
        public ICoordTrans getCT(IProjection dest) {
372
                // TODO Auto-generated method stub
373
                return null;
374
        }
375

    
376
    @Override
377
        public Rectangle2D getExtent(Rectangle2D extent, double scale, double wImage, double hImage, double mapUnits,double distanceUnits, double dpi) {
378
                Projection prj = Geodetic.getProjection((Ellipsoid) getDatum());
379
        GeoPoint pt1 = (GeoPoint) prj.createPoint(1.0, 0.0);
380
        GeoPoint pt2 = (GeoPoint) prj.createPoint(2.0, 0.0);
381
        ProjPoint ppt1 = (ProjPoint) createPoint(0.0, 0.0);
382
        ProjPoint ppt2 = (ProjPoint) createPoint(0.0, 0.0);
383
        fromGeo(pt1, ppt1);
384
        fromGeo(pt2, ppt2);
385
                double w =0;
386
                double h =0;
387
                double wExtent =0;
388
                double hExtent =0;
389
            w = ((wImage / dpi) * 2.54);
390
                h = ((hImage / dpi) * 2.54);
391
                wExtent =((w*scale*distanceUnits)/ (ppt2.getX() - ppt1.getX()))/ (mapUnits*1852.0*60.0);
392
                hExtent =((h*scale*distanceUnits)/ (ppt2.getX() - ppt1.getX()))/ (mapUnits*1852.0*60.0);
393
                double xExtent = extent.getCenterX() - wExtent/2;
394
                double yExtent = extent.getCenterY() - hExtent/2;
395
                Rectangle2D rec=new Rectangle2D.Double(xExtent,yExtent,wExtent,hExtent);
396
            return  rec;
397
        }
398

    
399
        /* (non-Javadoc)
400
         * @see org.cresques.cts.IProjection#getFullCode()
401
         */
402
    @Override
403
        public String getFullCode() {
404
                return getAbrev();
405
        }
406

    
407
    /* (non-Javadoc)
408
     * @see org.cresques.cts.IProjection#export(java.lang.String)
409
     */
410
    @Override
411
    public String export(String arg0) {
412
        // TODO Auto-generated method stub
413
        return null;
414
    }
415
}