Weltkarte Wald: Outline-Fill-Mismatch durch Chaikin-Schrumpfen behoben
Chaikin corner-cutting bewegt Punkte nach innen → Outline lag kleiner als die Fill-Fläche. Die Wald-Density-Boundary ist bereits glatt (Summe kreisförmiger Kernels), braucht kein Smoothing. - assembleClosedPaths(segs, chaikinIter) extrahiert aus buildSeaCoastPaths: chaikinIter=0 → Pfade ohne Glättung, liegen exakt auf der Fill-Grenze - buildForestOutlinePaths nutzt assembleClosedPaths(..., 0) - buildSeaCoastPaths delegiert weiterhin mit chaikinIter=3 (Küste braucht Glättung wegen der stepped Terrain-Height-Boundary) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1006,6 +1006,14 @@ public class WorldMapView extends VBox {
|
||||
|
||||
// Verbindet Rohsegmente zu geschlossenen Küstenpfaden.
|
||||
private static List<float[][]> buildSeaCoastPaths(float[][] segs) {
|
||||
return assembleClosedPaths(segs, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbindet Rohsegmente zu geschlossenen Pfaden.
|
||||
* chaikinIter=0 → kein Smoothing (für bereits glatte Boundaries wie Wald-Density).
|
||||
*/
|
||||
private static List<float[][]> assembleClosedPaths(float[][] segs, int chaikinIter) {
|
||||
if (segs == null || segs.length == 0) { return Collections.emptyList(); }
|
||||
|
||||
Map<Long, List<Integer>> adj = new HashMap<>(segs.length * 4);
|
||||
@@ -1031,7 +1039,8 @@ public class WorldMapView extends VBox {
|
||||
float[][] raw = new float[bwd.size() + fwd.size()][];
|
||||
for (int i = 0; i < bwd.size(); i++) { raw[i] = bwd.get(bwd.size() - 1 - i); }
|
||||
for (int i = 0; i < fwd.size(); i++) { raw[bwd.size() + i] = fwd.get(i); }
|
||||
result.add(chaikin(simplifyCoastPath(raw), 3));
|
||||
float[][] path = simplifyCoastPath(raw);
|
||||
result.add(chaikinIter > 0 ? chaikin(path, chaikinIter) : path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1138,9 +1147,11 @@ public class WorldMapView extends VBox {
|
||||
}
|
||||
List<float[]> segs = new ArrayList<>();
|
||||
marchingSquares(mask, SIZE, 0.5f, null, null, segs);
|
||||
List<float[][]> paths = buildSeaCoastPaths(segs.toArray(new float[0][]));
|
||||
// chaikinIter=0: Density-Boundary ist bereits glatt (kreisförmige Kernels),
|
||||
// kein Chaikin-Schrumpfen → Outline liegt exakt auf der Fill-Grenze.
|
||||
List<float[][]> paths = assembleClosedPaths(segs.toArray(new float[0][]), 0);
|
||||
|
||||
// Kleinstpolygone filtern: weniger als ~100m Umfang = Artefakt (z.B. 2 isolierte Bäume)
|
||||
// Kleinstpolygone filtern: weniger als ~60m Umfang = Artefakt (z.B. isolierte Bäume)
|
||||
final float MIN_PERIMETER_SQ = 60f * 60f;
|
||||
return paths.stream().filter(p -> pathPerimeterSq(p) >= MIN_PERIMETER_SQ)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
Reference in New Issue
Block a user