Rev 3081 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2012.
*
* 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.List;
import uk.me.parabola.imgfmt.Utils;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.MapElement;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.mkgmap.general.MapShape;
/**
* Filter for lines and shapes. Remove obsolete points on straight lines and spikes.
* @author GerdP
*
*/
public class RemoveObsoletePointsFilter
implements MapFilter
{
private static final Logger log =
Logger.
getLogger(RemoveObsoletePointsFilter.
class);
final Coord
[] areaTest =
new Coord
[3];
private boolean checkPreserved
;
public void init
(FilterConfig config
) {
checkPreserved = config.
getLevel() ==
0 && config.
isRoutable();
}
/**
* @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
;
List<Coord
> points = line.
getPoints();
int numPoints = points.
size();
if (numPoints
<=
1){
return;
}
int requiredPoints =
(line
instanceof MapShape
) ? 4:
2;
List<Coord
> newPoints =
new ArrayList<Coord
>(numPoints
);
while (true){
boolean removedSpike =
false;
numPoints = points.
size();
Coord lastP = points.
get(0);
newPoints.
add(lastP
);
for(int i =
1; i
< numPoints
; i++
) {
Coord newP = points.
get(i
);
int last = newPoints.
size()-
1;
lastP = newPoints.
get(last
);
if (lastP.
equals(newP
)){
// only add the new point if it has different
// coordinates to the last point or is preserved
if (checkPreserved
&& line.
isRoad()){
if (newP.
preserved() ==
false)
continue;
else if (lastP.
preserved() ==
false){
newPoints.
set(last, newP
); // replace last
}
} else
continue;
}
if (newPoints.
size() > 1) {
switch (Utils.
isStraight(newPoints.
get(last-
1), lastP, newP
)){
case Utils.
STRICTLY_STRAIGHT:
if (checkPreserved
&& lastP.
preserved() && line.
isRoad()){
// keep it
} else {
log.
debug("found three consecutive points on strictly straight line");
newPoints.
set(last, newP
);
continue;
}
break;
case Utils.
STRAIGHT_SPIKE:
if (line
instanceof MapShape
){
log.
debug("removing spike");
newPoints.
remove(last
);
removedSpike =
true;
if (newPoints.
get(last-
1).
equals(newP
))
continue;
}
break;
default:
break;
}
}
newPoints.
add(newP
);
}
if (!removedSpike || newPoints.
size() < requiredPoints
)
break;
points = newPoints
;
newPoints =
new ArrayList<Coord
>(points.
size());
}
if (line
instanceof MapShape
&& newPoints.
size() > 3){
// check special case: shape starts with spike
if (Utils.
isStraight(newPoints.
get(0), newPoints.
get(1), newPoints.
get(newPoints.
size()-
2)) == Utils.
STRICTLY_STRAIGHT){
newPoints.
remove(0);
newPoints.
set(newPoints.
size()-
1, newPoints.
get(0));
if (newPoints.
get(newPoints.
size()-
2).
equals(newPoints.
get(newPoints.
size()-
1)))
newPoints.
remove(newPoints.
size()-
1);
}
}
if (newPoints.
size() != line.
getPoints().
size()){
if (line
instanceof MapShape
&& newPoints.
size() <=
3 || newPoints.
size() <=
1)
return;
MapLine newLine = line.
copy();
newLine.
setPoints(newPoints
);
next.
doFilter(newLine
);
} else {
// no need to create new object
next.
doFilter(line
);
}
}
}