/* * Copyright (C) 2006 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 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. * * * Author: Steve Ratcliffe * Create date: 18-Dec-2006 */ package uk.me.parabola.mkgmap.general; import java.awt.Rectangle; import java.util.List; import uk.me.parabola.imgfmt.app.Area; import uk.me.parabola.imgfmt.app.Coord; import uk.me.parabola.log.Logger; /** * Represent a line on a Garmin map. Lines are a list of points. They have * a type (major highway, stream etc) and a name. And that is just about it. * * @author Steve Ratcliffe */ public class MapLine extends MapElement { private static final Logger log = Logger.getLogger(MapLine.class); private List<Coord> points; private boolean direction; // set if direction is important. private boolean skipSizeFilter; private boolean wasClipped; private int minLat = Integer.MAX_VALUE; private int minLong = Integer.MAX_VALUE; private int maxLat = Integer.MIN_VALUE; private int maxLong = Integer.MIN_VALUE; public MapLine() { } public MapLine(MapLine orig) { super(orig); direction = orig.direction; skipSizeFilter = orig.skipSizeFilter; //roadDef = orig.roadDef; } public MapLine copy() { return new MapLine(this); } public List<Coord> getPoints() { return points; } public void setPoints(List<Coord> points) { if (this.points != null) log.warn("overwriting points"); assert points != null : "trying to set null points"; assert !points.isEmpty() : "trying to set points with zero length"; this.points = points; // preserve first and last point, so that points which are shared by // different ways are kept if (points.size() > 0 && this instanceof MapShape == false){ points.get(0).preserved(true); points.get(points.size()-1).preserved(true); } testForConsecutivePoints(points); } public void testForConsecutivePoints(List<Coord> points) { Coord last = null; for (Coord co : points) { if (last != null && last.equals(co)) log.info("Line " + getName() + " has consecutive equal points at " + co.toDegreeString()); else { addToBounds(co); last = co; } } } public void insertPointsAtStart(List<Coord> additionalPoints) { assert points.get(0).equals(additionalPoints.get(additionalPoints.size()-1)); testForConsecutivePoints(additionalPoints); points.addAll(0, additionalPoints.subList(0, additionalPoints.size()-1)); } public void insertPointsAtEnd(List<Coord> additionalPoints) { testForConsecutivePoints(additionalPoints); points.remove(points.size()-1); points.addAll(additionalPoints); } public boolean isDirection() { return direction; } public void setDirection(boolean direction) { this.direction = direction; } public boolean isRoad() { return false; } public boolean isSkipSizeFilter() { return skipSizeFilter; } public void setSkipSizeFilter(boolean skipSizeFilter) { this.skipSizeFilter = skipSizeFilter; } public boolean wasClipped() { return wasClipped; } public void setClipped(boolean wasClipped) { this.wasClipped = wasClipped; } /** * Get the mid-point of the bounding box for this element. This is as good * an indication of 'where the element is' as any. Previously we just * used the location of the first point which would lead to biases in * allocating elements to subdivisions. * * @return The mid-point of the bounding box. */ public Coord getLocation() { return new Coord((minLat + maxLat) / 2, (minLong + maxLong) / 2);// high prec not needed } /** * We build up the bounding box of this element by calling this routine. * * @param co The coordinate to add. */ private void addToBounds(Coord co) { int lat = co.getLatitude(); if (lat < minLat) minLat = lat; if (lat > maxLat) maxLat = lat; int lon = co.getLongitude(); if (lon < minLong) minLong = lon; if (lon > maxLong) maxLong = lon; } /** * Get the region that this element covers. * * @return The area that bounds this element. */ public Area getBounds() { return new Area(minLat, minLong, maxLat, maxLong); } /** * @return bounding box that can have 0 height or width */ public Rectangle getRect(){ return new Rectangle(minLong, minLat, maxLong-minLong, maxLat-minLat); } }