Changeset 1544 in osm for utils/josm/plugins/grid/src


Ignore:
Timestamp:
2006-11-04T02:21:56+01:00 (18 years ago)
Author:
enxrah
Message:

Sort out all the math to do arbitrarily orientated lat/lon grids

File:
1 edited

Legend:

Unmodified
Added
Removed
  • utils/josm/plugins/grid/src/grid/GridLayer.java

    r1484 r1544  
    55import java.awt.Component;
    66import java.awt.Graphics;
     7import java.awt.GridBagLayout;
    78import java.awt.Color;
    89import java.awt.Point;
     
    1718import javax.swing.Icon;
    1819import javax.swing.ImageIcon;
     20import javax.swing.JDialog;
     21import javax.swing.JLabel;
    1922import javax.swing.JMenuItem;
    2023import javax.swing.JSeparator;
     24import javax.swing.JColorChooser;
     25import javax.swing.JOptionPane;
     26import javax.swing.JPanel;
     27import javax.swing.JTextField;
    2128
    2229import org.openstreetmap.josm.Main;
     
    3037import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
    3138import org.openstreetmap.josm.gui.layer.Layer;
     39import org.openstreetmap.josm.tools.ColorHelper;
     40import org.openstreetmap.josm.tools.ImageProvider;
     41import org.openstreetmap.josm.tools.GBC;
    3242
    3343/**
     
    3545 */
    3646public class GridLayer extends Layer {
    37 
     47       
    3848        private static Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(GridPlugin.class.getResource("/images/grid.png")));
    39         private LatLon origin, pole;
    40     private float gridunits;
    41     private boolean drawLabels;
    42 
     49        private LatLon origin, pole;
     50        private float gridunits;
     51        private boolean drawLabels;
     52        private Helmert gridtoworld; //worldtogrid;
     53        private Color majcol = Color.RED;
     54        public double a, b, c;
    4355        public GridLayer(String url) {
    44             super(url.indexOf('/') != -1 ? url.substring(url.indexOf('/')+1) : url);
    45             origin = new LatLon(0.0,0.0);
    46             pole = new LatLon(0.0,90.0);
    47             drawLabels = true;
    48         }
    49 
    50     private void setGrid(LatLon origin, LatLon pole){
    51         this.origin = origin;
    52         this.pole = pole;
    53         //need to chech pole is perpendicular from origin;
    54     }
    55     private void toggleLabels(){
    56         drawLabels=!drawLabels;
    57     }
    58     private class toggleLabelsAction extends AbstractAction {
    59         GridLayer layer;
    60         public toggleLabelsAction(GridLayer layer) {
    61             super("show labels");
    62             this.layer = layer;
    63         }
    64         public void actionPerformed(ActionEvent e) {
    65             layer.toggleLabels();
    66         }
    67     }
     56                super(url.indexOf('/') != -1 ? url.substring(url.indexOf('/')+1) : url);
     57                origin = new LatLon(0.0,0.0);
     58                pole = new LatLon(0.0,90.0);
     59                drawLabels = true;
     60                gridtoworld = new Helmert(0.0, 0.0, 0);
     61                //worldtogrid = new Helmert(0.0, 0.0, 0);
     62        }
     63       
     64    //  private void setGrid(LatLon origin, LatLon pole){
     65    //  this.origin = origin;
     66    //  this.pole = pole;
     67                //need to check pole is perpendicular from origin;
     68    //  }
     69        private void setGrid(double a, double b, double c){
     70                System.out.println("Setting grid to :" + a + ", " + b + ", " + c);
     71                this.origin = origin;
     72                this.pole = pole;
     73                //need to chech pole is perpendicular from origin;
     74                this.a=a;
     75                this.b=b;
     76                this.c=c;
     77                gridtoworld = new Helmert(a, b, c);
     78                System.out.println(new LatLon(10,10) + "->" +
     79                                   gridtoworld.transform(new LatLon(10,10)) + "->" +
     80                                   gridtoworld.inverseTransform(gridtoworld.transform(new LatLon(10,10))));
     81                //worldtogrid = new Helmert(-a, -b, -c);
     82        }
     83
     84        private void setUnits(float units){
     85                gridunits = units;
     86        }
     87
     88        private void setUnitsToLatLon(){
     89                gridunits = 0;
     90        }
     91       
     92
     93        private void toggleLabels(){
     94                drawLabels=!drawLabels;
     95        }
     96
     97        private class toggleLabelsAction extends AbstractAction {
     98                GridLayer layer;
     99                public toggleLabelsAction(GridLayer layer) {
     100                        super("show labels");
     101                        this.layer = layer;
     102                }
     103                public void actionPerformed(ActionEvent e) {
     104                        layer.toggleLabels();
     105                        Main.map.repaint();
     106                }
     107        }
     108
     109        private class setWorldAction extends AbstractAction {
     110                GridLayer layer;
     111                public setWorldAction(GridLayer layer) {
     112                        super("set to world");
     113                        this.layer = layer;
     114                }
     115                public void actionPerformed(ActionEvent e) {
     116                        layer.setGrid(0,0,0);
     117                        Main.map.repaint();
     118                }
     119        }
     120        private class incAAction extends AbstractAction {
     121                GridLayer layer;
     122                public incAAction(GridLayer layer) {
     123                        super("increase a");
     124                        this.layer = layer;
     125                }
     126                public void actionPerformed(ActionEvent e) {
     127                        layer.setGrid(layer.a+10,layer.b,layer.c);
     128                        Main.map.repaint();
     129                }
     130        }
     131        private class incBAction extends AbstractAction {
     132                GridLayer layer;
     133                public incBAction(GridLayer layer) {
     134                        super("increase b");
     135                        this.layer = layer;
     136                }
     137                public void actionPerformed(ActionEvent e) {
     138                        layer.setGrid(layer.a,layer.b+10,layer.c);
     139                        Main.map.repaint();
     140                }
     141        }
     142        private class incCAction extends AbstractAction {
     143                GridLayer layer;
     144                public incCAction(GridLayer layer) {
     145                        super("increase c");
     146                        this.layer = layer;
     147                }
     148                public void actionPerformed(ActionEvent e) {
     149                        layer.setGrid(layer.a,layer.b,layer.c+10);
     150                        Main.map.repaint();
     151                }
     152        }
     153        private class setColorAction extends AbstractAction {
     154                GridLayer layer;
     155                public setColorAction(GridLayer layer) {
     156                        super("Customize Color", ImageProvider.get("colorchooser"));
     157                        this.layer = layer;
     158                }
     159                public void actionPerformed(ActionEvent e) {
     160                        String col=ColorHelper.color2html(layer.majcol);
     161                        JColorChooser c = new JColorChooser(ColorHelper.html2color(col));
     162                        Object[] options = new Object[]{tr("OK"), tr("Cancel"), tr("Default")};
     163                        int answer = JOptionPane.showOptionDialog(Main.parent, c, tr("Choose a color"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
     164                        switch (answer) {
     165                        case 0:
     166//                              Main.pref.put("color.layer "+name, ColorHelper.color2html(c.getColor()));
     167                                majcol = c.getColor();
     168                                break;
     169                        case 1:
     170                                return;
     171                        case 2:
     172//                              Main.pref.put("color.layer "+name, null);
     173                                majcol = Color.RED;
     174                                break;
     175                        }
     176                        Main.map.repaint();
     177                }
     178        }
     179
     180        private class setGridLayoutAction extends AbstractAction {
     181                GridLayer layer;
     182                public setGridLayoutAction(GridLayer layer) {
     183                        super("Set grid origin");
     184                        this.layer = layer;
     185                }
     186                public void actionPerformed(ActionEvent e) {
     187                        NumberFormat nf = NumberFormat.getInstance();
     188                        JPanel p = new JPanel(new GridBagLayout());
     189                        JTextField latText = new JTextField(nf.format(layer.a));
     190                        JTextField lonText = new JTextField(nf.format(layer.b));
     191                        JTextField devText = new JTextField(nf.format(layer.c));
     192                        p.add(new JLabel(tr("Grid origin location")), GBC.eol());
     193                        p.add(new JLabel(tr("Latitude")));
     194                        p.add(latText, GBC.eol());
     195                        p.add(new JLabel(tr("Longitude")));
     196                        p.add(lonText, GBC.eol());
     197                        p.add(new JLabel(tr("Grid rotation")));
     198                        p.add(devText, GBC.eol());
     199                        Object[] options = new Object[]{tr("OK"), tr("Cancel"), tr("World")};   
     200                        int answer = JOptionPane.showOptionDialog(Main.parent, p,tr("Grid layout"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
     201                        switch (answer) {
     202                        case 0:
     203                                layer.setGrid(
     204                                        -Double.parseDouble(latText.getText()),
     205                                        -Double.parseDouble(lonText.getText()),
     206                                        Double.parseDouble(devText.getText()));
     207
     208                        case 1:
     209                                return;
     210                        case 2:
     211                                layer.setGrid(0,0,0);
     212                        }
     213                        Main.map.repaint();
     214                }
     215        }
    68216
    69217        @Override public Icon getIcon() {
    70218                return icon;
    71219        }
    72 
     220       
    73221        @Override public String getToolTipText() {
    74                 return tr("Grid layer:" + origin);
     222                return tr("Grid layer:" + a + "," + b + "," + c);
    75223        }
    76224
     
    83231
    84232        @Override public void paint(Graphics g, final MapView mv) {
    85             //draw grid here?
    86 
    87233            //establish viewport size
    88234            int w = mv.getWidth();
    89235            int h = mv.getHeight();
     236
     237            //establish viewport world coordinates
     238            LatLon tl = mv.getLatLon(0,0);
     239            LatLon br = mv.getLatLon(w,h);
     240
     241            //establish max visible world coordinates
     242            double wminlat = Math.max(Math.min(tl.lat(),br.lat()),-Main.proj.MAX_LAT);
     243            double wmaxlat = Math.min(Math.max(tl.lat(),br.lat()), Main.proj.MAX_LAT);
     244            double wminlon = Math.max(Math.min(tl.lon(),br.lon()),-Main.proj.MAX_LON);
     245            double wmaxlon = Math.min(Math.max(tl.lon(),br.lon()), Main.proj.MAX_LON);
    90246           
    91             //establish viewport world coordinates
    92             LatLon tl = mv.getLatLon(0,0);
    93             LatLon br = mv.getLatLon(w,h);
    94 
    95             //establish max visible grid coordinates (currently also world coordinates)
    96             double minlat = Math.max(Math.min(tl.lat(),br.lat()),-Main.proj.MAX_LAT);
    97             double maxlat = Math.min(Math.max(tl.lat(),br.lat()), Main.proj.MAX_LAT);
    98             double minlon = Math.max(Math.min(tl.lon(),br.lon()),-Main.proj.MAX_LON);
    99             double maxlon = Math.min(Math.max(tl.lon(),br.lon()), Main.proj.MAX_LON);
    100 
    101             //span is maximum lat/lon span across visible grid normalised to 800pixels
    102             double span = Math.max((maxlat-minlat),(maxlon-minlon))
    103                 * 800.0/Math.max(h,w);
     247            //establish viewport grid coordinates
     248            //because grid is arbitrarily orientated and may be curved check several points on border
     249            double minlat = 180, maxlat=-180, minlon=90, maxlon=-90;
     250           
     251            for(double x=0;x<=1;x+=0.2){
     252                    LatLon[] p = new LatLon[] {
     253                            gridtoworld.inverseTransform(new LatLon(wminlat, x*wminlon+(1-x)*wmaxlon)),
     254                            gridtoworld.inverseTransform(new LatLon(wmaxlat, x*wminlon+(1-x)*wmaxlon)),
     255                            gridtoworld.inverseTransform(new LatLon(x*wminlat+(1-x)*wmaxlat, wminlon)),
     256                            gridtoworld.inverseTransform(new LatLon(x*wminlat+(1-x)*wmaxlat, wmaxlon))};
     257                    for(int i=0;i<4;i++){
     258                            maxlat=Math.max(p[i].lat(),maxlat);
     259                            minlat=Math.min(p[i].lat(),minlat);
     260                            maxlon=Math.max(p[i].lon(),maxlon);
     261                            minlon=Math.min(p[i].lon(),minlon);
     262                    }
     263            }
     264           
     265            //also check if the singularities are visible
     266            LatLon northpole = gridtoworld.transform(new LatLon(90,0));
     267            LatLon southpole = gridtoworld.transform(new LatLon(-90,0));
     268            if((northpole.lat()>=wminlat) && (northpole.lat()<=wmaxlat) && (northpole.lon()>=wminlon) && (northpole.lon()<=wmaxlon)){
     269                    maxlat=90;
     270                    minlon=-180;
     271                    maxlon=180;
     272            }
     273            if((southpole.lat()>=wminlat) && (southpole.lat()<=wmaxlat) && (southpole.lon()>=wminlon) && (southpole.lon()<=wmaxlon)){
     274                    minlat=-90;
     275                    minlon=-180;
     276                    maxlon=180;
     277            }
     278
     279            //span is maximum lat/lon span across visible grid normalised to 1600pixels
     280            double latspan = (maxlat-minlat) * 1600.0/Math.max(h,w);
     281            double lonspan = (maxlon-minlon) * 1600.0/Math.max(h,w);
    104282
    105283            //grid spacing is power of ten to use for grid interval.
    106             double spacing = Math.pow(10,Math.floor(Math.log(span)/Math.log(10.0))-1.0);
     284            double latspacing = Math.pow(10,Math.floor(Math.log(latspan)/Math.log(10.0))-1.0);
     285            double lonspacing = Math.pow(10,Math.floor(Math.log(lonspan)/Math.log(10.0))-1.0);
     286            if (Math.max(latspan,lonspan)/Math.min(latspan,lonspan)<4){
     287                    lonspacing = latspacing = Math.max(latspacing,lonspacing);
     288            }
     289            double latmaj = (latspacing>=10)?3:10;
     290            double lonmaj = (lonspacing>=10)?3:10;
    107291
    108292            //set up stuff need to draw grid
    109293            NumberFormat nf = NumberFormat.getInstance();
    110             Color majcol = Color.RED;
    111294            Color mincol = (majcol.darker()).darker();
    112295
    113 
    114             System.out.println("Span: "+span);
    115             System.out.println("Spacing: "+spacing);
    116296            g.setFont (new Font("Helvetica", Font.PLAIN, 8));
    117297            FontMetrics fm = g.getFontMetrics();
    118 
    119             for(double lat=spacing*Math.floor(minlat/spacing);lat<maxlat;lat+=spacing){
    120                 for(double lon=spacing*Math.floor(minlon/spacing);lon<maxlon;lon+=spacing){
     298//          g.setWidth(0);
     299            for(double lat=latspacing*Math.floor(minlat/latspacing);lat<maxlat;lat+=latspacing){
     300                for(double lon=lonspacing*Math.floor(minlon/lonspacing);lon<maxlon;lon+=lonspacing){
    121301                    LatLon ll0, lli, llj;
    122                     ll0 = new LatLon(lat,lon);
    123                     lli = new LatLon(lat+spacing,lon);
    124                     llj = new LatLon(lat,lon+spacing);
     302                    ll0 = gridtoworld.transform(new LatLon(lat,lon));
     303                    lli = gridtoworld.transform(new LatLon(lat+latspacing,lon));
     304                    llj = gridtoworld.transform(new LatLon(lat,lon+lonspacing));
    125305                    Point p0=mv.getPoint(Main.proj.latlon2eastNorth(ll0));
    126306                    Point pi=mv.getPoint(Main.proj.latlon2eastNorth(lli));
    127307                    Point pj=mv.getPoint(Main.proj.latlon2eastNorth(llj));
    128308
    129                     if(Math.round(lon/spacing)%10==0)
     309                    if(Math.round(lon/lonspacing)%lonmaj==0)
    130310                        g.setColor(majcol);
    131311                    else
    132312                        g.setColor(mincol);
    133                     g.drawLine(p0.x,p0.y,pi.x,pi.y);
    134 
    135                     if(Math.round(lat/spacing)%10==0)
     313
     314                    drawGridLine(g, mv, ll0, lli);
     315
     316
     317                    if(Math.round(lat/latspacing)%latmaj==0)
    136318                        g.setColor(majcol);
    137319                    else
    138320                        g.setColor(mincol);
    139                     g.drawLine(p0.x,p0.y,pj.x,pj.y);
    140 
    141                     if((Math.round(lon/spacing))%10==0 && (Math.round(lat/spacing))%10==0 && drawLabels){
     321
     322                    drawGridLine(g, mv, ll0, llj);
     323
     324                    if((Math.round(lon/lonspacing))%lonmaj==0 && (Math.round(lat/latspacing))%latmaj==0 && drawLabels){
    142325                        String label = nf.format(lat);
    143326                        int tw = fm.stringWidth(label);
     
    151334        }
    152335
     336        private void drawGridLine(Graphics g, final MapView mv, LatLon ll0, LatLon ll1){
     337                Point p0=mv.getPoint(Main.proj.latlon2eastNorth(ll0));
     338                Point p1=mv.getPoint(Main.proj.latlon2eastNorth(ll1));
     339
     340                if(Math.abs(ll0.lon()-ll1.lon())<180){
     341                        g.drawLine(p0.x,p0.y,p1.x,p1.y);
     342                } else {
     343                        double lat0, lat1, lon0, lon1, latm;
     344                        lon0 = ll0.lon();
     345                        lon1 = ll1.lon();
     346                        if(lon0<0) lon0+=360;
     347                        if(lon1<0) lon1+=360;
     348                        latm = ll0.lat() + (180-lon0)*(ll1.lat()-ll0.lat())/(lon1-lon0);
     349                        Point pm1 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(latm,180)));
     350                        Point pm2 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(latm,-180)));
     351                        if(lon0<=180){
     352                                g.drawLine(p0.x,p0.y,pm1.x,pm1.y);
     353                                g.drawLine(p1.x,p1.y,pm2.x,pm2.y);
     354                        } else {
     355                                g.drawLine(p0.x,p0.y,pm2.x,pm2.y);
     356                                g.drawLine(p1.x,p1.y,pm1.x,pm1.y);
     357                        }
     358                }
     359        }
     360
    153361        @Override public void visitBoundingBox(BoundingXYVisitor v) {
    154362                // doesn't have a bounding box
     
    165373                                new JMenuItem(new toggleLabelsAction(this)),
    166374                                new JSeparator(),
     375                                new JMenuItem(new setGridLayoutAction(this)),
     376                                new JMenuItem(new setWorldAction(this)),
     377                                new JMenuItem(new incAAction(this)),
     378                                new JMenuItem(new incBAction(this)),
     379                                new JMenuItem(new incCAction(this)),
     380                                new JMenuItem(new setColorAction(this)),
     381                                new JSeparator(),
    167382                                new JMenuItem(new LayerListPopup.InfoAction(this))};
    168383        }
Note: See TracChangeset for help on using the changeset viewer.