Subversion Repositories mkgmap

Rev

Rev 4850 | 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.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import uk.me.parabola.imgfmt.app.Area;
import uk.me.parabola.mkgmap.reader.osm.MultiPolygonRelation;
import uk.me.parabola.mkgmap.reader.osm.Relation;
import uk.me.parabola.mkgmap.reader.osm.Way;
import uk.me.parabola.util.Java2DConverter;


public class BoundaryRelation extends MultiPolygonRelation {
        private java.awt.geom.Area outerResultArea;
       
        /** keeps the result of the multipolygon processing */
        private Boundary boundary;
       
        public BoundaryRelation(Relation other, Map<Long, Way> wayMap, Area bbox) {
                super(other, wayMap, bbox);
        }
       
        public Boundary getBoundary() {
                if (boundary == null) {
                        if (outerResultArea == null) {
                                return null;
                        }
                        boundary = new Boundary(outerResultArea, this, "r"+this.getId());
                        outerResultArea = null;
                }
                return boundary;
        }
       
        @Override
        protected boolean isUsable() {
                return true; // we assume that tags were already checked by calling code
        }

        /**
         * Tile bounds have a different meaning when boundaries are compiled. We expect
         * either planet or a bbox around a country extract in tile bounds. A country
         * extract typically only contains the complete admin_level boundaries for one
         * country but also many incomplete boundaries for neighbouring countries. <br>
         * We may either ignore all incomplete boundaries or try to close them using the
         * shape ([country].poly) file. The latter should improve LocationHook results
         * for data outside the country.  
         *
         * @return false
         */

        @Override
        protected boolean assumeDataInBoundsIsComplete() {
                return false;
        }
       
        @Override
        protected boolean needsWaysForOutlines() {
                return false;
        }
       
        @Override
        protected void processQueue(Partition partition, Queue<PolygonStatus> polygonWorkingQueue) {
                if (outerResultArea == null)
                        outerResultArea = new java.awt.geom.Area();
               
                while (!polygonWorkingQueue.isEmpty()) {
       
                        // the polygon is not contained by any other unfinished polygon
                        PolygonStatus currentPolygon = polygonWorkingQueue.poll();
       
                        // this polygon is now processed and should not be used by any
                        // further step
                        partition.markFinished(currentPolygon);
       
                        List<PolygonStatus> holes = partition.getPolygonStatus(currentPolygon);

                        // these polygons must all be checked for holes
                        polygonWorkingQueue.addAll(holes);
       
                        if (currentPolygon.outer) {
                                // add the original ways to the list of ways that get the line tags of the mp
                                // the joined ways may be changed by the auto closing algorithm
                                outerWaysForLineTagging.addAll(currentPolygon.polygon.getOriginalWays());

                                java.awt.geom.Area toAdd = Java2DConverter.createArea(currentPolygon.polygon.getPoints());
                                if (outerResultArea.isEmpty())
                                        outerResultArea = toAdd;
                                else
                                        outerResultArea.add(toAdd);
                        } else {
                                outerResultArea.subtract(Java2DConverter.createArea(currentPolygon.polygon.getPoints()));
                        }
                }
        }

        @Override
        protected boolean doReporting() {
                return false;
        }

        @Override
        protected double getMaxCloseDist() {
                String admString = getTag("admin_level");
                if (admString == null)
                        return 1000;
                switch (admString) {
                case "2": return 50000;
                case "3": return 20000;
                case "4": return 4000;
                default:
                        return 1000;
                }
        }

       
        @Override
        public String toString() {
                String basicInfo = "boundary r" + getId();
                String admLevel = getTag("admin_level");
                if (admLevel != null)
                        return basicInfo + " admlvl=" + admLevel + " (" + getTag("name") + ")";
                String postal = getTag("postal_code");
                if (postal != null)
                        return basicInfo + " postal_code=" + postal;
                return basicInfo;
        }

        @Override
        protected void cleanup() {
                super.cleanup();
                this.getElements().clear();
                ((ArrayList<?>)this.getElements()).trimToSize();
        }
}