Subversion Repositories mkgmap

Rev

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

/*
 * Copyright (C) 2014.
 *
 * 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.filters;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.mkgmap.general.MapShape;
//import uk.me.parabola.util.GpxCreator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;


public class ShapeMergeFilterTest {
        // create one Coord instance for each point in a small test grid
        private static final HashMap<Integer, Coord> map = new HashMap<>();
        static {
                for (int latHp = 0; latHp < 100; latHp += 5) {
                        for (int lonHp = 0; lonHp < 100; lonHp += 5) {
                                Coord co = Coord.makeHighPrecCoord(latHp, lonHp);
                                map.put(latHp * 1000 + lonHp, co);
                        }
                }

        }

        @Test
        public void testAreaTestVal(){
                List<Coord> points = Arrays.asList(
                                getPoint(10,10),
                                getPoint(30,10),
                                getPoint(30,30),
                                getPoint(10,30),
                                getPoint(10,10)); // close
               
                assertEquals(2L * (20 * 20), ShapeMergeFilter.calcAreaSizeTestVal(points));
        }      
        /**
         * two simple shapes, sharing one point
         */

        @Test
        public void testSimpleSharingOne(){
                List<Coord> points1 = Arrays.asList(
                                getPoint(15,10),
                                getPoint(30,25),
                                getPoint(25,30),
                                getPoint(10,30),
                                getPoint(5,20),
                                getPoint(15,10)); // close
               
                List<Coord> points2 = Arrays.asList(
                                getPoint(25,30),
                                getPoint(30,35),
                                getPoint(20,40),
                                getPoint(15,35),
                                getPoint(25,30)); // close
               
                testVariants("simple shapes sharing one point", points1, points2, 1, 10);
        }
       
        /**
         * two simple shapes, sharing one edge
         */

        @Test
        public void testSimpleNonOverlapping(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(15,10),
                        getPoint(30,25),
                        getPoint(25,30),
                        getPoint(15,35),
                        getPoint(5,20),
                        getPoint(15,10)); // close
               
                List<Coord> points2 = Arrays.asList(
                        getPoint(25,30),
                        getPoint(30,35),
                        getPoint(20,40),
                        getPoint(15,35),
                        getPoint(25,30)); // close
               
                testVariants("simple shapes", points1, points2, 1, 8);
        }

        /**
         * two simple shapes, sharing three consecutive points
         */


        @Test
        public void test3SharedPointsNonOverlapping(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(15,10),
                        getPoint(30,25),
                        getPoint(25,30),
                        getPoint(20,35),
                        getPoint(15,35),
                        getPoint(5,20),
                        getPoint(15,10));// close
               
                List<Coord> points2 = Arrays.asList(
                        getPoint(25,30),
                        getPoint(30,35),
                        getPoint(20,40),
                        getPoint(15,35),
                        getPoint(20,35),
                        getPoint(25,30));// close
               
                testVariants("test 3 consecutive shared points", points1, points2, 1, 8);
        }
       
        /**
         * two simple shapes, sharing three consecutive points
         */


        @Test
        public void test2SharedPointsNoEdge(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(15,10),
                        getPoint(30,25),
                        getPoint(25,30),
                        getPoint(15,35),
                        getPoint(5,20),
                        getPoint(15,10));// close
               
                List<Coord> points2 = Arrays.asList(
                        getPoint(25,30),
                        getPoint(30,35),
                        getPoint(20,40),
                        getPoint(15,35),
                        getPoint(20,35),
                        getPoint(25,30));// close
               
                testVariants("test 2 non-consecutive shared points", points1, points2, 1, 11);
        }
       
        /**
         * one u-formed shape, the other closes it to a rectangular shape with a hole
         * They are sharing 4 points.
         */


        @Test
        public void testCloseUFormed(){
                List<Coord> points1 = Arrays.asList(
                        // u-formed shaped (open at top)
                        getPoint(15,50),
                        getPoint(30,50),
                        getPoint(30,55),
                        getPoint(20,55),
                        getPoint(20,65),
                        getPoint(30,65),
                        getPoint(30,70),
                        getPoint(15,70),
                        getPoint(15,50));// close

                List<Coord> points2 = Arrays.asList(
                        getPoint(35,50),
                        getPoint(35,70),
                        getPoint(30,70),
                        getPoint(30,65),
                        getPoint(30,55),
                        getPoint(30,50),
                        getPoint(35,50)); // close
               
                testVariants("test close U formed shape", points1, points2, 1, 11);
        }
       
        /**
         * one u-formed shape, the fits into the u and shares all points
         */


        @Test
        public void testFillUFormed(){
                List<Coord> points1 = Arrays.asList(
                        // u-formed shaped (open at top)
                        getPoint(15,50),
                        getPoint(30,50),
                        getPoint(30,55),
                        getPoint(20,55),
                        getPoint(20,65),
                        getPoint(30,65),
                        getPoint(30,70),
                        getPoint(15,70),
                        getPoint(15,50)); // close
               
                List<Coord> points2 = Arrays.asList(
                        getPoint(30,55),
                        getPoint(30,65),
                        getPoint(20,65),
                        getPoint(20,55),
                        getPoint(30,55)); // close

                testVariants("test fill U-formed shape", points1, points2, 1, 5);
        }
       
        /**
         * one u-formed shape, the fits into the u and shares all points
         */


        @Test
        public void testFillHole(){
                List<Coord> points1 = Arrays.asList(
                        // a rectangle with a hole
                        getPoint(35,50),
                        getPoint(35,70),
                        getPoint(15,70),
                        getPoint(15,50),
                        getPoint(30,50),
                        getPoint(30,55),
                        getPoint(20,55),
                        getPoint(20,65),
                        getPoint(30,65),
                        getPoint(30,50),
                        getPoint(35,50));// close

                List<Coord> points2 = Arrays.asList(
                        getPoint(30,55),
                        getPoint(30,65),
                        getPoint(20,65),
                        getPoint(20,55),
                        getPoint(30,55)); // close

                testVariants("test-fill-hole", points1, points2, 1, 5); // expect 8 points if spike is not removed  
        }

        @Test
        public void testDuplicate(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(30,55),
                        getPoint(30,65),
                        getPoint(20,65),
                        getPoint(20,55),
                        getPoint(30,55)); // close

                List<Coord> points2 = new ArrayList<>(points1);
               
                testVariants("test duplicate", points1, points2, 1, 5);
        }

        @Test
        public void testOverlap(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(30,55),
                        getPoint(30,65),
                        getPoint(20,65),
                        getPoint(20,55),
                        getPoint(30,55)); // close

                List<Coord> points2 = Arrays.asList(
                        getPoint(30,55),
                        getPoint(30,65),
                        getPoint(25,65),
                        getPoint(25,55),
                        getPoint(30,55)); // close

                // no merge expected
                testVariants("test overlap", points1, points2, 2, 5);
        }

        /*
         * shapes are connected at multiple edges like two
         * w-formed shapes.
         */

        @Test
        public void testTwoWShaped(){
                List<Coord> points1 = Arrays.asList(
                        getPoint(0,5),
                        getPoint(35,5),
                        getPoint(35,20),
                        getPoint(30,15),
                        getPoint(25,20),
                        getPoint(25,10),
                        getPoint(15,10),
                        getPoint(15,20),
                        getPoint(10,15),
                        getPoint(5,20),
                        getPoint(0,20),
                        getPoint(0,5)); // close

                List<Coord> points2 = Arrays.asList(
                        getPoint(35,35),
                        getPoint(35,20),
                        getPoint(30,15),
                        getPoint(25,20),
                        getPoint(25,25),
                        getPoint(15,25),
                        getPoint(15,20),
                        getPoint(10,15),
                        getPoint(5,20),
                        getPoint(0,20),
                        getPoint(5,35),
                        getPoint(35,35)); // close
               
                // wanted: merge that removes at least the longer shared sequence
                testVariants("test two w-shaped", points1, points2, 1, 16);
        }

        /**
         * Test all variants regarding clockwise/ccw direction and positions of the points
         * in the list and the order of shapes.
         * @param list1
         * @param list2
         */

        void testVariants(String msg, List<Coord> list1, List<Coord> list2, int expectedNumShapes, int expectedNumPoints){
                MapShape s1 = new MapShape(1);
                MapShape s2 = new MapShape(2);
                s1.setMinResolution(22);
                s2.setMinResolution(22);
                for (int i = 0; i < 4; i++){
                        for (int j = 0; j < list1.size(); j++){
                                List<Coord> points1 = new ArrayList<>(list1);
                                if ((i & 1) != 0)
                                        Collections.reverse(points1);
                                points1.remove(points1.size()-1);
                                Collections.rotate(points1, j);
                                points1.add(points1.get(0));
                                s1.setPoints(points1);
                                for (int k = 0; k < list2.size(); k++){
                                        List<Coord> points2 = new ArrayList<>(list2);
                                        if ((i & 2) != 0)
                                                Collections.reverse(points2);
                                        points2.remove(points2.size()-1);
                                        Collections.rotate(points2, k);
                                        points2.add(points2.get(0));
                                        s2.setPoints(points2);
                                       
                                        for (int l = 0; l < 2; l++){
                                                String testId = msg+" i="+i+",j="+j+",k="+k+",l="+l;
                                                if (l == 0)
                                                        testOneVariant(testId, s1, s2, expectedNumShapes,expectedNumPoints);
                                                else
                                                        testOneVariant(testId, s2, s1, expectedNumShapes,expectedNumPoints);
                                        }
                                }
                        }
                }
        }
       
        void testOneVariant(String testId, MapShape s1, MapShape s2, int expectedNumShapes, int expectedNumPoints){
                ShapeMergeFilter smf = new ShapeMergeFilter(24, false);
                List<MapShape> res = smf.merge(Arrays.asList(s1,s2));
                assertTrue(testId, res != null);
                assertEquals(testId,expectedNumShapes, res.size() );
                assertEquals(testId, expectedNumPoints, res.get(0).getPoints().size());
                // TODO: test shape size
        }
        Coord getPoint(int lat, int lon){
                Coord co = map.get(lat*1000+lon);
                assert co != null;
                return co;
        }
       
        @Test
        public void testRepeatedWithDifferentId(){
                Coord copy = new Coord(getPoint(25,20));
                List<Coord> points1 = Arrays.asList(
                                getPoint(35,15),
                                getPoint(25,20),
                                copy,
                                getPoint(15,10),
                                getPoint(25,5),
                                getPoint(35,15)); // close
                       
                        List<Coord> points2 = Arrays.asList(
                                        getPoint(30,20),
                                        getPoint(25,25),
                                        getPoint(20,20),
                                        copy,
                                        new Coord(copy),
                                        getPoint(25,20),
                                        getPoint(30,20)); // close
                       
                testVariants("test-repeated-different", points1, points2, 1, 9);  
        }

}