Subversion Repositories splitter

Rev

Rev 606 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (c) 2009, Steve Ratcliffe
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 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.splitter;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

/**
 * A map area in map units.  There is a constructor available for creating
 * in lat/long form.
 *
 * @author Steve Ratcliffe
 */

public class Area {

        public static final Area EMPTY = new Area();

        private int mapId;
        private String name;
        private final int minLat;
        private final int minLong;
        private final int maxLat;
        private final int maxLong;
        private Rectangle javaRect;
        private boolean isJoinable = true;
        private boolean isPseudoArea;
       
        public boolean isJoinable() {
                return isJoinable;
        }

        public void setJoinable(boolean isJoinable) {
                this.isJoinable = isJoinable;
        }

        /**
         * Create an area from the given Garmin coordinates. We ensure that no dimension is zero.
         *
         * @param minLat The western latitude.
         * @param minLong The southern longitude.
         * @param maxLat The eastern lat.
         * @param maxLong The northern long.
         */

        public Area(int minLat, int minLong, int maxLat, int maxLong) {
                this.minLat = minLat;
                if (maxLat == minLat)
                        this.maxLat = minLat + 1;
                else
                        this.maxLat = maxLat;

                this.minLong = minLong;
                if (minLong == maxLong)
                        this.maxLong = maxLong + 1;
                else
                        this.maxLong = maxLong;
        }

        /**
         * Apply bbox to area.
         * @param area the area
         * @param bbox the bounding box
         * @return A new area instance that covers the intersection of area and bbox
         * or null if they don't intersect
         */

        public static Area calcArea (Area area, Rectangle bbox) {
                Rectangle dest = new Rectangle();
                Rectangle2D.intersect(area.getRect(), bbox, dest);
                if (dest.getHeight() > 0 && dest.getWidth() > 0)
                        return new Area(dest.y, dest.x, dest.y + dest.height, dest.x + dest.width);
                return null;
        }


        /**
         * Creates an empty area.
         */

        private Area() {
                minLat = 0;
                maxLat = 0;
                minLong = 0;
                maxLong = 0;
        }

        public boolean verify(){
                return ! (minLat > maxLat || minLong > maxLong
                                || minLong < Utils.MIN_LON_MAP_UNITS
                                || maxLong > Utils.MAX_LON_MAP_UNITS
                                || minLat < Utils.MIN_LAT_MAP_UNITS
                                || maxLat > Utils.MAX_LAT_MAP_UNITS);
        }
       
       
        public Rectangle getRect(){
                if (javaRect == null)
                        javaRect = new Rectangle(this.minLong, this.minLat, this.maxLong-this.minLong, this.maxLat-this.minLat);
                return javaRect;
        }
       
        /**
         *
         * @return a new {@link java.awt.geom.Area} instance
         */

        public java.awt.geom.Area getJavaArea(){
                return new java.awt.geom.Area(getRect());
        }
        public void setMapId(int mapId) {
                this.mapId = mapId;
        }

        public int getMapId() {
                return mapId;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public int getMinLat() {
                return minLat;
        }

        public int getMinLong() {
                return minLong;
        }

        public int getMaxLat() {
                return maxLat;
        }

        public int getMaxLong() {
                return maxLong;
        }

        public int getWidth() {
                return maxLong - minLong;
        }

        public int getHeight() {
                return maxLat - minLat;
        }

        @Override
        public String toString() {
                return "("
                                + Utils.toDegrees(minLat) + ','
                                + Utils.toDegrees(minLong) + ") to ("
                                + Utils.toDegrees(maxLat) + ','
                                + Utils.toDegrees(maxLong) + ')';
        }

        public String toHexString() {
                return "(0x"
                                + Integer.toHexString(minLat) + ",0x"
                                + Integer.toHexString(minLong) + ") to (0x"
                                + Integer.toHexString(maxLat) + ",0x"
                                + Integer.toHexString(maxLong) + ')';
        }

        public boolean contains(int lat, int lon) {
                return lat >= minLat
                                && lat <= maxLat
                                && lon >= minLong
                                && lon <= maxLong;
        }

        public boolean contains(Node node) {
                return contains(node.getMapLat(), node.getMapLon());
        }

        /**
         *
         * @param other an area
         * @return true if the other area is inside the Area (it may touch the boundary)
         */

        public final boolean contains(Area other) {
                return other.getMinLat() >= minLat
                                && other.getMaxLat() <= maxLat
                                && other.getMinLong() >= minLong
                                && other.getMaxLong() <= maxLong;
        }

        /**
         * Checks if this area intersects the given bounding box at least
         * in one point.
         *
         * @param bbox an area
         * @return <code>true</code> if this area intersects the bbox;
         *                 <code>false</code> else
         */

        public final boolean intersects(Area bbox) {
                return minLat <= bbox.getMaxLat() && maxLat >= bbox.getMinLat() &&
                                minLong <= bbox.getMaxLong() && maxLong >= bbox.getMinLong();
        }
       
        public final boolean overlaps(Area bbox) {
                return minLat < bbox.getMaxLat() && maxLat > bbox.getMinLat() &&
                                minLong < bbox.getMaxLong() && maxLong > bbox.getMinLong();
        }
       
 
        public Area add(Area area) {
                return new Area(
                                                Math.min(minLat, area.minLat),
                                                Math.min(minLong, area.minLong),
                                                Math.max(maxLat, area.maxLat),
                                                Math.max(maxLong, area.maxLong)
                );
        }

        public boolean isPseudoArea() {
                return isPseudoArea;
        }

        public void setPseudoArea(boolean isPseudoArea) {
                this.isPseudoArea = isPseudoArea;
        }

}