mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Delete the dead v1 hydrology settings surface
- Surface inset, terrain blend and ridge tunnel settings gone; Hydraulics keeps only waterfallMinimumDrop - Branching folded into Routing; refinementSpacing derived from the sample lattice - Contained surface routing branch, surface incision helpers and 13 unreachable compiler members deleted
This commit is contained in:
@@ -8,13 +8,11 @@ public enum HydrologyCandidateRejection {
|
||||
SOURCE_QUOTA,
|
||||
SOURCE_SPACING,
|
||||
OUTLET_LIMIT,
|
||||
RIDGE_CONTAINMENT,
|
||||
OUTLET_LEVEL,
|
||||
CAVE_CONTAINMENT,
|
||||
VOLUME_LIMIT,
|
||||
SURFACE_HEAD_RANGE,
|
||||
SURFACE_HEAD_DISTRIBUTION,
|
||||
SURFACE_RIDGE_TUNNEL_LIMIT,
|
||||
SURFACE_EXPOSURE,
|
||||
SURFACE_DROP_UNSUPPORTED,
|
||||
SURFACE_CORRIDOR_UNSUPPORTED,
|
||||
|
||||
@@ -5,6 +5,8 @@ public enum HydrologyFeatureType {
|
||||
RIFFLE,
|
||||
CASCADE,
|
||||
WATERFALL,
|
||||
// No planner produces a ridge bore any more. The constant stays because its ordinal seeds the
|
||||
// segment, outlet and feature ids of every constant after it on the cave and deep-fluid paths.
|
||||
RIDGE_BORE,
|
||||
UNDERGROUND_POOL,
|
||||
UNDERGROUND_DROP,
|
||||
|
||||
+7
-418
@@ -12,19 +12,15 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
final class HydrologyFootprintCompiler {
|
||||
private static final int FEATURE_ROLE_COUNT = 7;
|
||||
private static final int COURSE_FOOTPRINT_CACHE_SIZE = 8;
|
||||
private static final int VALIDATION_RASTER_CACHE_SIZE = 8;
|
||||
private static final int MINIMUM_ENDPOINT_PROFILE_LENGTH = 48;
|
||||
private static final double MINIMUM_ENDPOINT_RAMP_WIDTHS = 2D;
|
||||
private static final int[][] HORIZONTAL_NEIGHBORS = {
|
||||
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
|
||||
};
|
||||
@@ -53,7 +49,7 @@ final class HydrologyFootprintCompiler {
|
||||
HydrologyPlannerSettings settings,
|
||||
HydrologyTerrainSampler sampler
|
||||
) {
|
||||
this(settings, sampler, HydrologyGeometrySampler.deterministic(0L, sampler));
|
||||
this(settings, sampler, HydrologyGeometrySampler.deterministic(sampler));
|
||||
}
|
||||
|
||||
HydrologyFootprintCompiler(
|
||||
@@ -172,404 +168,6 @@ final class HydrologyFootprintCompiler {
|
||||
return fullMaterializationCount;
|
||||
}
|
||||
|
||||
boolean surfaceHeadwaterRampSupported(RiverCourse course) {
|
||||
Objects.requireNonNull(course, "course");
|
||||
if (course.type() != RiverCourseType.SURFACE) {
|
||||
return true;
|
||||
}
|
||||
if (settings.routing().branching().minimumSurfaceCourseLength()
|
||||
< MINIMUM_ENDPOINT_PROFILE_LENGTH) {
|
||||
return true;
|
||||
}
|
||||
RiverFootprint footprint = compileCourse(course);
|
||||
List<HydrologyPoint> raster = surfaceCourseCenterline(course);
|
||||
if (raster.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
HashSet<Long> ownedCells = new HashSet<>();
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
if (fluid != null
|
||||
&& fluid.feature().courseId() == course.id()
|
||||
&& fluid.feature().type().isSurface()
|
||||
&& fluid.channel()
|
||||
&& fluid.connectedFluid()
|
||||
&& fluid.fluidOwned()
|
||||
&& !fluid.oceanApron()) {
|
||||
ownedCells.add(RiverFootprint.pack(sample.x(), sample.z()));
|
||||
}
|
||||
}
|
||||
int maximumWidth = 1;
|
||||
for (HydraulicSegment segment : course.segments()) {
|
||||
if (segment.type().isSurface()) {
|
||||
maximumWidth = Math.max(maximumWidth, segment.width());
|
||||
}
|
||||
}
|
||||
HydrologyPoint source = raster.getFirst();
|
||||
if (!ownedNear(ownedCells, source.x(), source.z(), maximumWidth)) {
|
||||
return false;
|
||||
}
|
||||
int cruiseWidth = cruiseWidth(ownedCells, raster, maximumWidth);
|
||||
double transitionLength = endpointTransitionLength(
|
||||
ownedCells,
|
||||
raster,
|
||||
maximumWidth,
|
||||
cruiseWidth
|
||||
);
|
||||
return transitionLength >= cruiseWidth * MINIMUM_ENDPOINT_RAMP_WIDTHS;
|
||||
}
|
||||
|
||||
boolean surfaceIncisionContained(RiverCourse course) {
|
||||
Objects.requireNonNull(course, "course");
|
||||
if (course.type() != RiverCourseType.SURFACE) {
|
||||
return true;
|
||||
}
|
||||
RiverFootprint footprint = compileCourse(course);
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
if (fluid == null
|
||||
|| fluid.feature().courseId() != course.id()
|
||||
|| fluid.feature().type() == HydrologyFeatureType.MOUTH
|
||||
|| fluid.oceanApron()
|
||||
|| fluid.fallingFluid()
|
||||
|| !fluid.channel()
|
||||
|| !fluid.fluidOwned()) {
|
||||
continue;
|
||||
}
|
||||
HydrologyTerrainSample basis = sampleTerrainBasis(sample.x(), sample.z());
|
||||
HydrologyTerrainSample terrain = sampleTerrain(sample.x(), sample.z());
|
||||
if (terrain == null
|
||||
|| basis == null
|
||||
|| (terrain.naturalHeight() - fluid.fluidHeadY() > permittedSurfaceIncision(terrain)
|
||||
&& basis.naturalHeight() - fluid.fluidHeadY() <= permittedSurfaceIncision(basis))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean surfaceIncisionContained(RiverCourse course, RiverFootprint footprint) {
|
||||
Objects.requireNonNull(course, "course");
|
||||
Objects.requireNonNull(footprint, "footprint");
|
||||
if (course.type() != RiverCourseType.SURFACE) {
|
||||
return true;
|
||||
}
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
for (HydrologyColumnLayer fluid : sample.layers()) {
|
||||
if (fluid.feature().courseId() != course.id()
|
||||
|| fluid.feature().type() == HydrologyFeatureType.MOUTH
|
||||
|| fluid.oceanApron()
|
||||
|| fluid.fallingFluid()
|
||||
|| !fluid.channel()
|
||||
|| !fluid.fluidOwned()) {
|
||||
continue;
|
||||
}
|
||||
HydrologyTerrainSample basis = sampleTerrainBasis(sample.x(), sample.z());
|
||||
HydrologyTerrainSample terrain = sampleTerrain(sample.x(), sample.z());
|
||||
if (basis == null
|
||||
|| terrain == null
|
||||
|| (terrain.naturalHeight() - fluid.fluidHeadY()
|
||||
> settings.surface().maximumIncision()
|
||||
&& basis.naturalHeight() - fluid.fluidHeadY()
|
||||
<= permittedSurfaceIncision(basis))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean surfaceBanksContained(RiverCourse course) {
|
||||
Objects.requireNonNull(course, "course");
|
||||
if (course.type() != RiverCourseType.SURFACE) {
|
||||
return true;
|
||||
}
|
||||
RiverFootprint footprint = compileCourse(course);
|
||||
if (!surfaceCenterlinePublished(course, footprint)
|
||||
|| !surfaceTransitionCenterlinePublished(course, footprint)) {
|
||||
return false;
|
||||
}
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
if (fluid == null || fluid.oceanApron() || fluid.fallingFluid()) {
|
||||
continue;
|
||||
}
|
||||
for (int[] offset : HORIZONTAL_NEIGHBORS) {
|
||||
HydrologyColumnSample neighbor = footprint.sample(
|
||||
sample.x() + offset[0],
|
||||
sample.z() + offset[1]
|
||||
).orElse(null);
|
||||
if (ownsSurfaceFluid(neighbor, course.id())) {
|
||||
continue;
|
||||
}
|
||||
if (neighbor != null
|
||||
&& fluid.fluidHeadY() <= neighbor.seaLevel()
|
||||
&& (neighbor.ocean() || neighbor.naturalHeight() <= neighbor.seaLevel())) {
|
||||
continue;
|
||||
}
|
||||
if (neighbor == null || neighbor.terrainHeight() <= fluid.fluidHeadY()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean surfaceCenterlinePublished(RiverCourse course, RiverFootprint footprint) {
|
||||
for (HydraulicSegment segment : course.segments()) {
|
||||
if (!segment.type().isSurface()) {
|
||||
continue;
|
||||
}
|
||||
for (HydrologyPoint point : segment.centerline()) {
|
||||
HydrologyColumnSample sample = footprint.sample(point.x(), point.z()).orElse(null);
|
||||
if (ownsSurfaceFluid(sample, course.id())
|
||||
|| segment.type() == HydrologyFeatureType.MOUTH
|
||||
&& ownsOceanApron(sample, course.id())) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean surfaceTransitionCenterlinePublished(RiverCourse course, RiverFootprint footprint) {
|
||||
for (int segmentIndex = 0; segmentIndex < course.segments().size(); segmentIndex++) {
|
||||
HydraulicSegment segment = course.segments().get(segmentIndex);
|
||||
if (!terrainRoofedSurfaceTransition(course, segment)) {
|
||||
continue;
|
||||
}
|
||||
List<HydrologyPoint> centerline = continuousCenterline(segment);
|
||||
for (int pointIndex = 0; pointIndex < centerline.size(); pointIndex++) {
|
||||
HydrologyPoint point = centerline.get(pointIndex);
|
||||
HydrologyColumnSample sample = footprint.sample(point.x(), point.z()).orElse(null);
|
||||
if (ownsTransitionFluid(sample, course.id(), segment.id(), point.y())) {
|
||||
continue;
|
||||
}
|
||||
boolean joinedStart = pointIndex == 0
|
||||
&& segmentIndex > 0
|
||||
&& segmentsJoin(course.segments().get(segmentIndex - 1), segment);
|
||||
boolean joinedEnd = pointIndex == centerline.size() - 1
|
||||
&& segmentIndex + 1 < course.segments().size()
|
||||
&& segmentsJoin(segment, course.segments().get(segmentIndex + 1));
|
||||
if ((joinedStart || joinedEnd) && ownsCourseFluid(sample, course.id(), point.y())) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean ownsTransitionFluid(
|
||||
HydrologyColumnSample sample,
|
||||
long courseId,
|
||||
long segmentId,
|
||||
int fluidHead
|
||||
) {
|
||||
if (sample == null) {
|
||||
return false;
|
||||
}
|
||||
for (HydrologyColumnLayer layer : sample.layers()) {
|
||||
if (layer.feature().courseId() == courseId
|
||||
&& layer.feature().segmentId() == segmentId
|
||||
&& layer.fluidHeadY() == fluidHead
|
||||
&& layer.channel()
|
||||
&& layer.connectedFluid()
|
||||
&& layer.fluidOwned()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean ownsCourseFluid(HydrologyColumnSample sample, long courseId, int fluidHead) {
|
||||
if (sample == null) {
|
||||
return false;
|
||||
}
|
||||
for (HydrologyColumnLayer layer : sample.layers()) {
|
||||
if (layer.feature().courseId() == courseId
|
||||
&& layer.fluidHeadY() == fluidHead
|
||||
&& layer.channel()
|
||||
&& layer.connectedFluid()
|
||||
&& layer.fluidOwned()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int permittedSurfaceIncision(HydrologyTerrainSample terrain) {
|
||||
int maximumIncision = settings.surface().maximumIncision();
|
||||
return Math.min(
|
||||
maximumIncision,
|
||||
(int) StrictMath.floor(maximumIncision * terrain.incisionMultiplier())
|
||||
);
|
||||
}
|
||||
|
||||
private boolean ownsSurfaceFluid(HydrologyColumnSample sample, long courseId) {
|
||||
if (sample == null) {
|
||||
return false;
|
||||
}
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
return fluid != null
|
||||
&& fluid.fluidOwned()
|
||||
&& fluid.feature().courseId() == courseId;
|
||||
}
|
||||
|
||||
private boolean ownsOceanApron(HydrologyColumnSample sample, long courseId) {
|
||||
if (sample == null) {
|
||||
return false;
|
||||
}
|
||||
for (HydrologyColumnLayer layer : sample.layers()) {
|
||||
if (layer.oceanApron() && layer.feature().courseId() == courseId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<HydrologyPoint> surfaceCourseCenterline(RiverCourse course) {
|
||||
ArrayList<HydrologyPoint> points = new ArrayList<>();
|
||||
for (HydraulicSegment segment : course.segments()) {
|
||||
if (!segment.type().isSurface() && segment.type() != HydrologyFeatureType.RIDGE_BORE) {
|
||||
break;
|
||||
}
|
||||
for (HydrologyPoint point : segment.centerline()) {
|
||||
if (points.isEmpty()
|
||||
|| point.x() != points.getLast().x()
|
||||
|| point.z() != points.getLast().z()) {
|
||||
points.add(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rasterCenterline(points);
|
||||
}
|
||||
|
||||
private List<HydrologyPoint> rasterCenterline(List<HydrologyPoint> points) {
|
||||
ArrayList<HydrologyPoint> raster = new ArrayList<>();
|
||||
for (int pairIndex = 0; pairIndex < points.size() - 1; pairIndex++) {
|
||||
HydrologyPoint start = points.get(pairIndex);
|
||||
HydrologyPoint end = points.get(pairIndex + 1);
|
||||
int steps = Math.max(Math.abs(end.x() - start.x()), Math.abs(end.z() - start.z()));
|
||||
if (steps == 0) {
|
||||
continue;
|
||||
}
|
||||
int firstStep = raster.isEmpty() ? 0 : 1;
|
||||
for (int step = firstStep; step <= steps; step++) {
|
||||
double progress = step / (double) steps;
|
||||
raster.add(new HydrologyPoint(
|
||||
(int) StrictMath.round(start.x() + (end.x() - start.x()) * progress),
|
||||
(int) StrictMath.round(start.y() + (end.y() - start.y()) * progress),
|
||||
(int) StrictMath.round(start.z() + (end.z() - start.z()) * progress)
|
||||
));
|
||||
}
|
||||
}
|
||||
return List.copyOf(raster);
|
||||
}
|
||||
|
||||
private boolean ownedNear(Set<Long> cells, int x, int z, int radius) {
|
||||
for (int deltaZ = -radius; deltaZ <= radius; deltaZ++) {
|
||||
for (int deltaX = -radius; deltaX <= radius; deltaX++) {
|
||||
if (cells.contains(RiverFootprint.pack(x + deltaX, z + deltaZ))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int cruiseWidth(Set<Long> cells, List<HydrologyPoint> raster, int maximumWidth) {
|
||||
int start = Math.min(raster.size() - 2, Math.max(48, maximumWidth * 4));
|
||||
int end = Math.min(raster.size() - 1, Math.max(start + 16, maximumWidth * 6));
|
||||
ArrayList<Integer> widths = new ArrayList<>();
|
||||
for (int offset = start; offset <= end; offset++) {
|
||||
if (offset <= 0 || offset >= raster.size() - 1) {
|
||||
continue;
|
||||
}
|
||||
int width = crossSectionWidth(
|
||||
cells,
|
||||
raster.get(offset),
|
||||
raster.get(offset - 1),
|
||||
raster.get(offset + 1),
|
||||
maximumWidth
|
||||
);
|
||||
if (width > 0) {
|
||||
widths.add(width);
|
||||
}
|
||||
}
|
||||
if (widths.isEmpty()) {
|
||||
return maximumWidth;
|
||||
}
|
||||
widths.sort(Integer::compare);
|
||||
return Math.max(1, widths.get(widths.size() / 2));
|
||||
}
|
||||
|
||||
private double endpointTransitionLength(
|
||||
Set<Long> cells,
|
||||
List<HydrologyPoint> raster,
|
||||
int maximumWidth,
|
||||
int cruiseWidth
|
||||
) {
|
||||
int endpointWidth = crossSectionWidth(
|
||||
cells,
|
||||
raster.getFirst(),
|
||||
raster.getFirst(),
|
||||
raster.get(1),
|
||||
maximumWidth
|
||||
);
|
||||
int widthTolerance = Math.max(1, (int) StrictMath.ceil(cruiseWidth * 0.1D));
|
||||
if (Math.abs(endpointWidth - cruiseWidth) <= widthTolerance) {
|
||||
return 0D;
|
||||
}
|
||||
int search = Math.max(32, cruiseWidth * 6);
|
||||
double distance = 0D;
|
||||
int pointIndex = 1;
|
||||
while (pointIndex < raster.size() && distance <= search) {
|
||||
int previousIndex = pointIndex - 1;
|
||||
int nextIndex = Math.min(raster.size() - 1, pointIndex + 1);
|
||||
HydrologyPoint previous = raster.get(previousIndex);
|
||||
HydrologyPoint station = raster.get(pointIndex);
|
||||
HydrologyPoint next = raster.get(nextIndex);
|
||||
distance += StrictMath.hypot(station.x() - previous.x(), station.z() - previous.z());
|
||||
int width = crossSectionWidth(cells, station, previous, next, maximumWidth);
|
||||
if (Math.abs(width - cruiseWidth) <= widthTolerance) {
|
||||
return distance;
|
||||
}
|
||||
pointIndex++;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
private int crossSectionWidth(
|
||||
Set<Long> cells,
|
||||
HydrologyPoint center,
|
||||
HydrologyPoint before,
|
||||
HydrologyPoint after,
|
||||
int maximumWidth
|
||||
) {
|
||||
double tangentX = after.x() - before.x();
|
||||
double tangentZ = after.z() - before.z();
|
||||
double tangentLength = StrictMath.hypot(tangentX, tangentZ);
|
||||
if (tangentLength == 0D) {
|
||||
tangentX = 1D;
|
||||
tangentLength = 1D;
|
||||
}
|
||||
double perpendicularX = -tangentZ / tangentLength;
|
||||
double perpendicularZ = tangentX / tangentLength;
|
||||
int limit = Math.max(4, maximumWidth * 2);
|
||||
HashSet<Long> sampled = new HashSet<>();
|
||||
for (int offset = -limit; offset <= limit; offset++) {
|
||||
int x = (int) StrictMath.round(center.x() + perpendicularX * offset);
|
||||
int z = (int) StrictMath.round(center.z() + perpendicularZ * offset);
|
||||
long packed = RiverFootprint.pack(x, z);
|
||||
if (cells.contains(packed)) {
|
||||
sampled.add(packed);
|
||||
}
|
||||
}
|
||||
return sampled.size();
|
||||
}
|
||||
|
||||
private ValidationCourseRaster compileValidationCourse(RiverCourse course) {
|
||||
CourseRasterKey rasterKey = new CourseRasterKey(
|
||||
course.id(),
|
||||
@@ -825,7 +423,6 @@ final class HydrologyFootprintCompiler {
|
||||
return false;
|
||||
}
|
||||
return segment.type().isSurface()
|
||||
|| segment.type() == HydrologyFeatureType.RIDGE_BORE
|
||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_POOL
|
||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP
|
||||
|| segment.type() == HydrologyFeatureType.SINKHOLE
|
||||
@@ -1145,21 +742,15 @@ final class HydrologyFootprintCompiler {
|
||||
point.x(),
|
||||
point.z(),
|
||||
segment.id(),
|
||||
settings.surface().minimumTerrainBlendWidth(),
|
||||
settings.surface().maximumTerrainBlendWidth()
|
||||
settings.surface().banks().minimumBlendWidth(),
|
||||
settings.surface().banks().maximumBlendWidth()
|
||||
);
|
||||
if (type == HydrologyFeatureType.WATERFALL) {
|
||||
shoreWidth = Math.min(2.5D, shoreWidth);
|
||||
gradingWidth = Math.min(gradingWidth, Math.max(8D, channelRadius * 4D));
|
||||
}
|
||||
}
|
||||
if (type == HydrologyFeatureType.RIDGE_BORE
|
||||
|| course.type() == RiverCourseType.SURFACE
|
||||
&& type == HydrologyFeatureType.UNDERGROUND_DROP) {
|
||||
ceiling = fluidHead + settings.surface().ridgeTunnelHeadroom();
|
||||
archedChannel = !falling;
|
||||
organicBoundary = true;
|
||||
} else if (type == HydrologyFeatureType.UNDERGROUND_POOL
|
||||
if (type == HydrologyFeatureType.UNDERGROUND_POOL
|
||||
|| type == HydrologyFeatureType.UNDERGROUND_DROP
|
||||
|| type == HydrologyFeatureType.SINKHOLE) {
|
||||
ceiling = fluidHead + geometrySampler.sample(
|
||||
@@ -1213,7 +804,7 @@ final class HydrologyFootprintCompiler {
|
||||
if (course.type() == RiverCourseType.SURFACE && type.isSurface()) {
|
||||
gradingWidth = Math.max(
|
||||
gradingWidth,
|
||||
Math.min(settings.surface().maximumTerrainBlendWidth(), channelRadius * 2D)
|
||||
Math.min(settings.surface().banks().maximumBlendWidth(), channelRadius * 2D)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1807,8 +1398,7 @@ final class HydrologyFootprintCompiler {
|
||||
|
||||
private boolean terrainRoofedSurfaceTransition(RiverCourse course, HydraulicSegment segment) {
|
||||
return course.type() == RiverCourseType.SURFACE
|
||||
&& (segment.type() == HydrologyFeatureType.RIDGE_BORE
|
||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_POOL
|
||||
&& (segment.type() == HydrologyFeatureType.UNDERGROUND_POOL
|
||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP);
|
||||
}
|
||||
|
||||
@@ -1943,8 +1533,7 @@ final class HydrologyFootprintCompiler {
|
||||
}
|
||||
|
||||
private HydrologyPlannerSettings.ChannelShape channelShape(HydrologyFeatureType type) {
|
||||
if (type.isGrotto() || type == HydrologyFeatureType.DEEP_POOL
|
||||
|| type == HydrologyFeatureType.RIDGE_BORE) {
|
||||
if (type.isGrotto() || type == HydrologyFeatureType.DEEP_POOL) {
|
||||
return settings.geometry().grottos();
|
||||
}
|
||||
if (type.isUnderground() || type == HydrologyFeatureType.DEEP_CHANNEL) {
|
||||
|
||||
@@ -37,10 +37,7 @@ public interface HydrologyGeometrySampler {
|
||||
return value;
|
||||
}
|
||||
|
||||
static HydrologyGeometrySampler deterministic(
|
||||
long worldSeed,
|
||||
HydrologyTerrainSampler terrainSampler
|
||||
) {
|
||||
static HydrologyGeometrySampler deterministic(HydrologyTerrainSampler terrainSampler) {
|
||||
Objects.requireNonNull(terrainSampler, "terrainSampler");
|
||||
return request -> {
|
||||
if (request.field() == Field.UNDERGROUND_FLUID_LEVEL) {
|
||||
@@ -52,7 +49,6 @@ public interface HydrologyGeometrySampler {
|
||||
}
|
||||
if (request.field() == Field.SURFACE_WIDTH
|
||||
|| request.field() == Field.SURFACE_DEPTH
|
||||
|| request.field() == Field.SURFACE_INSET
|
||||
|| request.field() == Field.UNDERGROUND_WIDTH
|
||||
|| request.field() == Field.UNDERGROUND_DEPTH) {
|
||||
return request.minimum();
|
||||
@@ -64,11 +60,6 @@ public interface HydrologyGeometrySampler {
|
||||
request.z(),
|
||||
0x424c454e44L
|
||||
);
|
||||
case TARGET_POOL_LENGTH -> HydrologyHash.mix(
|
||||
worldSeed,
|
||||
request.stableId(),
|
||||
0x504f4f4cL
|
||||
);
|
||||
case UNDERGROUND_HEADROOM -> HydrologyHash.mix(
|
||||
request.stableId(),
|
||||
request.x(),
|
||||
@@ -85,9 +76,7 @@ public interface HydrologyGeometrySampler {
|
||||
enum Field {
|
||||
SURFACE_WIDTH,
|
||||
SURFACE_DEPTH,
|
||||
SURFACE_INSET,
|
||||
SURFACE_BLEND_WIDTH,
|
||||
TARGET_POOL_LENGTH,
|
||||
UNDERGROUND_FLUID_LEVEL,
|
||||
UNDERGROUND_WIDTH,
|
||||
UNDERGROUND_DEPTH,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,9 +35,9 @@ public record HydrologyPlannerSettings(
|
||||
Source undergroundSources = new Source(true, 0.25D, Integer.MIN_VALUE, 0, 1, 512);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new Routing(2048, 64, 8, 8192, 8192, new Branching(384, 192), 1.5D, 24D, 2D, 0.2D),
|
||||
new Surface(true, surfaceSources, 4, 8, 2, 4, 1, 1, 10, 1.5D, 4, 32, false, 1, 1, Banks.defaults()),
|
||||
new Hydraulics(80, 180, 1, 7, 24, 8),
|
||||
new Routing(2048, 64, 8192, 8192, 384, 192, 1.5D, 24D, 2D, 0.2D),
|
||||
new Surface(true, surfaceSources, 4, 8, 2, 4, 10, 1.5D, Banks.defaults()),
|
||||
new Hydraulics(8),
|
||||
new Underground(true, undergroundSources, -48, 72, 3, 8, 1, 3, 6, 14, true),
|
||||
new Outlets(
|
||||
true,
|
||||
@@ -97,7 +97,7 @@ public record HydrologyPlannerSettings(
|
||||
int radius = 0;
|
||||
int routeDisplacement = Math.multiplyExact(routing.sampleSpacing(), 3);
|
||||
if (surface.enabled() && surface.sources().enabled()) {
|
||||
int blendWidth = Math.max(surface.maximumTerrainBlendWidth(), surface.banks().maximumBlendWidth());
|
||||
int blendWidth = surface.banks().maximumBlendWidth();
|
||||
int surfaceRadius = (int) StrictMath.ceil(
|
||||
surface.maximumWidth() / 2D + surface.shoreWidth() + blendWidth
|
||||
);
|
||||
@@ -105,7 +105,7 @@ public record HydrologyPlannerSettings(
|
||||
surfaceRadius,
|
||||
(int) StrictMath.ceil(geometry.drops().basinWidth(
|
||||
geometry.drops().flowWidth(surface.maximumWidth())
|
||||
) / 2D + surface.shoreWidth() + surface.maximumTerrainBlendWidth())
|
||||
) / 2D + surface.shoreWidth() + blendWidth)
|
||||
);
|
||||
surfaceRadius = Math.max(surfaceRadius, outlets.coastalGrotto().horizontalRadius());
|
||||
surfaceRadius = Math.max(surfaceRadius, outlets.inlandGrotto().horizontalRadius());
|
||||
@@ -144,18 +144,17 @@ public record HydrologyPlannerSettings(
|
||||
public record Routing(
|
||||
int tileSize,
|
||||
int sampleSpacing,
|
||||
int refinementSpacing,
|
||||
int maximumRouteNodes,
|
||||
int maximumRouteLength,
|
||||
Branching branching,
|
||||
int minimumSurfaceCourseLength,
|
||||
int minimumUndergroundCourseLength,
|
||||
double valleyPreference,
|
||||
double uphillPenalty,
|
||||
double slopePenalty,
|
||||
double confluenceAttraction
|
||||
) {
|
||||
public Routing {
|
||||
if (tileSize < 32 || sampleSpacing < 4 || refinementSpacing < 1 || branching == null
|
||||
|| tileSize % sampleSpacing != 0 || sampleSpacing % refinementSpacing != 0) {
|
||||
if (tileSize < 32 || sampleSpacing < 4 || tileSize % sampleSpacing != 0) {
|
||||
throw new IllegalArgumentException("Routing sizes must form an exact bounded tile lattice.");
|
||||
}
|
||||
int latticeWidth = tileSize / sampleSpacing + 1;
|
||||
@@ -166,8 +165,12 @@ public record HydrologyPlannerSettings(
|
||||
if (maximumRouteNodes < latticeNodes || maximumRouteNodes > 1_000_000 || maximumRouteLength < 1) {
|
||||
throw new IllegalArgumentException("maximumRouteNodes must contain the complete lattice and remain bounded.");
|
||||
}
|
||||
if (branching.minimumSurfaceCourseLength() > maximumRouteLength
|
||||
|| branching.minimumUndergroundCourseLength() > maximumRouteLength) {
|
||||
if (minimumSurfaceCourseLength < 0 || minimumSurfaceCourseLength > 32_768
|
||||
|| minimumUndergroundCourseLength < 0 || minimumUndergroundCourseLength > 32_768) {
|
||||
throw new IllegalArgumentException("Hydrology course lengths are invalid.");
|
||||
}
|
||||
if (minimumSurfaceCourseLength > maximumRouteLength
|
||||
|| minimumUndergroundCourseLength > maximumRouteLength) {
|
||||
throw new IllegalArgumentException("Minimum course lengths cannot exceed maximum route length.");
|
||||
}
|
||||
requireFiniteNonNegative(valleyPreference, "valleyPreference");
|
||||
@@ -175,17 +178,17 @@ public record HydrologyPlannerSettings(
|
||||
requireFiniteNonNegative(slopePenalty, "slopePenalty");
|
||||
requireFiniteNonNegative(confluenceAttraction, "confluenceAttraction");
|
||||
}
|
||||
}
|
||||
|
||||
public record Branching(
|
||||
int minimumSurfaceCourseLength,
|
||||
int minimumUndergroundCourseLength
|
||||
) {
|
||||
public Branching {
|
||||
if (minimumSurfaceCourseLength < 0 || minimumSurfaceCourseLength > 32_768
|
||||
|| minimumUndergroundCourseLength < 0 || minimumUndergroundCourseLength > 32_768) {
|
||||
throw new IllegalArgumentException("Hydrology branching lengths are invalid.");
|
||||
// Route refinement is derived from the lattice, never authored.
|
||||
public static int refinementSpacing(int sampleSpacing) {
|
||||
if (sampleSpacing % 4 == 0) {
|
||||
return 4;
|
||||
}
|
||||
return sampleSpacing % 2 == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
public int refinementSpacing() {
|
||||
return refinementSpacing(sampleSpacing);
|
||||
}
|
||||
|
||||
public int minimumCourseLength(boolean surface) {
|
||||
@@ -221,15 +224,8 @@ public record HydrologyPlannerSettings(
|
||||
int maximumWidth,
|
||||
int minimumDepth,
|
||||
int maximumDepth,
|
||||
int minimumSurfaceInset,
|
||||
int maximumSurfaceInset,
|
||||
int maximumIncision,
|
||||
double shoreWidth,
|
||||
int minimumTerrainBlendWidth,
|
||||
int maximumTerrainBlendWidth,
|
||||
boolean ridgeTunnelsEnabled,
|
||||
int maximumRidgeTunnelLength,
|
||||
int ridgeTunnelHeadroom,
|
||||
Banks banks
|
||||
) {
|
||||
public Surface {
|
||||
@@ -238,14 +234,9 @@ public record HydrologyPlannerSettings(
|
||||
}
|
||||
requireRange(minimumWidth, maximumWidth, 1, 256, "surface width");
|
||||
requireRange(minimumDepth, maximumDepth, 1, 64, "surface depth");
|
||||
requireRange(minimumSurfaceInset, maximumSurfaceInset, 1, 64, "surface inset");
|
||||
if (maximumIncision < 0 || !Double.isFinite(shoreWidth) || shoreWidth < 0D || shoreWidth > 32D) {
|
||||
throw new IllegalArgumentException("Surface incision and shore width are invalid.");
|
||||
}
|
||||
requireRange(minimumTerrainBlendWidth, maximumTerrainBlendWidth, 0, 128, "terrain blend width");
|
||||
if (maximumRidgeTunnelLength < 0 || ridgeTunnelHeadroom < 0) {
|
||||
throw new IllegalArgumentException("Ridge tunnel bounds cannot be negative.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,21 +271,11 @@ public record HydrologyPlannerSettings(
|
||||
}
|
||||
}
|
||||
|
||||
public record Hydraulics(
|
||||
int minimumTargetPoolLength,
|
||||
int maximumTargetPoolLength,
|
||||
int riffleDrop,
|
||||
int maximumGradualDrop,
|
||||
int maximumGradualLength,
|
||||
int waterfallMinimumDrop
|
||||
) {
|
||||
// The routing gates read one hydraulic threshold: the drop that makes a reach a waterfall.
|
||||
public record Hydraulics(int waterfallMinimumDrop) {
|
||||
public Hydraulics {
|
||||
requireRange(minimumTargetPoolLength, maximumTargetPoolLength, 1, 4096, "target pool length");
|
||||
if (riffleDrop < 0 || maximumGradualDrop < riffleDrop
|
||||
|| maximumGradualLength < Math.max(1, maximumGradualDrop)
|
||||
|| waterfallMinimumDrop != maximumGradualDrop + 1
|
||||
|| minimumTargetPoolLength < maximumGradualLength) {
|
||||
throw new IllegalArgumentException("Hydraulic transition thresholds are inconsistent.");
|
||||
if (waterfallMinimumDrop < 1) {
|
||||
throw new IllegalArgumentException("waterfallMinimumDrop must be at least one block.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public record RiverCourse(
|
||||
HydraulicSegment lip = segments.get(segments.size() - 3);
|
||||
HydraulicSegment sinkhole = segments.get(segments.size() - 2);
|
||||
HydraulicSegment grotto = segments.getLast();
|
||||
if (!lip.type().isSurface() && lip.type() != HydrologyFeatureType.RIDGE_BORE
|
||||
if (!lip.type().isSurface()
|
||||
|| sinkhole.type() != HydrologyFeatureType.SINKHOLE
|
||||
|| sinkhole.drop() <= 0
|
||||
|| !sinkhole.receivingPool()
|
||||
|
||||
+7
-36
@@ -65,9 +65,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
private static final int BIOME_PATCH_SCALE = 32;
|
||||
private static final long SURFACE_WIDTH_SALT = 0x5355524657494454L;
|
||||
private static final long SURFACE_DEPTH_SALT = 0x5355524644455054L;
|
||||
private static final long SURFACE_INSET_SALT = 0x53555246494e5345L;
|
||||
private static final long SURFACE_BLEND_SALT = 0x53555246424c454eL;
|
||||
private static final long TARGET_POOL_SALT = 0x544152474554504fL;
|
||||
private static final long UNDERGROUND_LEVEL_SALT = 0x554e4445524c564cL;
|
||||
private static final long UNDERGROUND_WIDTH_SALT = 0x554e444552574944L;
|
||||
private static final long UNDERGROUND_DEPTH_SALT = 0x554e444552444550L;
|
||||
@@ -556,9 +554,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||
ProceduralStream<Double> surfaceWidth = styledStream(context, channel.getWidth(), SURFACE_WIDTH_SALT);
|
||||
ProceduralStream<Double> surfaceDepth = styledStream(context, channel.getDepth(), SURFACE_DEPTH_SALT);
|
||||
ProceduralStream<Double> surfaceInset = ProceduralStream.ofDouble((x, z) -> (double) channel.getInset());
|
||||
ProceduralStream<Double> surfaceBlend = ProceduralStream.ofDouble((x, z) -> (double) banks.getMaximumBlendWidth());
|
||||
ProceduralStream<Double> targetPool = ProceduralStream.ofDouble((x, z) -> 128D);
|
||||
ProceduralStream<Double> undergroundLevel = styledStream(
|
||||
context,
|
||||
underground.getFluidLevel(),
|
||||
@@ -589,9 +585,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
ProceduralStream<Double> stream = switch (request.field()) {
|
||||
case SURFACE_WIDTH -> surfaceWidth;
|
||||
case SURFACE_DEPTH -> surfaceDepth;
|
||||
case SURFACE_INSET -> surfaceInset;
|
||||
case SURFACE_BLEND_WIDTH -> surfaceBlend;
|
||||
case TARGET_POOL_LENGTH -> targetPool;
|
||||
case UNDERGROUND_FLUID_LEVEL -> undergroundLevel;
|
||||
case UNDERGROUND_WIDTH -> undergroundWidth;
|
||||
case UNDERGROUND_DEPTH -> undergroundDepth;
|
||||
@@ -639,7 +633,6 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||
IrisUndergroundRiverSourceConfig undergroundSources = underground.getSources();
|
||||
int routeNodes = maximumRouteNodes(routing);
|
||||
int refinementSpacing = refinementSpacing(routing.getSampleSpacing());
|
||||
int minimumWorldY = dimension.getMinHeight();
|
||||
boolean riversEnabled = rivers.isEnabled();
|
||||
boolean surfaceEnabled = riversEnabled && surface.isEnabled();
|
||||
@@ -647,13 +640,10 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
HydrologyPlannerSettings.Routing plannerRouting = new HydrologyPlannerSettings.Routing(
|
||||
routing.getTileSize(),
|
||||
routing.getSampleSpacing(),
|
||||
refinementSpacing,
|
||||
routeNodes,
|
||||
routing.getMaximumRouteLength(),
|
||||
new HydrologyPlannerSettings.Branching(
|
||||
routing.getMinimumSurfaceCourseLength(),
|
||||
routing.getMinimumUndergroundCourseLength()
|
||||
),
|
||||
routing.getMinimumSurfaceCourseLength(),
|
||||
routing.getMinimumUndergroundCourseLength(),
|
||||
routing.getValleyPreference(),
|
||||
routing.getUphillPenalty(),
|
||||
routing.getSlopePenalty(),
|
||||
@@ -674,15 +664,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
maximumInt(channel.getWidth()),
|
||||
minimumInt(channel.getDepth()),
|
||||
maximumInt(channel.getDepth()),
|
||||
channel.getInset(),
|
||||
channel.getInset(),
|
||||
channel.getMaximumIncision(),
|
||||
banks.getShoreWidth(),
|
||||
banks.getMinimumBlendWidth(),
|
||||
banks.getMaximumBlendWidth(),
|
||||
false,
|
||||
1,
|
||||
1,
|
||||
new HydrologyPlannerSettings.Banks(
|
||||
channel.getInset(),
|
||||
banks.getFreeboard(),
|
||||
@@ -697,14 +680,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
banks.isExposeCutStrata()
|
||||
)
|
||||
);
|
||||
HydrologyPlannerSettings.Hydraulics plannerHydraulics = new HydrologyPlannerSettings.Hydraulics(
|
||||
80,
|
||||
180,
|
||||
1,
|
||||
flow.getWaterfallMinimumDrop() - 1,
|
||||
24,
|
||||
flow.getWaterfallMinimumDrop()
|
||||
);
|
||||
HydrologyPlannerSettings.Hydraulics plannerHydraulics =
|
||||
new HydrologyPlannerSettings.Hydraulics(flow.getWaterfallMinimumDrop());
|
||||
HydrologyPlannerSettings.Source plannerUndergroundSources = new HydrologyPlannerSettings.Source(
|
||||
undergroundEnabled,
|
||||
undergroundSources.getDensity(),
|
||||
@@ -760,17 +737,10 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
plannerUnderground,
|
||||
plannerOutlets,
|
||||
plannerGeometry,
|
||||
deepFluids(hydrology.getDeepFluids(), minimumWorldY, routing, refinementSpacing)
|
||||
deepFluids(hydrology.getDeepFluids(), minimumWorldY, routing, plannerRouting.refinementSpacing())
|
||||
);
|
||||
}
|
||||
|
||||
static int refinementSpacing(int sampleSpacing) {
|
||||
if (sampleSpacing % 4 == 0) {
|
||||
return 4;
|
||||
}
|
||||
return sampleSpacing % 2 == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
private static HydrologyPlannerSettings.Geometry geometry(
|
||||
IrisRiverGeometryConfig geometry,
|
||||
HydrologyPlannerSettings.ChannelShape surfaceShape
|
||||
@@ -877,7 +847,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
||||
return 0;
|
||||
}
|
||||
int configuredLength = Math.max(
|
||||
refinementSpacing(routing.getSampleSpacing()), configuration.getSpacing() / 3);
|
||||
HydrologyPlannerSettings.Routing.refinementSpacing(routing.getSampleSpacing()),
|
||||
configuration.getSpacing() / 3);
|
||||
return Math.min(configuredLength, routing.getTileSize() / 2);
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -31,12 +31,12 @@ public class HydrologyCaveCourseFilterTest {
|
||||
};
|
||||
|
||||
@Test
|
||||
public void rejectedRidgeBoreIsAbsentFromCoursesFootprintRendererAndLocator() {
|
||||
public void rejectedCaveCourseIsAbsentFromCoursesFootprintRendererAndLocator() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
22L,
|
||||
11L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -81,19 +81,19 @@ public class HydrologyCaveCourseFilterTest {
|
||||
assertTrue(tile.footprint().isEmpty());
|
||||
assertTrue(tile.features().isEmpty());
|
||||
assertTrue(tile.renderAt(8, 8).features().isEmpty());
|
||||
assertTrue(tile.nearestFeature(HydrologyFeatureType.RIDGE_BORE, 8, 8, 16).isEmpty());
|
||||
assertTrue(tile.nearestFeature(HydrologyFeatureType.UNDERGROUND_POOL, 8, 8, 16).isEmpty());
|
||||
assertEquals(1, tile.diagnosticCandidates().size());
|
||||
assertEquals(HydrologyCandidateRejection.CAVE_CONTAINMENT,
|
||||
tile.diagnosticCandidates().getFirst().rejection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatedSurfaceConnectedCaveAroundRidgeBoreIsSealed() {
|
||||
public void generatedSurfaceConnectedCaveAroundAnUndergroundReachIsSealed() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
42L,
|
||||
41L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -136,7 +136,7 @@ public class HydrologyCaveCourseFilterTest {
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
420L,
|
||||
410L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -218,12 +218,12 @@ public class HydrologyCaveCourseFilterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ridgeBoreAboveFinalTerrainRejectsTheWholeCourse() {
|
||||
public void undergroundReachAboveFinalTerrainRejectsTheWholeCourse() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
52L,
|
||||
51L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -255,12 +255,12 @@ public class HydrologyCaveCourseFilterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceRidgeExposurePreflightChecksTheFullActionBoundaryBeforeVoxelExpansion() {
|
||||
public void surfaceExposurePreflightChecksTheFullActionBoundaryBeforeVoxelExpansion() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
152L,
|
||||
151L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -294,12 +294,12 @@ public class HydrologyCaveCourseFilterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ridgeSurfaceOpeningExemptsItsCompleteSixNeighborShell() {
|
||||
public void caveSurfaceOpeningExemptsItsCompleteSixNeighborShell() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
162L,
|
||||
161L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -505,7 +505,7 @@ public class HydrologyCaveCourseFilterTest {
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
192L,
|
||||
191L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -598,12 +598,12 @@ public class HydrologyCaveCourseFilterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptedRidgeBoreRetainsItsExactPlanOnTheImmutableTile() {
|
||||
public void acceptedCaveCourseRetainsItsExactPlanOnTheImmutableTile() {
|
||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
82L,
|
||||
81L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -959,7 +959,7 @@ public class HydrologyCaveCourseFilterTest {
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
102L,
|
||||
101L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
@@ -1034,7 +1034,7 @@ public class HydrologyCaveCourseFilterTest {
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
92L,
|
||||
91L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
20,
|
||||
20,
|
||||
2,
|
||||
|
||||
+64
-129
@@ -16,6 +16,57 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HydrologyFootprintCompilerTest {
|
||||
private static final int[][] CARDINALS = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
|
||||
|
||||
/**
|
||||
* Published dry cells cardinally adjacent to owned water whose final terrain sits below the
|
||||
* water head plus the configured freeboard.
|
||||
*/
|
||||
private static int unsupportedBankCells(RiverFootprint footprint, long courseId) {
|
||||
int freeboard = HydrologyPlannerSettings.defaults().surface().banks().freeboard();
|
||||
int unsupported = 0;
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
if (fluid == null
|
||||
|| fluid.feature().courseId() != courseId
|
||||
|| fluid.oceanApron()
|
||||
|| fluid.fallingFluid()) {
|
||||
continue;
|
||||
}
|
||||
for (int[] offset : CARDINALS) {
|
||||
HydrologyColumnSample neighbor = footprint
|
||||
.sample(sample.x() + offset[0], sample.z() + offset[1])
|
||||
.orElse(null);
|
||||
if (neighbor == null || neighbor.primarySurfaceFluidLayer().isPresent()) {
|
||||
continue;
|
||||
}
|
||||
if (neighbor.terrainHeight() < fluid.fluidHeadY() + freeboard) {
|
||||
unsupported++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return unsupported;
|
||||
}
|
||||
|
||||
/** Deepest cut between natural terrain and the published water head over an owned channel. */
|
||||
private static int maximumSurfaceCut(RiverFootprint footprint, long courseId) {
|
||||
int maximum = 0;
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
HydrologyColumnLayer fluid = sample.primarySurfaceFluidLayer().orElse(null);
|
||||
if (fluid == null
|
||||
|| fluid.feature().courseId() != courseId
|
||||
|| fluid.feature().type() == HydrologyFeatureType.MOUTH
|
||||
|| fluid.oceanApron()
|
||||
|| fluid.fallingFluid()
|
||||
|| !fluid.channel()
|
||||
|| !fluid.fluidOwned()) {
|
||||
continue;
|
||||
}
|
||||
maximum = Math.max(maximum, sample.naturalHeight() - fluid.fluidHeadY());
|
||||
}
|
||||
return maximum;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceChannelNeverRaisesTerrainOrPublishesUnsupportedFluid() {
|
||||
HydraulicSegment segment = new HydraulicSegment(
|
||||
@@ -78,7 +129,7 @@ public class HydrologyFootprintCompilerTest {
|
||||
RiverFootprint footprint = new HydrologyFootprintCompiler(
|
||||
HydrologyPlannerSettings.defaults(),
|
||||
terrain,
|
||||
HydrologyGeometrySampler.deterministic(1L, terrain)
|
||||
HydrologyGeometrySampler.deterministic(terrain)
|
||||
).compile(List.of(course));
|
||||
|
||||
for (int x = 0; x <= 8; x++) {
|
||||
@@ -162,7 +213,7 @@ public class HydrologyFootprintCompilerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceChannelAtTerrainLevelIsReportedAsUncontained() {
|
||||
public void surfaceChannelAtTerrainLevelHasNoContainingBank() {
|
||||
HydraulicSegment segment = new HydraulicSegment(
|
||||
15L,
|
||||
14L,
|
||||
@@ -180,7 +231,7 @@ public class HydrologyFootprintCompilerTest {
|
||||
HydrologyFootprintCompiler compiler = compiler(terrain);
|
||||
RiverFootprint footprint = compiler.compile(List.of(course));
|
||||
|
||||
assertFalse(compiler.surfaceBanksContained(course));
|
||||
assertTrue(unsupportedBankCells(footprint, 14L) > 0);
|
||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||
assertTrue(sample.terrainHeight() <= sample.naturalHeight());
|
||||
}
|
||||
@@ -1026,51 +1077,6 @@ public class HydrologyFootprintCompilerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceBankGradingTapersAnIntersectingBoreInsteadOfOpeningItsSide() {
|
||||
HydraulicSegment surface = new HydraulicSegment(
|
||||
321L,
|
||||
320L,
|
||||
HydrologyFeatureType.SURFACE_POOL,
|
||||
70,
|
||||
70,
|
||||
6,
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
List.of(new HydrologyPoint(0, 70, 0), new HydrologyPoint(8, 70, 0))
|
||||
);
|
||||
HydraulicSegment ridge = new HydraulicSegment(
|
||||
322L,
|
||||
320L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
74,
|
||||
74,
|
||||
4,
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
List.of(new HydrologyPoint(0, 74, 8), new HydrologyPoint(8, 74, 8))
|
||||
);
|
||||
HydrologyTerrainSampler terrain = (int x, int z) -> HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||
RiverFootprint footprint = compiler(terrain).compile(List.of(new RiverCourse(
|
||||
320L,
|
||||
RiverCourseType.SURFACE,
|
||||
OptionalLong.of(1L),
|
||||
OptionalLong.of(2L),
|
||||
"water",
|
||||
1,
|
||||
List.of(),
|
||||
List.of(surface, ridge)
|
||||
)));
|
||||
|
||||
HydrologyColumnSample gradedBank = footprint.sample(4, 8).orElseThrow();
|
||||
assertTrue(gradedBank.layers().stream().noneMatch(
|
||||
(HydrologyColumnLayer layer) -> layer.feature().type() == HydrologyFeatureType.RIDGE_BORE
|
||||
));
|
||||
assertTrue(gradedBank.terrainHeight() < gradedBank.naturalHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compactValidationMatchesFullRasterAcrossOverlapsOceanAndSurfaceOnlyCourses() {
|
||||
RiverCourse mixed = new RiverCourse(
|
||||
@@ -1389,64 +1395,6 @@ public class HydrologyFootprintCompilerTest {
|
||||
int sourceDepth = source.fluidHeadY() - source.bedY();
|
||||
int cruiseDepth = cruise.fluidHeadY() - cruise.bedY();
|
||||
assertTrue(Math.abs(sourceDepth - cruiseDepth) <= 1);
|
||||
assertTrue(compiler.surfaceHeadwaterRampSupported(course));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void incompleteSurfaceBoreCenterlineRejectsTheWholeCourse() {
|
||||
HydraulicSegment entry = new HydraulicSegment(
|
||||
532L,
|
||||
531L,
|
||||
HydrologyFeatureType.SURFACE_POOL,
|
||||
70,
|
||||
70,
|
||||
8,
|
||||
3,
|
||||
false,
|
||||
false,
|
||||
List.of(new HydrologyPoint(0, 70, 0), new HydrologyPoint(16, 70, 0))
|
||||
);
|
||||
HydraulicSegment bore = new HydraulicSegment(
|
||||
533L,
|
||||
531L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
70,
|
||||
70,
|
||||
8,
|
||||
3,
|
||||
false,
|
||||
false,
|
||||
List.of(new HydrologyPoint(16, 70, 0), new HydrologyPoint(48, 70, 0))
|
||||
);
|
||||
HydraulicSegment exit = new HydraulicSegment(
|
||||
534L,
|
||||
531L,
|
||||
HydrologyFeatureType.SURFACE_POOL,
|
||||
70,
|
||||
70,
|
||||
8,
|
||||
3,
|
||||
false,
|
||||
false,
|
||||
List.of(new HydrologyPoint(48, 70, 0), new HydrologyPoint(64, 70, 0))
|
||||
);
|
||||
HydrologyTerrainSampler terrain = (int x, int z) -> HydrologyTerrainSample.openLand(
|
||||
x == 32 ? 70 : 82,
|
||||
0D,
|
||||
"parent"
|
||||
);
|
||||
RiverCourse course = new RiverCourse(
|
||||
531L,
|
||||
RiverCourseType.SURFACE,
|
||||
OptionalLong.of(1L),
|
||||
OptionalLong.of(2L),
|
||||
"water",
|
||||
1,
|
||||
List.of(),
|
||||
List.of(entry, bore, exit)
|
||||
);
|
||||
|
||||
assertFalse(compiler(terrain).surfaceBanksContained(course));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1519,17 +1467,17 @@ public class HydrologyFootprintCompilerTest {
|
||||
RiverFootprint lowBankFootprint = lowBankCompiler.compile(List.of(course));
|
||||
HydrologyColumnSample lowBank = lowBankFootprint.sample(12, lowBankZ).orElseThrow();
|
||||
|
||||
assertTrue(highCompiler.surfaceBanksContained(course));
|
||||
assertEquals(0, unsupportedBankCells(highFootprint, 528L));
|
||||
assertEquals(70, lowBank.naturalHeight());
|
||||
assertEquals(70, lowBank.terrainHeight());
|
||||
assertFalse(lowBankCompiler.surfaceBanksContained(course));
|
||||
assertTrue(unsupportedBankCells(lowBankFootprint, 528L) > 0);
|
||||
for (HydrologyColumnSample sample : lowBankFootprint.columns().values()) {
|
||||
assertTrue(sample.terrainHeight() <= sample.naturalHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceIncisionContainmentUsesFinalTerrainHeight() {
|
||||
public void publishedSurfaceChannelStaysWithinTheConfiguredIncision() {
|
||||
HydraulicSegment channel = new HydraulicSegment(
|
||||
529L,
|
||||
528L,
|
||||
@@ -1543,28 +1491,16 @@ public class HydrologyFootprintCompilerTest {
|
||||
List.of(new HydrologyPoint(0, 70, 0), new HydrologyPoint(24, 70, 0))
|
||||
);
|
||||
RiverCourse course = course(528L, RiverCourseType.SURFACE, channel);
|
||||
HydrologyFootprintCompiler supported = compiler((int x, int z) ->
|
||||
HydrologyFootprintCompiler compiler = compiler((int x, int z) ->
|
||||
HydrologyTerrainSample.openLand(76, 0D, "parent"));
|
||||
HydrologyTerrainSample routingBasis = HydrologyTerrainSample.openLand(76, 0D, "parent");
|
||||
HydrologyFootprintCompiler excessive = new HydrologyFootprintCompiler(
|
||||
HydrologyPlannerSettings.defaults(),
|
||||
new HydrologyFootprintCompiler.Sampling(
|
||||
(int x, int z) -> HydrologyTerrainSample.openLand(83, 0D, "parent"),
|
||||
request -> request.minimum(),
|
||||
new CountingNaturalSampler(
|
||||
routingBasis,
|
||||
HydrologyRoutingTerrainSampler.NaturalClassification.LAND
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
assertTrue(supported.surfaceIncisionContained(course));
|
||||
RiverFootprint excessiveFootprint = excessive.compile(List.of(course));
|
||||
assertFalse(
|
||||
"center=" + excessiveFootprint.sample(12, 0),
|
||||
excessive.surfaceIncisionContained(course)
|
||||
RiverFootprint footprint = compiler.compile(List.of(course));
|
||||
|
||||
assertTrue(
|
||||
"center=" + footprint.sample(12, 0),
|
||||
maximumSurfaceCut(footprint, 528L)
|
||||
<= HydrologyPlannerSettings.defaults().surface().maximumIncision()
|
||||
);
|
||||
assertFalse(excessive.surfaceIncisionContained(course, excessiveFootprint));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1592,7 +1528,6 @@ public class HydrologyFootprintCompilerTest {
|
||||
HydrologyFootprintCompiler compiler = compiler(terrain);
|
||||
|
||||
assertTrue(compiler.compile(List.of(course)).isEmpty());
|
||||
assertFalse(compiler.surfaceBanksContained(course));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -153,7 +153,7 @@ public class HydrologyModelTest {
|
||||
HydraulicSegment containedLip = new HydraulicSegment(
|
||||
4L,
|
||||
9L,
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.SURFACE_POOL,
|
||||
80,
|
||||
80,
|
||||
4,
|
||||
|
||||
+2
-19
@@ -252,8 +252,7 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(256, 16, 4, 1_089, 256,
|
||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.2D),
|
||||
new HydrologyPlannerSettings.Routing(256, 16, 1_089, 256, 16, 8, 0.5D, 12D, 0.5D, 0.2D),
|
||||
new HydrologyPlannerSettings.Surface(
|
||||
true,
|
||||
surfaceSources,
|
||||
@@ -261,18 +260,10 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
20,
|
||||
2,
|
||||
5,
|
||||
4,
|
||||
8,
|
||||
12,
|
||||
1.5D,
|
||||
4,
|
||||
10,
|
||||
true,
|
||||
96,
|
||||
10
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
true,
|
||||
undergroundSources,
|
||||
@@ -343,16 +334,8 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
||||
baseSurface.maximumWidth(),
|
||||
baseSurface.minimumDepth(),
|
||||
baseSurface.maximumDepth(),
|
||||
baseSurface.minimumSurfaceInset(),
|
||||
baseSurface.maximumSurfaceInset(),
|
||||
64,
|
||||
baseSurface.shoreWidth(),
|
||||
baseSurface.minimumTerrainBlendWidth(),
|
||||
baseSurface.maximumTerrainBlendWidth(),
|
||||
baseSurface.ridgeTunnelsEnabled(),
|
||||
baseSurface.maximumRidgeTunnelLength(),
|
||||
baseSurface.ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
|
||||
+9
-28
@@ -639,33 +639,31 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
boolean undergroundEnabled,
|
||||
List<HydrologyPlannerSettings.DeepFluid> deepFluids
|
||||
) {
|
||||
return settingsWithRefinement(
|
||||
return plannerSettings(
|
||||
surfaceSources,
|
||||
undergroundSources,
|
||||
surfaceEnabled,
|
||||
undergroundEnabled,
|
||||
deepFluids,
|
||||
4
|
||||
deepFluids
|
||||
);
|
||||
}
|
||||
|
||||
private HydrologyPlannerSettings settingsWithRefinement(
|
||||
private HydrologyPlannerSettings plannerSettings(
|
||||
HydrologyPlannerSettings.Source surfaceSources,
|
||||
HydrologyPlannerSettings.Source undergroundSources,
|
||||
boolean surfaceEnabled,
|
||||
boolean undergroundEnabled,
|
||||
List<HydrologyPlannerSettings.DeepFluid> deepFluids,
|
||||
int refinementSpacing
|
||||
List<HydrologyPlannerSettings.DeepFluid> deepFluids
|
||||
) {
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(
|
||||
TILE_SIZE,
|
||||
16,
|
||||
refinementSpacing,
|
||||
512,
|
||||
256,
|
||||
new HydrologyPlannerSettings.Branching(16, 8),
|
||||
16,
|
||||
8,
|
||||
0.5D,
|
||||
12D,
|
||||
0.5D,
|
||||
@@ -678,18 +676,10 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
8,
|
||||
128,
|
||||
1D,
|
||||
1,
|
||||
2,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundEnabled,
|
||||
undergroundSources,
|
||||
@@ -724,13 +714,12 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
boolean surfaceEnabled,
|
||||
boolean undergroundEnabled
|
||||
) {
|
||||
HydrologyPlannerSettings base = settingsWithRefinement(
|
||||
HydrologyPlannerSettings base = plannerSettings(
|
||||
surfaceSources,
|
||||
undergroundSources,
|
||||
surfaceEnabled,
|
||||
undergroundEnabled,
|
||||
List.of(),
|
||||
8
|
||||
List.of()
|
||||
);
|
||||
HydrologyPlannerSettings.Surface surface = base.surface();
|
||||
HydrologyPlannerSettings.Underground underground = base.underground();
|
||||
@@ -744,16 +733,8 @@ public class HydrologyPlannerGlobalInvariantTest {
|
||||
surface.minimumWidth(),
|
||||
surface.minimumDepth(),
|
||||
surface.maximumDepth(),
|
||||
surface.minimumSurfaceInset(),
|
||||
surface.maximumSurfaceInset(),
|
||||
surface.maximumIncision(),
|
||||
surface.shoreWidth(),
|
||||
surface.minimumTerrainBlendWidth(),
|
||||
surface.maximumTerrainBlendWidth(),
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
surface.maximumRidgeTunnelLength(),
|
||||
surface.ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
||||
settings,
|
||||
detailSampler,
|
||||
routingSampler,
|
||||
HydrologyGeometrySampler.deterministic(17L, detailSampler),
|
||||
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||
-4096,
|
||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||
);
|
||||
@@ -70,7 +70,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
||||
settings,
|
||||
detailSampler,
|
||||
routingSampler,
|
||||
HydrologyGeometrySampler.deterministic(19L, detailSampler),
|
||||
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||
-4096,
|
||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||
);
|
||||
@@ -108,7 +108,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
||||
settings,
|
||||
detailSampler,
|
||||
routingSampler,
|
||||
HydrologyGeometrySampler.deterministic(23L, detailSampler),
|
||||
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||
-4096,
|
||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||
);
|
||||
|
||||
+18
-32
@@ -11,11 +11,19 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HydrologyPlannerSettingsTest {
|
||||
@Test
|
||||
public void branchingUsesIndependentSurfaceAndUndergroundCourseFloors() {
|
||||
HydrologyPlannerSettings.Branching branching = new HydrologyPlannerSettings.Branching(384, 192);
|
||||
public void routingUsesIndependentSurfaceAndUndergroundCourseFloors() {
|
||||
HydrologyPlannerSettings.Routing routing = HydrologyPlannerSettings.defaults().routing();
|
||||
|
||||
assertEquals(384, branching.minimumCourseLength(true));
|
||||
assertEquals(192, branching.minimumCourseLength(false));
|
||||
assertEquals(384, routing.minimumCourseLength(true));
|
||||
assertEquals(192, routing.minimumCourseLength(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refinementSpacingIsDerivedFromTheSampleLattice() {
|
||||
assertEquals(4, HydrologyPlannerSettings.Routing.refinementSpacing(64));
|
||||
assertEquals(2, HydrologyPlannerSettings.Routing.refinementSpacing(50));
|
||||
assertEquals(1, HydrologyPlannerSettings.Routing.refinementSpacing(45));
|
||||
assertEquals(4, HydrologyPlannerSettings.defaults().routing().refinementSpacing());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,10 +71,10 @@ public class HydrologyPlannerSettingsTest {
|
||||
HydrologyPlannerSettings.Routing routing = new HydrologyPlannerSettings.Routing(
|
||||
512,
|
||||
512,
|
||||
64,
|
||||
4,
|
||||
256,
|
||||
new HydrologyPlannerSettings.Branching(0, 0),
|
||||
0,
|
||||
0,
|
||||
0D,
|
||||
0D,
|
||||
0D,
|
||||
@@ -80,25 +88,10 @@ public class HydrologyPlannerSettingsTest {
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1D,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults());
|
||||
HydrologyPlannerSettings.Hydraulics hydraulics = new HydrologyPlannerSettings.Hydraulics(
|
||||
8,
|
||||
8,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
);
|
||||
HydrologyPlannerSettings.Hydraulics hydraulics = new HydrologyPlannerSettings.Hydraulics(1);
|
||||
HydrologyPlannerSettings.Grotto grotto = new HydrologyPlannerSettings.Grotto(true, 1, 1, 1, 1);
|
||||
HydrologyPlannerSettings.Outlets outlets = new HydrologyPlannerSettings.Outlets(
|
||||
true,
|
||||
@@ -168,20 +161,13 @@ public class HydrologyPlannerSettingsTest {
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Surface(
|
||||
true,
|
||||
new HydrologyPlannerSettings.Source(true, 1D, 0, 0, 1, 0),
|
||||
1, 1, 1, 1, 1, 1, 0, 1D, 0, 0, false, 0, 0,
|
||||
1, 1, 1, 1, 0, 1D,
|
||||
null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inconsistentHydraulicThresholdsAreRejected() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Hydraulics(
|
||||
8,
|
||||
16,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
));
|
||||
public void nonPositiveWaterfallThresholdsAreRejected() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Hydraulics(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -522,35 +522,14 @@ public class HydrologyPlannerTest {
|
||||
assertFalse("diagnostics=" + tile.diagnosticCandidates(), surfaceCourses(tile).isEmpty());
|
||||
boolean aggregateTransition = false;
|
||||
for (RiverCourse course : surfaceCourses(tile)) {
|
||||
double recovery = Double.POSITIVE_INFINITY;
|
||||
boolean transitionActive = false;
|
||||
for (HydraulicSegment segment : course.segments()) {
|
||||
boolean surfaceDrop = segment.type().isSurface() && segment.type().isDrop();
|
||||
if (surfaceDrop) {
|
||||
if (!transitionActive) {
|
||||
assertTrue(
|
||||
"segments=" + course.segments(),
|
||||
!Double.isFinite(recovery)
|
||||
|| recovery >= settings.hydraulics().minimumTargetPoolLength()
|
||||
);
|
||||
}
|
||||
recovery = 0D;
|
||||
transitionActive = !segment.receivingPool();
|
||||
if (segment.type() == HydrologyFeatureType.WATERFALL
|
||||
&& segment.drop() >= settings.hydraulics().waterfallMinimumDrop()) {
|
||||
aggregateTransition = true;
|
||||
}
|
||||
if (segment.drop() < settings.hydraulics().waterfallMinimumDrop()) {
|
||||
continue;
|
||||
}
|
||||
if (segment.type() == HydrologyFeatureType.UNDERGROUND_DROP
|
||||
&& segment.drop() >= settings.hydraulics().waterfallMinimumDrop()) {
|
||||
if (segment.type() == HydrologyFeatureType.WATERFALL
|
||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP) {
|
||||
aggregateTransition = true;
|
||||
}
|
||||
if (transitionActive && segment.receivingPool()) {
|
||||
transitionActive = false;
|
||||
} else if (!transitionActive && Double.isFinite(recovery)) {
|
||||
recovery += segmentLength(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("courses=" + surfaceCourses(tile), aggregateTransition);
|
||||
@@ -597,10 +576,8 @@ public class HydrologyPlannerTest {
|
||||
new HydrologyPlannerSettings.Routing(
|
||||
routing.tileSize(),
|
||||
routing.sampleSpacing(),
|
||||
routing.refinementSpacing(),
|
||||
routing.maximumRouteNodes(),
|
||||
routing.maximumRouteLength(),
|
||||
new HydrologyPlannerSettings.Branching(96, 0),
|
||||
routing.maximumRouteLength(), 96, 0,
|
||||
routing.valleyPreference(),
|
||||
routing.uphillPenalty(),
|
||||
routing.slopePenalty(),
|
||||
@@ -792,7 +769,7 @@ public class HydrologyPlannerTest {
|
||||
333L,
|
||||
settings,
|
||||
coast,
|
||||
HydrologyGeometrySampler.deterministic(333L, coast),
|
||||
HydrologyGeometrySampler.deterministic(coast),
|
||||
-4096,
|
||||
footprint -> solidCaveView()
|
||||
).plan(TILE);
|
||||
@@ -1134,16 +1111,8 @@ public class HydrologyPlannerTest {
|
||||
base.surface().maximumWidth(),
|
||||
base.surface().minimumDepth(),
|
||||
8,
|
||||
base.surface().minimumSurfaceInset(),
|
||||
base.surface().maximumSurfaceInset(),
|
||||
128,
|
||||
base.surface().shoreWidth(),
|
||||
base.surface().minimumTerrainBlendWidth(),
|
||||
base.surface().maximumTerrainBlendWidth(),
|
||||
base.surface().ridgeTunnelsEnabled(),
|
||||
base.surface().maximumRidgeTunnelLength(),
|
||||
base.surface().ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults());
|
||||
HydrologyPlannerSettings shaped = new HydrologyPlannerSettings(
|
||||
base.seaLevel(),
|
||||
@@ -1432,16 +1401,8 @@ public class HydrologyPlannerTest {
|
||||
surface.maximumWidth(),
|
||||
surface.minimumDepth(),
|
||||
surface.maximumDepth(),
|
||||
surface.minimumSurfaceInset(),
|
||||
surface.maximumSurfaceInset(),
|
||||
surface.maximumIncision(),
|
||||
surface.shoreWidth(),
|
||||
surface.minimumTerrainBlendWidth(),
|
||||
surface.maximumTerrainBlendWidth(),
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
32,
|
||||
surface.ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
base.hydraulics(),
|
||||
base.underground(),
|
||||
@@ -1772,8 +1733,7 @@ public class HydrologyPlannerTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 4, 512, 256,
|
||||
new HydrologyPlannerSettings.Branching(0, 0), 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 0, 0, 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(
|
||||
surfaceDensity > 0D || surfaceSources.maximumPerTile() > 0,
|
||||
surfaceSources,
|
||||
@@ -1781,18 +1741,10 @@ public class HydrologyPlannerTest {
|
||||
18,
|
||||
2,
|
||||
4,
|
||||
4,
|
||||
8,
|
||||
10,
|
||||
1.5D,
|
||||
4,
|
||||
8,
|
||||
true,
|
||||
64,
|
||||
8
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
undergroundSources,
|
||||
@@ -1842,10 +1794,8 @@ public class HydrologyPlannerTest {
|
||||
new HydrologyPlannerSettings.Routing(
|
||||
512,
|
||||
64,
|
||||
4,
|
||||
1024,
|
||||
2048,
|
||||
new HydrologyPlannerSettings.Branching(64, 32),
|
||||
2048, 64, 32,
|
||||
1.5D,
|
||||
24D,
|
||||
2D,
|
||||
@@ -1858,18 +1808,10 @@ public class HydrologyPlannerTest {
|
||||
surface.maximumWidth(),
|
||||
surface.minimumDepth(),
|
||||
surface.maximumDepth(),
|
||||
surface.minimumSurfaceInset(),
|
||||
surface.maximumSurfaceInset(),
|
||||
96,
|
||||
surface.shoreWidth(),
|
||||
surface.minimumTerrainBlendWidth(),
|
||||
surface.maximumTerrainBlendWidth(),
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
192,
|
||||
surface.ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 4, 12, 5),
|
||||
new HydrologyPlannerSettings.Hydraulics(5),
|
||||
base.underground(),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
true,
|
||||
@@ -2172,16 +2114,8 @@ public class HydrologyPlannerTest {
|
||||
surface.maximumWidth(),
|
||||
surface.minimumDepth(),
|
||||
surface.maximumDepth(),
|
||||
surface.minimumSurfaceInset(),
|
||||
surface.maximumSurfaceInset(),
|
||||
surface.maximumIncision(),
|
||||
surface.shoreWidth(),
|
||||
surface.minimumTerrainBlendWidth(),
|
||||
surface.maximumTerrainBlendWidth(),
|
||||
surface.ridgeTunnelsEnabled(),
|
||||
surface.maximumRidgeTunnelLength(),
|
||||
surface.ridgeTunnelHeadroom()
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
settings.hydraulics(),
|
||||
settings.underground(),
|
||||
|
||||
+2
-11
@@ -192,8 +192,7 @@ public class HydrologyStyledGeometryTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 4, 512, 256,
|
||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(
|
||||
surfaceDensity > 0D,
|
||||
surfaceSources,
|
||||
@@ -201,18 +200,10 @@ public class HydrologyStyledGeometryTest {
|
||||
18,
|
||||
2,
|
||||
4,
|
||||
4,
|
||||
8,
|
||||
10,
|
||||
1.5D,
|
||||
4,
|
||||
8,
|
||||
true,
|
||||
96,
|
||||
8
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
undergroundSources,
|
||||
|
||||
@@ -243,10 +243,10 @@ public class HydrologyTileCacheTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 64,
|
||||
new HydrologyPlannerSettings.Branching(0, 0), 0D, 0D, 0D, 0D),
|
||||
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 2, 4, 4, 1D, 2, 4, false, 0, 0, HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 128, 64, 0, 0, 0D, 0D, 0D, 0D),
|
||||
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 4, 1D,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(3),
|
||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
false,
|
||||
@@ -282,10 +282,9 @@ public class HydrologyTileCacheTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 96,
|
||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 4, 8, 20, 1.5D, 2, 4, true, 96, 8, tileBoundedBanks()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
||||
new HydrologyPlannerSettings.Routing(64, 16, 128, 96, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 20, 1.5D, tileBoundedBanks()),
|
||||
new HydrologyPlannerSettings.Hydraulics(3),
|
||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||
new HydrologyPlannerSettings.Outlets(
|
||||
true,
|
||||
|
||||
+4
-4
@@ -114,14 +114,14 @@ public class IrisHydrologyRuntimeSettingsTest {
|
||||
assertEquals(8, settings.hydraulics().waterfallMinimumDrop());
|
||||
assertEquals(96, settings.outlets().mouthLevelingDistance());
|
||||
assertEquals(4, settings.routing().refinementSpacing());
|
||||
assertEquals(500, settings.routing().branching().minimumSurfaceCourseLength());
|
||||
assertEquals(250, settings.routing().branching().minimumUndergroundCourseLength());
|
||||
assertEquals(500, settings.routing().minimumSurfaceCourseLength());
|
||||
assertEquals(250, settings.routing().minimumUndergroundCourseLength());
|
||||
assertEquals(2.5D, settings.routing().valleyPreference(), 0D);
|
||||
assertEquals(30D, settings.routing().uphillPenalty(), 0D);
|
||||
assertEquals(3D, settings.routing().slopePenalty(), 0D);
|
||||
assertEquals(0.4D, settings.routing().confluenceAttraction(), 0D);
|
||||
assertEquals(2, IrisHydrologyRuntime.refinementSpacing(50));
|
||||
assertEquals(1, IrisHydrologyRuntime.refinementSpacing(45));
|
||||
assertEquals(2, HydrologyPlannerSettings.Routing.refinementSpacing(50));
|
||||
assertEquals(1, HydrologyPlannerSettings.Routing.refinementSpacing(45));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -172,7 +172,7 @@ public class ErosionFieldCompilerTest {
|
||||
return new HydrologyPlannerSettings.Surface(
|
||||
true,
|
||||
defaults.sources(),
|
||||
4, 8, 2, 4, 1, 1, 10, 1.5D, 4, 32, false, 1, 1,
|
||||
4, 8, 2, 4, 10, 1.5D,
|
||||
new HydrologyPlannerSettings.Banks(1, 1, 3D, 4, 32, 0D, 16, 2, 6, 1.6D, true)
|
||||
);
|
||||
}
|
||||
|
||||
+8
-17
@@ -746,10 +746,10 @@ public class MantleHydrologyComponentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sameCourseSurfaceFluidOwnsAChangedRidgeBoundary() {
|
||||
public void sameCourseSurfaceFluidOwnsAChangedCaveBoundary() {
|
||||
long courseId = 33L;
|
||||
HydrologyColumnLayer ridge = layerForCourse(
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
34L,
|
||||
courseId,
|
||||
10L,
|
||||
@@ -1115,7 +1115,7 @@ public class MantleHydrologyComponentTest {
|
||||
"river"
|
||||
);
|
||||
HydrologyColumnLayer cave = layer(
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
72L,
|
||||
15L,
|
||||
20,
|
||||
@@ -1158,7 +1158,7 @@ public class MantleHydrologyComponentTest {
|
||||
"river"
|
||||
);
|
||||
HydrologyColumnLayer cave = layer(
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
72L,
|
||||
15L,
|
||||
20,
|
||||
@@ -1192,7 +1192,7 @@ public class MantleHydrologyComponentTest {
|
||||
"river"
|
||||
);
|
||||
HydrologyColumnLayer cave = layer(
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
74L,
|
||||
17L,
|
||||
20,
|
||||
@@ -1245,7 +1245,7 @@ public class MantleHydrologyComponentTest {
|
||||
"lava"
|
||||
);
|
||||
HydrologyColumnLayer cave = layer(
|
||||
HydrologyFeatureType.RIDGE_BORE,
|
||||
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||
76L,
|
||||
19L,
|
||||
17,
|
||||
@@ -1530,8 +1530,7 @@ public class MantleHydrologyComponentTest {
|
||||
);
|
||||
return new HydrologyPlannerSettings(
|
||||
63,
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 8, 512, 256,
|
||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||
new HydrologyPlannerSettings.Surface(
|
||||
true,
|
||||
surfaceSources,
|
||||
@@ -1539,18 +1538,10 @@ public class MantleHydrologyComponentTest {
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
4,
|
||||
8,
|
||||
128,
|
||||
0D,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
,
|
||||
HydrologyPlannerSettings.Banks.defaults()),
|
||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
false,
|
||||
disabledSources,
|
||||
|
||||
@@ -1576,7 +1576,7 @@ public final class HydrologyPackProbe {
|
||||
publishedMorphology.observe(
|
||||
tile,
|
||||
settings.surface().minimumWidth(),
|
||||
settings.routing().branching().minimumSurfaceCourseLength()
|
||||
settings.routing().minimumSurfaceCourseLength()
|
||||
);
|
||||
HydrologyPlannerSettings.Routing routing = settings.routing();
|
||||
int sampleSpacing = routing.sampleSpacing();
|
||||
@@ -1704,7 +1704,7 @@ public final class HydrologyPackProbe {
|
||||
List<ChannelIncision> incisions = channelIncisions(
|
||||
tile.footprint(),
|
||||
scopedCourseIds,
|
||||
settings.surface().minimumSurfaceInset(),
|
||||
settings.surface().banks().inset(),
|
||||
settings.surface().maximumIncision()
|
||||
);
|
||||
for (ChannelIncision incision : incisions) {
|
||||
|
||||
@@ -220,10 +220,10 @@ public final class HydrologyPlannerProbe {
|
||||
new HydrologyPlannerSettings.Routing(
|
||||
128,
|
||||
16,
|
||||
4,
|
||||
512,
|
||||
256,
|
||||
new HydrologyPlannerSettings.Branching(32, 16),
|
||||
32,
|
||||
16,
|
||||
0.5D,
|
||||
12D,
|
||||
0.5D,
|
||||
@@ -236,18 +236,11 @@ public final class HydrologyPlannerProbe {
|
||||
18,
|
||||
2,
|
||||
4,
|
||||
4,
|
||||
8,
|
||||
10,
|
||||
1.5D,
|
||||
4,
|
||||
8,
|
||||
true,
|
||||
96,
|
||||
8,
|
||||
HydrologyPlannerSettings.Banks.defaults()
|
||||
),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
undergroundDensity > 0D,
|
||||
undergroundSources,
|
||||
@@ -438,10 +431,10 @@ public final class HydrologyPlannerProbe {
|
||||
new HydrologyPlannerSettings.Routing(
|
||||
256,
|
||||
16,
|
||||
4,
|
||||
1_089,
|
||||
256,
|
||||
new HydrologyPlannerSettings.Branching(32, 16),
|
||||
32,
|
||||
16,
|
||||
0.5D,
|
||||
12D,
|
||||
0.5D,
|
||||
@@ -454,18 +447,11 @@ public final class HydrologyPlannerProbe {
|
||||
20,
|
||||
2,
|
||||
5,
|
||||
4,
|
||||
8,
|
||||
12,
|
||||
1.5D,
|
||||
4,
|
||||
10,
|
||||
true,
|
||||
96,
|
||||
10,
|
||||
HydrologyPlannerSettings.Banks.defaults()
|
||||
),
|
||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
||||
new HydrologyPlannerSettings.Hydraulics(4),
|
||||
new HydrologyPlannerSettings.Underground(
|
||||
true,
|
||||
undergroundSources,
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class HydrologyPlannerProbeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requiredCoverageExcludesTheRemovedRidgeBore() {
|
||||
public void requiredCoverageExcludesTheUnproducedRidgeBore() {
|
||||
assertFalse(HydrologyPlannerProbe.REQUIRED_FEATURE_TYPES.contains(HydrologyFeatureType.RIDGE_BORE));
|
||||
assertEquals(
|
||||
EnumSet.complementOf(EnumSet.of(HydrologyFeatureType.RIDGE_BORE)),
|
||||
|
||||
Reference in New Issue
Block a user