/* * 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. * * * Author: Steve Ratcliffe * Create date: Dec 2, 2007 */ package uk.me.parabola.mkgmap.filters; import uk.me.parabola.mkgmap.general.MapElement; import uk.me.parabola.mkgmap.general.MapShape; import java.util.ArrayList; import java.util.List; /** * Split polygons so that they have less than the maximum number of points. * This is handled by using java built in classes. Basically I am just taking * the bounding box, splitting that in half and getting the intersection of * each half-box with the original shape. Recurse until all are small enough. * * <p>Cutting things up may make discontiguous shapes, but this is handled by * the java classes (for sure) and my code (probably). * * <p>Written assuming that this is not very common, once we start doing sea * areas, may want to re-examine to see if we can optimize. * * @author Steve Ratcliffe */ public class PolygonSplitterFilter extends PolygonSplitterBase implements MapFilter { public static final int MAX_POINT_IN_ELEMENT = 250; /** * Split up polygons that have more than the max allowed number of points. * Initially I shall just throw out polygons that have too many points * to see if this is causing particular problems. * * @param element A map element, only polygons will be processed. * @param next This is used to pass the possibly transformed element onward. */ public void doFilter(MapElement element, MapFilterChain next) { assert element instanceof MapShape; MapShape shape = (MapShape) element; int n = shape.getPoints().size(); if (n < MAX_POINT_IN_ELEMENT) { // This is ok let it through and return. next.doFilter(element); return; } List<MapShape> outputs = new ArrayList<MapShape>(); // Do an initial split split(shape, outputs); // Now check that all the resulting parts are also small enough. // NOTE: the end condition is changed from within the loop. for (int i = 0; i < outputs.size(); i++) { MapShape s = outputs.get(i); if (s.getPoints().size() > MAX_POINT_IN_ELEMENT) { // Not small enough, so remove it and split it again. The resulting // pieces will be placed at the end of the list and will be // picked up later on. outputs.set(i, null); split(s, outputs); } } // Now add all to the chain. for (MapShape s : outputs) { if (s == null) continue; next.doFilter(s); } } }