/* * Copyright (C) 2007 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. * */ package uk.me.parabola.mkgmap.filters; import java.util.ArrayList; import java.util.List; import uk.me.parabola.imgfmt.app.Coord; import uk.me.parabola.imgfmt.app.CoordNode; import uk.me.parabola.mkgmap.general.MapElement; import uk.me.parabola.mkgmap.general.MapLine; public class RoundCoordsFilter implements MapFilter { private int shift; private boolean checkRouting; public void init(FilterConfig config) { shift = config.getShift(); checkRouting = config.getLevel() == 0 && config.isRoutable() == true; } /** * @param element A map element that will be a line or a polygon. * @param next This is used to pass the possibly transformed element onward. */ public void doFilter(MapElement element, MapFilterChain next) { MapLine line = (MapLine) element; int half = 1 << (shift - 1); // 0.5 shifted int mask = ~((1 << shift) - 1); // to remove fraction bits if(shift == 0) { // do nothing next.doFilter(line); } else { // round lat/lon values to nearest for shift List<Coord> newPoints = new ArrayList<Coord>(line.getPoints().size()); Coord lastP = null; for(Coord p : line.getPoints()) { int lat = (p.getLatitude() + half) & mask; int lon = (p.getLongitude() + half) & mask; Coord newP; if(p instanceof CoordNode && checkRouting) newP = new CoordNode(lat, lon, p.getId(), p.getOnBoundary()); else newP = new Coord(lat, lon); newP.preserved(p.preserved()); // only add the new point if it has different // coordinates to the last point or if it's a // CoordNode and the last point wasn't a CoordNode if(lastP == null || !lastP.equals(newP) || (newP instanceof CoordNode && !(lastP instanceof CoordNode))) { newPoints.add(newP); lastP = newP; } else if(newP.preserved()) { // this point is not going to be used because it // has the same (rounded) coordinates as the last // node but it has been marked as being "preserved" - // transfer that property to the previous point so // that it's not lost lastP.preserved(true); } } if(newPoints.size() > 1) { MapLine newLine = line.copy(); newLine.setPoints(newPoints); next.doFilter(newLine); } } } }