Ignore:
Timestamp:
2009-08-16T23:36:16+02:00 (16 years ago)
Author:
pieren
Message:

raster image feature implementation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java

    r16791 r17089  
    66import java.awt.Graphics;
    77import java.awt.Graphics2D;
     8import java.awt.Image;
    89import java.awt.Toolkit;
    910import java.awt.image.BufferedImage;
     11import java.awt.image.ImageObserver;
    1012import java.io.EOFException;
    1113import java.io.IOException;
     
    1315import java.io.ObjectOutputStream;
    1416import java.util.ArrayList;
     17import java.util.Vector;
    1518
    1619import javax.swing.Icon;
     
    3538 * server load.
    3639 */
    37 public class WMSLayer extends Layer {
     40public class WMSLayer extends Layer implements ImageObserver {
    3841
    3942    Component[] component = null;
     
    4447            CadastrePlugin.class.getResource("/images/cadastre_small.png")));
    4548
    46     protected ArrayList<GeorefImage> images = new ArrayList<GeorefImage>();
     49    protected Vector<GeorefImage> images = new Vector<GeorefImage>();
    4750
    4851    protected final int serializeFormatVersion = 2;
     
    5659    private String codeCommune = "";
    5760
    58     private EastNorthBound communeBBox = new EastNorthBound(new EastNorth(0,0), new EastNorth(0,0));
     61    public EastNorthBound communeBBox = new EastNorthBound(new EastNorth(0,0), new EastNorth(0,0));
    5962
    6063    private boolean isRaster = false;
    6164
    6265    private EastNorth rasterMin;
    63 
    64     private EastNorth rasterCenter;
    65 
     66    private EastNorth rasterMax;
    6667    private double rasterRatio;
    67 
    68     double cRasterMaxSizeX = 12286;
    69     double cRasterMaxSizeY = 8730;
     68   
     69    private JMenuItem saveAsPng;
    7070
    7171    public WMSLayer() {
     
    9494
    9595    public void grab(CadastreGrabber grabber, Bounds b) throws IOException {
    96         divideBbox(b, Integer.parseInt(Main.pref.get("cadastrewms.scale", Scale.X1.toString())));
     96        if (isRaster) {
     97            b = new Bounds(Main.proj.eastNorth2latlon(rasterMin), Main.proj.eastNorth2latlon(rasterMax));
     98            divideBbox(b, Integer.parseInt(Main.pref.get("cadastrewms.rasterDivider",
     99                    CadastrePreferenceSetting.DEFAULT_RASTER_DIVIDER)));
     100        } else
     101            divideBbox(b, Integer.parseInt(Main.pref.get("cadastrewms.scale", Scale.X1.toString())));
    97102
    98103        for (EastNorthBound n : dividedBbox) {
     
    148153        double dNorth = (lambertMax.north() - minNorth) / factor;
    149154        dividedBbox.clear();
    150         if (factor < 4) {
     155        if (factor < 4 || isRaster) {
    151156            for (int xEast = 0; xEast < factor; xEast++)
    152157                for (int xNorth = 0; xNorth < factor; xNorth++) {
     
    177182        if (isRaster) {
    178183            str += "\n"+tr("Is not vectorized.");
    179             str += "\n"+tr("Raster center: {0}", rasterCenter);
     184            str += "\n"+tr("Raster size: {0}", communeBBox);
    180185        } else
    181186            str += "\n"+tr("Is vectorized.");
     
    195200    @Override
    196201    public void paint(Graphics g, final MapView mv) {
    197         for (GeorefImage img : images)
    198             img.paint((Graphics2D) g, mv, CadastrePlugin.backgroundTransparent,
    199                     CadastrePlugin.transparency, CadastrePlugin.drawBoundaries);
     202        synchronized(this){
     203            for (GeorefImage img : images)
     204                img.paint((Graphics2D) g, mv, CadastrePlugin.backgroundTransparent,
     205                        CadastrePlugin.transparency, CadastrePlugin.drawBoundaries);
     206        }
    200207    }
    201208
     
    215222    @Override
    216223    public Component[] getMenuEntries() {
     224        saveAsPng = new JMenuItem(new MenuActionSaveRasterAs(this));
     225        saveAsPng.setEnabled(isRaster);
    217226        component = new Component[] { new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
    218                 new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)), new JMenuItem(new MenuActionLoadFromCache()),
    219                 new JMenuItem(new LayerListPopup.InfoAction(this)) };
     227                new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)),
     228                new JMenuItem(new MenuActionLoadFromCache()),
     229                saveAsPng,
     230                new JMenuItem(new LayerListPopup.InfoAction(this)),
     231               
     232        };
    220233        return component;
    221234    }
     
    245258
    246259    public void saveToCache(GeorefImage image) {
    247         if (CacheControl.cacheEnabled) {
     260        if (CacheControl.cacheEnabled && !isRaster()) {
    248261            getCacheControl().saveCache(image);
    249262        }
     
    303316    public void setRaster(boolean isRaster) {
    304317        this.isRaster = isRaster;
    305     }
    306 
    307     /**
    308      * Set the eastNorth position in rasterMin which is the 0,0 coordinate (bottom left corner).
    309      * The bounds width is the raster width and height is calculate on a fixed image ratio.
    310      * @param bounds
     318        if (saveAsPng != null)
     319            saveAsPng.setEnabled(isRaster);
     320    }
     321
     322    /**
     323     * Set raster positions used for grabbing and georeferencing.
     324     * rasterMin is the Eaast North of bottom left corner raster image on the screen when image is grabbed.
     325     * The bounds width and height are the raster width and height. The image width matches the current view
     326     * and the image height is adapted.
     327     * Required: the communeBBox must be set (normally it is catched by CadastreInterface and saved by DownloadWMSPlanImage)   
     328     * @param bounds the current main map view boundaries
    311329     */
    312330    public void setRasterBounds(Bounds bounds) {
    313         rasterMin = new EastNorth(Main.proj.latlon2eastNorth(bounds.min).east(), Main.proj.latlon2eastNorth(bounds.min).north());
    314         EastNorth rasterMax = new EastNorth(Main.proj.latlon2eastNorth(bounds.max).east(), Main.proj.latlon2eastNorth(bounds.max).north());
    315         // now, resize on same proportion as wms server raster images (bounds center)
    316         double rasterHalfHeight = (rasterMax.east() - rasterMin.east())/cRasterMaxSizeX*cRasterMaxSizeY/2;
    317         double rasterMid = rasterMin.north() + (rasterMax.north()-rasterMin.north())/2;
    318         rasterMin.setLocation(rasterMin.east(), rasterMid - rasterHalfHeight);
    319         rasterMax.setLocation(rasterMax.east(), rasterMid + rasterHalfHeight);
    320         rasterCenter = new EastNorth(rasterMin.east()+(rasterMax.east()-rasterMin.east())/2,
    321                 rasterMin.north()+(rasterMax.north()-rasterMin.north())/2);
    322         rasterRatio = (rasterMax.east() - rasterMin.east()) / cRasterMaxSizeX;
    323     }
    324 
    325     public EastNorth getRasterMin() {
    326         return rasterMin;
    327     }
    328 
    329     public void setRasterMin(EastNorth rasterMin) {
    330         this.rasterMin = rasterMin;
    331     }
    332 
    333     public void displace(double dx, double dy) {
    334         this.rasterMin = new EastNorth(rasterMin.east() + dx, rasterMin.north() + dy);
    335         this.rasterCenter = new EastNorth(rasterCenter.east() + dx, rasterCenter.north() + dy);
    336         for (GeorefImage img : images)
    337             img.displace(dx, dy);
    338     }
    339 
    340     public void resize(double proportion) {
    341         this.rasterMin = rasterMin.interpolate(rasterCenter, proportion);
    342         for (GeorefImage img : images)
    343             img.resize(rasterCenter, proportion);
    344     }
    345 
    346     public void rotate(double angle) {
    347         this.rasterMin = rasterMin.rotate(rasterCenter, angle);
    348         for (GeorefImage img : images)
    349             img.rotate(rasterCenter, angle);
     331        EastNorth rasterCenter = Main.proj.latlon2eastNorth(bounds.getCenter());
     332        EastNorth eaMin = Main.proj.latlon2eastNorth(bounds.min);
     333        EastNorth eaMax = Main.proj.latlon2eastNorth(bounds.max);
     334        double rasterSizeX = communeBBox.max.getX() - communeBBox.min.getX();
     335        double rasterSizeY = communeBBox.max.getY() - communeBBox.min.getY();
     336        double ratio = rasterSizeY/rasterSizeX;
     337        // keep same ratio on screen as WMS bbox (stored in communeBBox)
     338        rasterMin = new EastNorth(eaMin.getX(), rasterCenter.getY()-(eaMax.getX()-eaMin.getX())*ratio/2);
     339        rasterMax = new EastNorth(eaMax.getX(), rasterCenter.getY()+(eaMax.getX()-eaMin.getX())*ratio/2);
     340        rasterRatio = (rasterMax.getX()-rasterMin.getX())/rasterSizeX;
    350341    }
    351342
     
    363354        if (this.isRaster) {
    364355            oos.writeObject(this.rasterMin);
    365             oos.writeObject(this.rasterCenter);
     356            oos.writeObject(this.rasterMax);
    366357            oos.writeDouble(this.rasterRatio);
    367         } else {
    368             oos.writeObject(this.communeBBox);
    369         }
    370         for (GeorefImage img : imgs) {
    371             oos.writeObject(img);
     358        }
     359        oos.writeObject(this.communeBBox);
     360        synchronized(this){
     361            for (GeorefImage img : imgs) {
     362                oos.writeObject(img);
     363            }
    372364        }
    373365    }
     
    389381        this.setCodeCommune((String) ois.readObject());
    390382        this.lambertZone = ois.readInt();
    391         this.isRaster = ois.readBoolean();
     383        this.setRaster(ois.readBoolean());
    392384        if (this.isRaster) {
    393385            this.rasterMin = (EastNorth) ois.readObject();
    394             this.rasterCenter = (EastNorth) ois.readObject();
     386            this.rasterMax = (EastNorth) ois.readObject();
    395387            this.rasterRatio = ois.readDouble();
    396         } else {
    397             this.communeBBox = (EastNorthBound) ois.readObject();
    398         }
     388        }
     389        this.communeBBox = (EastNorthBound) ois.readObject();
    399390        if (this.lambertZone != currentLambertZone) {
    400391            JOptionPane.showMessageDialog(Main.parent, tr("Lambert zone {0} in cache "+
     
    403394            return false;
    404395        }
    405         boolean EOF = false;
    406         try {
    407             while (!EOF) {
    408                 GeorefImage newImage = (GeorefImage) ois.readObject();
    409                 for (GeorefImage img : this.images) {
    410                     if (CadastrePlugin.backgroundTransparent) {
    411                         if (img.overlap(newImage))
    412                             // mask overlapping zone in already grabbed image
    413                             img.withdraw(newImage);
    414                         else
    415                             // mask overlapping zone in new image only when
    416                             // new image covers completely the existing image
    417                             newImage.withdraw(img);
     396        synchronized(this){
     397            boolean EOF = false;
     398            try {
     399                while (!EOF) {
     400                    GeorefImage newImage = (GeorefImage) ois.readObject();
     401                    for (GeorefImage img : this.images) {
     402                        if (CadastrePlugin.backgroundTransparent) {
     403                            if (img.overlap(newImage))
     404                                // mask overlapping zone in already grabbed image
     405                                img.withdraw(newImage);
     406                            else
     407                                // mask overlapping zone in new image only when
     408                                // new image covers completely the existing image
     409                                newImage.withdraw(img);
     410                        }
    418411                    }
     412                    this.images.add(newImage);
    419413                }
    420                 this.images.add(newImage);
    421             }
    422         } catch (EOFException ex) {
    423             // expected exception when all images are read
     414            } catch (EOFException ex) {
     415                // expected exception when all images are read
     416            }
    424417        }
    425418        return true;
    426419    }
    427 
    428     public double getRasterRatio() {
    429         return rasterRatio;
    430     }
    431 
    432     public void setRasterRatio(double rasterRatio) {
    433         this.rasterRatio = rasterRatio;
    434     }
    435 
    436     public EastNorth getRasterCenter() {
    437         return rasterCenter;
    438     }
    439 
    440     public void setRasterCenter(EastNorth rasterCenter) {
    441         this.rasterCenter = rasterCenter;
     420   
     421    /**
     422     * Join the grabbed images into one single.
     423     * Works only for images grabbed from non-georeferenced images (Feuilles cadastrales)(same amount of
     424     * images in x and y)
     425     */
     426    public void joinRasterImages() {
     427        if (images.size() > 1) {
     428            EastNorth min = images.get(0).min;
     429            EastNorth max = images.get(images.size()-1).max;
     430            int oldImgWidth = images.get(0).image.getWidth();
     431            int oldImgHeight = images.get(0).image.getHeight();
     432            int newWidth = oldImgWidth*(int)Math.sqrt(images.size());
     433            int newHeight = oldImgHeight*(int)Math.sqrt(images.size());
     434            BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
     435            Graphics g = new_img.getGraphics();
     436            // Coordinate (0,0) is on top,left corner where images are grabbed from bottom left
     437            int rasterDivider = (int)Math.sqrt(images.size());
     438            for (int h = 0; h < rasterDivider; h++) {
     439                for (int v = 0; v < rasterDivider; v++) {
     440                    int newx = h*oldImgWidth;
     441                    int newy = newHeight - oldImgHeight - (v*oldImgHeight);
     442                    int j = h*rasterDivider + v;
     443                    g.drawImage(images.get(j).image, newx, newy, this);
     444                }
     445            }
     446            synchronized(this) {
     447                images.clear();
     448                images.add(new GeorefImage(new_img, min, max));
     449            }
     450        }
     451    }
     452   
     453    /**
     454     * Image cropping based on two EN coordinates pointing to two corners in diagonal
     455     * Because it's coming from user mouse clics, we have to sort de positions first.
     456     * Works only for raster image layer (only one image in collection).
     457     * Updates layer georeferences.
     458     * @param en1
     459     * @param en2
     460     */
     461    public void cropImage(EastNorth en1, EastNorth en2){
     462        // adj1 is corner bottom, left
     463        EastNorth adj1 = new EastNorth(en1.east() <= en2.east() ? en1.east() : en2.east(),
     464                en1.north() <= en2.north() ? en1.north() : en2.north());
     465        // adj2 is corner top, right
     466        EastNorth adj2 = new EastNorth(en1.east() > en2.east() ? en1.east() : en2.east(),
     467                en1.north() > en2.north() ? en1.north() : en2.north());
     468        // s1 and s2 have 0,0 at top, left where all EastNorth coord. have 0,0 at bottom, left
     469        int sx1 = (int)((adj1.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
     470        int sy1 = (int)((images.get(0).max.getY() - adj2.getY())*images.get(0).getPixelPerNorth());
     471        int sx2 = (int)((adj2.getX() - images.get(0).min.getX())*images.get(0).getPixelPerEast());
     472        int sy2 = (int)((images.get(0).max.getY() - adj1.getY())*images.get(0).getPixelPerNorth());
     473        int newWidth = Math.abs(sx2 - sx1);
     474        int newHeight = Math.abs(sy2 - sy1);
     475        BufferedImage new_img = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
     476        Graphics g = new_img.getGraphics();
     477        g.drawImage(images.get(0).image, 0, 0, newWidth-1, newHeight-1,
     478                (int)sx1, (int)sy1, (int)sx2, (int)sy2,
     479                this);
     480        images.set(0, new GeorefImage(new_img, adj1, adj2));
     481        // important: update the layer georefs !
     482        rasterMin = adj1;
     483        rasterMax = adj2;
     484        rasterRatio = (rasterMax.getX()-rasterMin.getX())/(communeBBox.max.getX() - communeBBox.min.getX());
     485        setCommuneBBox(new EastNorthBound(new EastNorth(0,0), new EastNorth(newWidth-1,newHeight-1)));
    442486    }
    443487
     
    450494    }
    451495
     496    /**
     497     * Method required by ImageObserver when drawing an image
     498     */
     499    public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
     500        return false;
     501    }
     502
    452503}
Note: See TracChangeset for help on using the changeset viewer.