/*
* 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);
}
}