Subversion Repositories mkgmap

Rev

Rev 3666 | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2006, 2011.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

package uk.me.parabola.mkgmap.reader.osm.boundary;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

/**
 * The class merges two directories with precompiled bounds files. Both directory may contain files covering
 * the same area. These files are merged so that the resulting file contains all boundaries of both
 * files. Boundaries with the same OSM-id that are contained in both files are merged with a union of its covered area.
 * <br/><br/>
 * Using this merger it is possible to create several smaller bounds compilations (e.g. one country only) and merge
 * these compilations together afterwards.
 *
 * @author WanMil
 */

public class BoundaryMerger {

        public BoundaryMerger() {
               
        }
       
        private void copy(File file, File to) {
                String filename = file.getName();
                try (FileChannel in = (new FileInputStream(file)).getChannel();
                                FileChannel out = (new FileOutputStream(new File(to, filename))).getChannel()) {
                        in.transferTo(0, file.length(), out);
                        in.close();
                        out.close();
                } catch (IOException exp) {
                        System.err.println(exp);
                }
        }
       
        public void merge(File dir1, File dir2, File targetDir) throws IOException {
                List<String> fl1 = BoundaryUtil.getBoundaryDirContent(dir1.getAbsolutePath());
                List<String> fl2 = BoundaryUtil.getBoundaryDirContent(dir2.getAbsolutePath());
               
                Collections.sort(fl1);
                Collections.sort(fl2);
               
                ListIterator<String> fl1Iter = fl1.listIterator();
                ListIterator<String> fl2Iter = fl2.listIterator();
               
                BoundarySaver bSave = new BoundarySaver(targetDir, BoundarySaver.QUADTREE_DATA_FORMAT);
                bSave.setCreateEmptyFiles(false);
               
                List<File> copy = new ArrayList<File>();
               
                int processed = 0;
                int all = fl1.size()+fl2.size();
               
                while (fl1Iter.hasNext() || fl2Iter.hasNext()) {
                        String f1 = (fl1Iter.hasNext() ? fl1Iter.next(): null);
                        String f2 = (fl2Iter.hasNext() ? fl2Iter.next(): null);

                        if (f1 == null) {
                                copy.add(new File(dir2,f2));
                        } else if (f2 == null) {
                                copy.add(new File(dir1,f1));
                        } else {
                                int cmp = f1.compareTo(f2);
                                if (cmp < 0) {
                                        copy.add(new File(dir1,f1));
                                        fl2Iter.previous();
                                } else if (cmp > 0) {
                                        copy.add(new File(dir2,f2));
                                        fl1Iter.previous();
                                } else {
                                        BoundaryQuadTree bqt1 = BoundaryUtil.loadQuadTree(dir1.getAbsolutePath(), f1);
                                        if (bqt1 == null){
                                                System.err.println("Failed to load quadtree for " + dir1.getAbsolutePath() + f1);
                                                System.exit(-1);
                                        }
                                        BoundaryQuadTree bqt2 = BoundaryUtil.loadQuadTree(dir2.getAbsolutePath(), f2);
                                        if (bqt2 == null){
                                                System.err.println("Failed to load quadtree for " + dir2.getAbsolutePath() + f2);
                                                System.exit(-1);
                                        }
                                       
                                        bqt1.merge(bqt2);
                                        bSave.saveQuadTree(bqt1, f1);
                                        processed += 2;
                                        System.out.println(processed+"/"+all+" processed");
                                }
                        }
                }
                bSave.end();
               
                for (File f: copy) {
                        copy(f, targetDir);
                        processed++;
                        System.out.println(processed+"/"+all+" processed");
                }
        }
       
        /**
         * @param args
         * @throws IOException
         */

        public static void main(String[] args) throws IOException {
                if (args.length != 3) {
                        System.err.println("java uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryMerger <bounds1> <bounds2> <merge>");
                        System.err.println("<bounds1> <bounds2> : directories with *.bnd files to merge");
                        System.err.println("<merge> target directory, is created if it doesn't exist");
                       
                        return;
                }

                File b1 = new File(args[0]);
                File b2 = new File(args[1]);

                File merge = new File(args[2]);

                // TODO: maybe allow zip as input
                if (b1.exists() == false || b1.isDirectory() == false) {
                        System.err.println(b1 + " does not exist or is not a directory");
                        return;
                }

                if (b2.exists() == false || b2.isDirectory() == false) {
                        System.err.println(b2 + " does not exist or is not a directory");
                        return;
                }

                if (merge.exists() && merge.isDirectory() == false) {
                        System.err.println(merge + " is not a directory");
                }

                if (merge.exists() == false) {
                        merge.mkdirs();
                }
       
                BoundaryMerger merger = new BoundaryMerger();
                merger.merge(b1, b2, merge);
               
        }

}