Rev 3314 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
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.log.Logger;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.util.MultiHashMap;
public class LineMergeFilter
{
private static final Logger log =
Logger.
getLogger(LineMergeFilter.
class);
private List<MapLine
> linesMerged
;
private final MultiHashMap
<Coord, MapLine
> startPoints =
new MultiHashMap
<Coord, MapLine
>();
private final MultiHashMap
<Coord, MapLine
> endPoints =
new MultiHashMap
<Coord, MapLine
>();
private void addLine
(MapLine line
) {
linesMerged.
add(line
);
List<Coord
> points = line.
getPoints();
startPoints.
add(points.
get(0), line
);
endPoints.
add(points.
get(points.
size()-
1), line
);
}
private void mergeLines
(MapLine line1, MapLine line2
) {
// Removes the first line,
// Merges the points in the second one
List<Coord
> points1 = line1.
getPoints();
List<Coord
> points2 = line2.
getPoints();
startPoints.
removeMapping(points1.
get(0), line1
);
endPoints.
removeMapping(points1.
get(points1.
size() -
1), line1
);
startPoints.
removeMapping(points2.
get(0), line2
);
startPoints.
add(points1.
get(0), line2
);
line2.
insertPointsAtStart(points1
);
linesMerged.
remove(line1
);
}
private void addPointsAtStart
(MapLine line,
List<Coord
> additionalPoints
) {
log.
info("merged lines before " + line.
getName());
List<Coord
> points = line.
getPoints();
startPoints.
removeMapping(points.
get(0), line
);
line.
insertPointsAtStart(additionalPoints
);
startPoints.
add(points.
get(0), line
);
}
private void addPointsAtEnd
(MapLine line,
List<Coord
> additionalPoints
) {
log.
info("merged lines after " + line.
getName());
List<Coord
> points = line.
getPoints();
endPoints.
removeMapping(points.
get(points.
size() -
1), line
);
line.
insertPointsAtEnd(additionalPoints
);
endPoints.
add(points.
get(points.
size()-
1), line
);
}
//TODO: This routine has a side effect: it modifies some of the MapLine instances
// instead of creating copies. It seems that this has no bad effect, but it is not clean
public List<MapLine
> merge
(List<MapLine
> lines,
int res
) {
linesMerged =
new ArrayList<MapLine
>(lines.
size()); //better use LinkedList??
for (MapLine line : lines
) {
if (line.
getMinResolution() > res || line.
getMaxResolution() < res
)
continue;
if (line.
isRoad()){
linesMerged.
add(line
);
continue;
}
boolean isMerged =
false;
List<Coord
> points = line.
getPoints();
Coord start = points.
get(0);
Coord end = points.
get(points.
size()-
1);
// Search for start point in hashlist
// (can the end of current line connected to an existing line?)
for (MapLine line2 : startPoints.
get(end
)) {
if (line.
isSimilar(line2
)) {
addPointsAtStart
(line2, points
);
// Search for endpoint in hashlist
// (if the other end (=start of line =start of line2) could be connected to an existing line,
// both lines has to be merged and one of them dropped)
for (MapLine line1 : endPoints.
get(start
)) {
if (line2.
isSimilar(line1
)
&& !line2.
equals(line1
)) // don't make a closed loop a double loop
{
mergeLines
(line1, line2
);
break;
}
}
isMerged =
true;
break;
}
}
if (isMerged
)
continue;
// Search for endpoint in hashlist
// (can the start of current line connected to an existing line?)
for (MapLine line2 : endPoints.
get(start
)) {
if (line.
isSimilar(line2
)) {
addPointsAtEnd
(line2, points
);
isMerged =
true;
break;
}
}
if (isMerged
)
continue;
// No matching, create a copy of line
MapLine l = line.
copy();
List<Coord
> p =
new ArrayList<Coord
>(line.
getPoints()); //use better LinkedList for performance?
l.
setPoints(p
);
addLine
(l
);
}
return linesMerged
;
}
}