mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 05:50:39 +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:
1 parent
639786537b
commit
896e58e212
24 files changed
+305
-1411
No files matched your search
@@ -8,13 +8,11 @@ public enum HydrologyCandidateRejection {
|
|||||||
SOURCE_QUOTA,
|
SOURCE_QUOTA,
|
||||||
SOURCE_SPACING,
|
SOURCE_SPACING,
|
||||||
OUTLET_LIMIT,
|
OUTLET_LIMIT,
|
||||||
RIDGE_CONTAINMENT,
|
|
||||||
OUTLET_LEVEL,
|
OUTLET_LEVEL,
|
||||||
CAVE_CONTAINMENT,
|
CAVE_CONTAINMENT,
|
||||||
VOLUME_LIMIT,
|
VOLUME_LIMIT,
|
||||||
SURFACE_HEAD_RANGE,
|
SURFACE_HEAD_RANGE,
|
||||||
SURFACE_HEAD_DISTRIBUTION,
|
SURFACE_HEAD_DISTRIBUTION,
|
||||||
SURFACE_RIDGE_TUNNEL_LIMIT,
|
|
||||||
SURFACE_EXPOSURE,
|
SURFACE_EXPOSURE,
|
||||||
SURFACE_DROP_UNSUPPORTED,
|
SURFACE_DROP_UNSUPPORTED,
|
||||||
SURFACE_CORRIDOR_UNSUPPORTED,
|
SURFACE_CORRIDOR_UNSUPPORTED,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ public enum HydrologyFeatureType {
|
|||||||
RIFFLE,
|
RIFFLE,
|
||||||
CASCADE,
|
CASCADE,
|
||||||
WATERFALL,
|
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,
|
RIDGE_BORE,
|
||||||
UNDERGROUND_POOL,
|
UNDERGROUND_POOL,
|
||||||
UNDERGROUND_DROP,
|
UNDERGROUND_DROP,
|
||||||
|
|||||||
+7
-418
@@ -12,19 +12,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
final class HydrologyFootprintCompiler {
|
final class HydrologyFootprintCompiler {
|
||||||
private static final int FEATURE_ROLE_COUNT = 7;
|
private static final int FEATURE_ROLE_COUNT = 7;
|
||||||
private static final int COURSE_FOOTPRINT_CACHE_SIZE = 8;
|
private static final int COURSE_FOOTPRINT_CACHE_SIZE = 8;
|
||||||
private static final int VALIDATION_RASTER_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 = {
|
private static final int[][] HORIZONTAL_NEIGHBORS = {
|
||||||
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
|
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
|
||||||
};
|
};
|
||||||
@@ -53,7 +49,7 @@ final class HydrologyFootprintCompiler {
|
|||||||
HydrologyPlannerSettings settings,
|
HydrologyPlannerSettings settings,
|
||||||
HydrologyTerrainSampler sampler
|
HydrologyTerrainSampler sampler
|
||||||
) {
|
) {
|
||||||
this(settings, sampler, HydrologyGeometrySampler.deterministic(0L, sampler));
|
this(settings, sampler, HydrologyGeometrySampler.deterministic(sampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
HydrologyFootprintCompiler(
|
HydrologyFootprintCompiler(
|
||||||
@@ -172,404 +168,6 @@ final class HydrologyFootprintCompiler {
|
|||||||
return fullMaterializationCount;
|
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) {
|
private ValidationCourseRaster compileValidationCourse(RiverCourse course) {
|
||||||
CourseRasterKey rasterKey = new CourseRasterKey(
|
CourseRasterKey rasterKey = new CourseRasterKey(
|
||||||
course.id(),
|
course.id(),
|
||||||
@@ -825,7 +423,6 @@ final class HydrologyFootprintCompiler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return segment.type().isSurface()
|
return segment.type().isSurface()
|
||||||
|| segment.type() == HydrologyFeatureType.RIDGE_BORE
|
|
||||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_POOL
|
|| segment.type() == HydrologyFeatureType.UNDERGROUND_POOL
|
||||||
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP
|
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP
|
||||||
|| segment.type() == HydrologyFeatureType.SINKHOLE
|
|| segment.type() == HydrologyFeatureType.SINKHOLE
|
||||||
@@ -1145,21 +742,15 @@ final class HydrologyFootprintCompiler {
|
|||||||
point.x(),
|
point.x(),
|
||||||
point.z(),
|
point.z(),
|
||||||
segment.id(),
|
segment.id(),
|
||||||
settings.surface().minimumTerrainBlendWidth(),
|
settings.surface().banks().minimumBlendWidth(),
|
||||||
settings.surface().maximumTerrainBlendWidth()
|
settings.surface().banks().maximumBlendWidth()
|
||||||
);
|
);
|
||||||
if (type == HydrologyFeatureType.WATERFALL) {
|
if (type == HydrologyFeatureType.WATERFALL) {
|
||||||
shoreWidth = Math.min(2.5D, shoreWidth);
|
shoreWidth = Math.min(2.5D, shoreWidth);
|
||||||
gradingWidth = Math.min(gradingWidth, Math.max(8D, channelRadius * 4D));
|
gradingWidth = Math.min(gradingWidth, Math.max(8D, channelRadius * 4D));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == HydrologyFeatureType.RIDGE_BORE
|
if (type == HydrologyFeatureType.UNDERGROUND_POOL
|
||||||
|| course.type() == RiverCourseType.SURFACE
|
|
||||||
&& type == HydrologyFeatureType.UNDERGROUND_DROP) {
|
|
||||||
ceiling = fluidHead + settings.surface().ridgeTunnelHeadroom();
|
|
||||||
archedChannel = !falling;
|
|
||||||
organicBoundary = true;
|
|
||||||
} else if (type == HydrologyFeatureType.UNDERGROUND_POOL
|
|
||||||
|| type == HydrologyFeatureType.UNDERGROUND_DROP
|
|| type == HydrologyFeatureType.UNDERGROUND_DROP
|
||||||
|| type == HydrologyFeatureType.SINKHOLE) {
|
|| type == HydrologyFeatureType.SINKHOLE) {
|
||||||
ceiling = fluidHead + geometrySampler.sample(
|
ceiling = fluidHead + geometrySampler.sample(
|
||||||
@@ -1213,7 +804,7 @@ final class HydrologyFootprintCompiler {
|
|||||||
if (course.type() == RiverCourseType.SURFACE && type.isSurface()) {
|
if (course.type() == RiverCourseType.SURFACE && type.isSurface()) {
|
||||||
gradingWidth = Math.max(
|
gradingWidth = Math.max(
|
||||||
gradingWidth,
|
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) {
|
private boolean terrainRoofedSurfaceTransition(RiverCourse course, HydraulicSegment segment) {
|
||||||
return course.type() == RiverCourseType.SURFACE
|
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);
|
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1943,8 +1533,7 @@ final class HydrologyFootprintCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private HydrologyPlannerSettings.ChannelShape channelShape(HydrologyFeatureType type) {
|
private HydrologyPlannerSettings.ChannelShape channelShape(HydrologyFeatureType type) {
|
||||||
if (type.isGrotto() || type == HydrologyFeatureType.DEEP_POOL
|
if (type.isGrotto() || type == HydrologyFeatureType.DEEP_POOL) {
|
||||||
|| type == HydrologyFeatureType.RIDGE_BORE) {
|
|
||||||
return settings.geometry().grottos();
|
return settings.geometry().grottos();
|
||||||
}
|
}
|
||||||
if (type.isUnderground() || type == HydrologyFeatureType.DEEP_CHANNEL) {
|
if (type.isUnderground() || type == HydrologyFeatureType.DEEP_CHANNEL) {
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ public interface HydrologyGeometrySampler {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HydrologyGeometrySampler deterministic(
|
static HydrologyGeometrySampler deterministic(HydrologyTerrainSampler terrainSampler) {
|
||||||
long worldSeed,
|
|
||||||
HydrologyTerrainSampler terrainSampler
|
|
||||||
) {
|
|
||||||
Objects.requireNonNull(terrainSampler, "terrainSampler");
|
Objects.requireNonNull(terrainSampler, "terrainSampler");
|
||||||
return request -> {
|
return request -> {
|
||||||
if (request.field() == Field.UNDERGROUND_FLUID_LEVEL) {
|
if (request.field() == Field.UNDERGROUND_FLUID_LEVEL) {
|
||||||
@@ -52,7 +49,6 @@ public interface HydrologyGeometrySampler {
|
|||||||
}
|
}
|
||||||
if (request.field() == Field.SURFACE_WIDTH
|
if (request.field() == Field.SURFACE_WIDTH
|
||||||
|| request.field() == Field.SURFACE_DEPTH
|
|| request.field() == Field.SURFACE_DEPTH
|
||||||
|| request.field() == Field.SURFACE_INSET
|
|
||||||
|| request.field() == Field.UNDERGROUND_WIDTH
|
|| request.field() == Field.UNDERGROUND_WIDTH
|
||||||
|| request.field() == Field.UNDERGROUND_DEPTH) {
|
|| request.field() == Field.UNDERGROUND_DEPTH) {
|
||||||
return request.minimum();
|
return request.minimum();
|
||||||
@@ -64,11 +60,6 @@ public interface HydrologyGeometrySampler {
|
|||||||
request.z(),
|
request.z(),
|
||||||
0x424c454e44L
|
0x424c454e44L
|
||||||
);
|
);
|
||||||
case TARGET_POOL_LENGTH -> HydrologyHash.mix(
|
|
||||||
worldSeed,
|
|
||||||
request.stableId(),
|
|
||||||
0x504f4f4cL
|
|
||||||
);
|
|
||||||
case UNDERGROUND_HEADROOM -> HydrologyHash.mix(
|
case UNDERGROUND_HEADROOM -> HydrologyHash.mix(
|
||||||
request.stableId(),
|
request.stableId(),
|
||||||
request.x(),
|
request.x(),
|
||||||
@@ -85,9 +76,7 @@ public interface HydrologyGeometrySampler {
|
|||||||
enum Field {
|
enum Field {
|
||||||
SURFACE_WIDTH,
|
SURFACE_WIDTH,
|
||||||
SURFACE_DEPTH,
|
SURFACE_DEPTH,
|
||||||
SURFACE_INSET,
|
|
||||||
SURFACE_BLEND_WIDTH,
|
SURFACE_BLEND_WIDTH,
|
||||||
TARGET_POOL_LENGTH,
|
|
||||||
UNDERGROUND_FLUID_LEVEL,
|
UNDERGROUND_FLUID_LEVEL,
|
||||||
UNDERGROUND_WIDTH,
|
UNDERGROUND_WIDTH,
|
||||||
UNDERGROUND_DEPTH,
|
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);
|
Source undergroundSources = new Source(true, 0.25D, Integer.MIN_VALUE, 0, 1, 512);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new Routing(2048, 64, 8, 8192, 8192, new Branching(384, 192), 1.5D, 24D, 2D, 0.2D),
|
new Routing(2048, 64, 8192, 8192, 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 Surface(true, surfaceSources, 4, 8, 2, 4, 10, 1.5D, Banks.defaults()),
|
||||||
new Hydraulics(80, 180, 1, 7, 24, 8),
|
new Hydraulics(8),
|
||||||
new Underground(true, undergroundSources, -48, 72, 3, 8, 1, 3, 6, 14, true),
|
new Underground(true, undergroundSources, -48, 72, 3, 8, 1, 3, 6, 14, true),
|
||||||
new Outlets(
|
new Outlets(
|
||||||
true,
|
true,
|
||||||
@@ -97,7 +97,7 @@ public record HydrologyPlannerSettings(
|
|||||||
int radius = 0;
|
int radius = 0;
|
||||||
int routeDisplacement = Math.multiplyExact(routing.sampleSpacing(), 3);
|
int routeDisplacement = Math.multiplyExact(routing.sampleSpacing(), 3);
|
||||||
if (surface.enabled() && surface.sources().enabled()) {
|
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(
|
int surfaceRadius = (int) StrictMath.ceil(
|
||||||
surface.maximumWidth() / 2D + surface.shoreWidth() + blendWidth
|
surface.maximumWidth() / 2D + surface.shoreWidth() + blendWidth
|
||||||
);
|
);
|
||||||
@@ -105,7 +105,7 @@ public record HydrologyPlannerSettings(
|
|||||||
surfaceRadius,
|
surfaceRadius,
|
||||||
(int) StrictMath.ceil(geometry.drops().basinWidth(
|
(int) StrictMath.ceil(geometry.drops().basinWidth(
|
||||||
geometry.drops().flowWidth(surface.maximumWidth())
|
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.coastalGrotto().horizontalRadius());
|
||||||
surfaceRadius = Math.max(surfaceRadius, outlets.inlandGrotto().horizontalRadius());
|
surfaceRadius = Math.max(surfaceRadius, outlets.inlandGrotto().horizontalRadius());
|
||||||
@@ -144,18 +144,17 @@ public record HydrologyPlannerSettings(
|
|||||||
public record Routing(
|
public record Routing(
|
||||||
int tileSize,
|
int tileSize,
|
||||||
int sampleSpacing,
|
int sampleSpacing,
|
||||||
int refinementSpacing,
|
|
||||||
int maximumRouteNodes,
|
int maximumRouteNodes,
|
||||||
int maximumRouteLength,
|
int maximumRouteLength,
|
||||||
Branching branching,
|
int minimumSurfaceCourseLength,
|
||||||
|
int minimumUndergroundCourseLength,
|
||||||
double valleyPreference,
|
double valleyPreference,
|
||||||
double uphillPenalty,
|
double uphillPenalty,
|
||||||
double slopePenalty,
|
double slopePenalty,
|
||||||
double confluenceAttraction
|
double confluenceAttraction
|
||||||
) {
|
) {
|
||||||
public Routing {
|
public Routing {
|
||||||
if (tileSize < 32 || sampleSpacing < 4 || refinementSpacing < 1 || branching == null
|
if (tileSize < 32 || sampleSpacing < 4 || tileSize % sampleSpacing != 0) {
|
||||||
|| tileSize % sampleSpacing != 0 || sampleSpacing % refinementSpacing != 0) {
|
|
||||||
throw new IllegalArgumentException("Routing sizes must form an exact bounded tile lattice.");
|
throw new IllegalArgumentException("Routing sizes must form an exact bounded tile lattice.");
|
||||||
}
|
}
|
||||||
int latticeWidth = tileSize / sampleSpacing + 1;
|
int latticeWidth = tileSize / sampleSpacing + 1;
|
||||||
@@ -166,8 +165,12 @@ public record HydrologyPlannerSettings(
|
|||||||
if (maximumRouteNodes < latticeNodes || maximumRouteNodes > 1_000_000 || maximumRouteLength < 1) {
|
if (maximumRouteNodes < latticeNodes || maximumRouteNodes > 1_000_000 || maximumRouteLength < 1) {
|
||||||
throw new IllegalArgumentException("maximumRouteNodes must contain the complete lattice and remain bounded.");
|
throw new IllegalArgumentException("maximumRouteNodes must contain the complete lattice and remain bounded.");
|
||||||
}
|
}
|
||||||
if (branching.minimumSurfaceCourseLength() > maximumRouteLength
|
if (minimumSurfaceCourseLength < 0 || minimumSurfaceCourseLength > 32_768
|
||||||
|| branching.minimumUndergroundCourseLength() > maximumRouteLength) {
|
|| 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.");
|
throw new IllegalArgumentException("Minimum course lengths cannot exceed maximum route length.");
|
||||||
}
|
}
|
||||||
requireFiniteNonNegative(valleyPreference, "valleyPreference");
|
requireFiniteNonNegative(valleyPreference, "valleyPreference");
|
||||||
@@ -175,17 +178,17 @@ public record HydrologyPlannerSettings(
|
|||||||
requireFiniteNonNegative(slopePenalty, "slopePenalty");
|
requireFiniteNonNegative(slopePenalty, "slopePenalty");
|
||||||
requireFiniteNonNegative(confluenceAttraction, "confluenceAttraction");
|
requireFiniteNonNegative(confluenceAttraction, "confluenceAttraction");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public record Branching(
|
// Route refinement is derived from the lattice, never authored.
|
||||||
int minimumSurfaceCourseLength,
|
public static int refinementSpacing(int sampleSpacing) {
|
||||||
int minimumUndergroundCourseLength
|
if (sampleSpacing % 4 == 0) {
|
||||||
) {
|
return 4;
|
||||||
public Branching {
|
|
||||||
if (minimumSurfaceCourseLength < 0 || minimumSurfaceCourseLength > 32_768
|
|
||||||
|| minimumUndergroundCourseLength < 0 || minimumUndergroundCourseLength > 32_768) {
|
|
||||||
throw new IllegalArgumentException("Hydrology branching lengths are invalid.");
|
|
||||||
}
|
}
|
||||||
|
return sampleSpacing % 2 == 0 ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int refinementSpacing() {
|
||||||
|
return refinementSpacing(sampleSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int minimumCourseLength(boolean surface) {
|
public int minimumCourseLength(boolean surface) {
|
||||||
@@ -221,15 +224,8 @@ public record HydrologyPlannerSettings(
|
|||||||
int maximumWidth,
|
int maximumWidth,
|
||||||
int minimumDepth,
|
int minimumDepth,
|
||||||
int maximumDepth,
|
int maximumDepth,
|
||||||
int minimumSurfaceInset,
|
|
||||||
int maximumSurfaceInset,
|
|
||||||
int maximumIncision,
|
int maximumIncision,
|
||||||
double shoreWidth,
|
double shoreWidth,
|
||||||
int minimumTerrainBlendWidth,
|
|
||||||
int maximumTerrainBlendWidth,
|
|
||||||
boolean ridgeTunnelsEnabled,
|
|
||||||
int maximumRidgeTunnelLength,
|
|
||||||
int ridgeTunnelHeadroom,
|
|
||||||
Banks banks
|
Banks banks
|
||||||
) {
|
) {
|
||||||
public Surface {
|
public Surface {
|
||||||
@@ -238,14 +234,9 @@ public record HydrologyPlannerSettings(
|
|||||||
}
|
}
|
||||||
requireRange(minimumWidth, maximumWidth, 1, 256, "surface width");
|
requireRange(minimumWidth, maximumWidth, 1, 256, "surface width");
|
||||||
requireRange(minimumDepth, maximumDepth, 1, 64, "surface depth");
|
requireRange(minimumDepth, maximumDepth, 1, 64, "surface depth");
|
||||||
requireRange(minimumSurfaceInset, maximumSurfaceInset, 1, 64, "surface inset");
|
|
||||||
if (maximumIncision < 0 || !Double.isFinite(shoreWidth) || shoreWidth < 0D || shoreWidth > 32D) {
|
if (maximumIncision < 0 || !Double.isFinite(shoreWidth) || shoreWidth < 0D || shoreWidth > 32D) {
|
||||||
throw new IllegalArgumentException("Surface incision and shore width are invalid.");
|
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(
|
// The routing gates read one hydraulic threshold: the drop that makes a reach a waterfall.
|
||||||
int minimumTargetPoolLength,
|
public record Hydraulics(int waterfallMinimumDrop) {
|
||||||
int maximumTargetPoolLength,
|
|
||||||
int riffleDrop,
|
|
||||||
int maximumGradualDrop,
|
|
||||||
int maximumGradualLength,
|
|
||||||
int waterfallMinimumDrop
|
|
||||||
) {
|
|
||||||
public Hydraulics {
|
public Hydraulics {
|
||||||
requireRange(minimumTargetPoolLength, maximumTargetPoolLength, 1, 4096, "target pool length");
|
if (waterfallMinimumDrop < 1) {
|
||||||
if (riffleDrop < 0 || maximumGradualDrop < riffleDrop
|
throw new IllegalArgumentException("waterfallMinimumDrop must be at least one block.");
|
||||||
|| maximumGradualLength < Math.max(1, maximumGradualDrop)
|
|
||||||
|| waterfallMinimumDrop != maximumGradualDrop + 1
|
|
||||||
|| minimumTargetPoolLength < maximumGradualLength) {
|
|
||||||
throw new IllegalArgumentException("Hydraulic transition thresholds are inconsistent.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public record RiverCourse(
|
|||||||
HydraulicSegment lip = segments.get(segments.size() - 3);
|
HydraulicSegment lip = segments.get(segments.size() - 3);
|
||||||
HydraulicSegment sinkhole = segments.get(segments.size() - 2);
|
HydraulicSegment sinkhole = segments.get(segments.size() - 2);
|
||||||
HydraulicSegment grotto = segments.getLast();
|
HydraulicSegment grotto = segments.getLast();
|
||||||
if (!lip.type().isSurface() && lip.type() != HydrologyFeatureType.RIDGE_BORE
|
if (!lip.type().isSurface()
|
||||||
|| sinkhole.type() != HydrologyFeatureType.SINKHOLE
|
|| sinkhole.type() != HydrologyFeatureType.SINKHOLE
|
||||||
|| sinkhole.drop() <= 0
|
|| sinkhole.drop() <= 0
|
||||||
|| !sinkhole.receivingPool()
|
|| !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 int BIOME_PATCH_SCALE = 32;
|
||||||
private static final long SURFACE_WIDTH_SALT = 0x5355524657494454L;
|
private static final long SURFACE_WIDTH_SALT = 0x5355524657494454L;
|
||||||
private static final long SURFACE_DEPTH_SALT = 0x5355524644455054L;
|
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 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_LEVEL_SALT = 0x554e4445524c564cL;
|
||||||
private static final long UNDERGROUND_WIDTH_SALT = 0x554e444552574944L;
|
private static final long UNDERGROUND_WIDTH_SALT = 0x554e444552574944L;
|
||||||
private static final long UNDERGROUND_DEPTH_SALT = 0x554e444552444550L;
|
private static final long UNDERGROUND_DEPTH_SALT = 0x554e444552444550L;
|
||||||
@@ -556,9 +554,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||||
ProceduralStream<Double> surfaceWidth = styledStream(context, channel.getWidth(), SURFACE_WIDTH_SALT);
|
ProceduralStream<Double> surfaceWidth = styledStream(context, channel.getWidth(), SURFACE_WIDTH_SALT);
|
||||||
ProceduralStream<Double> surfaceDepth = styledStream(context, channel.getDepth(), SURFACE_DEPTH_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> surfaceBlend = ProceduralStream.ofDouble((x, z) -> (double) banks.getMaximumBlendWidth());
|
||||||
ProceduralStream<Double> targetPool = ProceduralStream.ofDouble((x, z) -> 128D);
|
|
||||||
ProceduralStream<Double> undergroundLevel = styledStream(
|
ProceduralStream<Double> undergroundLevel = styledStream(
|
||||||
context,
|
context,
|
||||||
underground.getFluidLevel(),
|
underground.getFluidLevel(),
|
||||||
@@ -589,9 +585,7 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
ProceduralStream<Double> stream = switch (request.field()) {
|
ProceduralStream<Double> stream = switch (request.field()) {
|
||||||
case SURFACE_WIDTH -> surfaceWidth;
|
case SURFACE_WIDTH -> surfaceWidth;
|
||||||
case SURFACE_DEPTH -> surfaceDepth;
|
case SURFACE_DEPTH -> surfaceDepth;
|
||||||
case SURFACE_INSET -> surfaceInset;
|
|
||||||
case SURFACE_BLEND_WIDTH -> surfaceBlend;
|
case SURFACE_BLEND_WIDTH -> surfaceBlend;
|
||||||
case TARGET_POOL_LENGTH -> targetPool;
|
|
||||||
case UNDERGROUND_FLUID_LEVEL -> undergroundLevel;
|
case UNDERGROUND_FLUID_LEVEL -> undergroundLevel;
|
||||||
case UNDERGROUND_WIDTH -> undergroundWidth;
|
case UNDERGROUND_WIDTH -> undergroundWidth;
|
||||||
case UNDERGROUND_DEPTH -> undergroundDepth;
|
case UNDERGROUND_DEPTH -> undergroundDepth;
|
||||||
@@ -639,7 +633,6 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
IrisUndergroundRiverConfig underground = rivers.getUnderground();
|
||||||
IrisUndergroundRiverSourceConfig undergroundSources = underground.getSources();
|
IrisUndergroundRiverSourceConfig undergroundSources = underground.getSources();
|
||||||
int routeNodes = maximumRouteNodes(routing);
|
int routeNodes = maximumRouteNodes(routing);
|
||||||
int refinementSpacing = refinementSpacing(routing.getSampleSpacing());
|
|
||||||
int minimumWorldY = dimension.getMinHeight();
|
int minimumWorldY = dimension.getMinHeight();
|
||||||
boolean riversEnabled = rivers.isEnabled();
|
boolean riversEnabled = rivers.isEnabled();
|
||||||
boolean surfaceEnabled = riversEnabled && surface.isEnabled();
|
boolean surfaceEnabled = riversEnabled && surface.isEnabled();
|
||||||
@@ -647,13 +640,10 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
HydrologyPlannerSettings.Routing plannerRouting = new HydrologyPlannerSettings.Routing(
|
HydrologyPlannerSettings.Routing plannerRouting = new HydrologyPlannerSettings.Routing(
|
||||||
routing.getTileSize(),
|
routing.getTileSize(),
|
||||||
routing.getSampleSpacing(),
|
routing.getSampleSpacing(),
|
||||||
refinementSpacing,
|
|
||||||
routeNodes,
|
routeNodes,
|
||||||
routing.getMaximumRouteLength(),
|
routing.getMaximumRouteLength(),
|
||||||
new HydrologyPlannerSettings.Branching(
|
routing.getMinimumSurfaceCourseLength(),
|
||||||
routing.getMinimumSurfaceCourseLength(),
|
routing.getMinimumUndergroundCourseLength(),
|
||||||
routing.getMinimumUndergroundCourseLength()
|
|
||||||
),
|
|
||||||
routing.getValleyPreference(),
|
routing.getValleyPreference(),
|
||||||
routing.getUphillPenalty(),
|
routing.getUphillPenalty(),
|
||||||
routing.getSlopePenalty(),
|
routing.getSlopePenalty(),
|
||||||
@@ -674,15 +664,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
maximumInt(channel.getWidth()),
|
maximumInt(channel.getWidth()),
|
||||||
minimumInt(channel.getDepth()),
|
minimumInt(channel.getDepth()),
|
||||||
maximumInt(channel.getDepth()),
|
maximumInt(channel.getDepth()),
|
||||||
channel.getInset(),
|
|
||||||
channel.getInset(),
|
|
||||||
channel.getMaximumIncision(),
|
channel.getMaximumIncision(),
|
||||||
banks.getShoreWidth(),
|
banks.getShoreWidth(),
|
||||||
banks.getMinimumBlendWidth(),
|
|
||||||
banks.getMaximumBlendWidth(),
|
|
||||||
false,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
new HydrologyPlannerSettings.Banks(
|
new HydrologyPlannerSettings.Banks(
|
||||||
channel.getInset(),
|
channel.getInset(),
|
||||||
banks.getFreeboard(),
|
banks.getFreeboard(),
|
||||||
@@ -697,14 +680,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
banks.isExposeCutStrata()
|
banks.isExposeCutStrata()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
HydrologyPlannerSettings.Hydraulics plannerHydraulics = new HydrologyPlannerSettings.Hydraulics(
|
HydrologyPlannerSettings.Hydraulics plannerHydraulics =
|
||||||
80,
|
new HydrologyPlannerSettings.Hydraulics(flow.getWaterfallMinimumDrop());
|
||||||
180,
|
|
||||||
1,
|
|
||||||
flow.getWaterfallMinimumDrop() - 1,
|
|
||||||
24,
|
|
||||||
flow.getWaterfallMinimumDrop()
|
|
||||||
);
|
|
||||||
HydrologyPlannerSettings.Source plannerUndergroundSources = new HydrologyPlannerSettings.Source(
|
HydrologyPlannerSettings.Source plannerUndergroundSources = new HydrologyPlannerSettings.Source(
|
||||||
undergroundEnabled,
|
undergroundEnabled,
|
||||||
undergroundSources.getDensity(),
|
undergroundSources.getDensity(),
|
||||||
@@ -760,17 +737,10 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
plannerUnderground,
|
plannerUnderground,
|
||||||
plannerOutlets,
|
plannerOutlets,
|
||||||
plannerGeometry,
|
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(
|
private static HydrologyPlannerSettings.Geometry geometry(
|
||||||
IrisRiverGeometryConfig geometry,
|
IrisRiverGeometryConfig geometry,
|
||||||
HydrologyPlannerSettings.ChannelShape surfaceShape
|
HydrologyPlannerSettings.ChannelShape surfaceShape
|
||||||
@@ -877,7 +847,8 @@ public final class IrisHydrologyRuntime implements AutoCloseable {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int configuredLength = Math.max(
|
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);
|
return Math.min(configuredLength, routing.getTileSize() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-17
@@ -31,12 +31,12 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rejectedRidgeBoreIsAbsentFromCoursesFootprintRendererAndLocator() {
|
public void rejectedCaveCourseIsAbsentFromCoursesFootprintRendererAndLocator() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
22L,
|
22L,
|
||||||
11L,
|
11L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -81,19 +81,19 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
assertTrue(tile.footprint().isEmpty());
|
assertTrue(tile.footprint().isEmpty());
|
||||||
assertTrue(tile.features().isEmpty());
|
assertTrue(tile.features().isEmpty());
|
||||||
assertTrue(tile.renderAt(8, 8).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(1, tile.diagnosticCandidates().size());
|
||||||
assertEquals(HydrologyCandidateRejection.CAVE_CONTAINMENT,
|
assertEquals(HydrologyCandidateRejection.CAVE_CONTAINMENT,
|
||||||
tile.diagnosticCandidates().getFirst().rejection());
|
tile.diagnosticCandidates().getFirst().rejection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generatedSurfaceConnectedCaveAroundRidgeBoreIsSealed() {
|
public void generatedSurfaceConnectedCaveAroundAnUndergroundReachIsSealed() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
42L,
|
42L,
|
||||||
41L,
|
41L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -136,7 +136,7 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
420L,
|
420L,
|
||||||
410L,
|
410L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -218,12 +218,12 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ridgeBoreAboveFinalTerrainRejectsTheWholeCourse() {
|
public void undergroundReachAboveFinalTerrainRejectsTheWholeCourse() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
52L,
|
52L,
|
||||||
51L,
|
51L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -255,12 +255,12 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void surfaceRidgeExposurePreflightChecksTheFullActionBoundaryBeforeVoxelExpansion() {
|
public void surfaceExposurePreflightChecksTheFullActionBoundaryBeforeVoxelExpansion() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
152L,
|
152L,
|
||||||
151L,
|
151L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -294,12 +294,12 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ridgeSurfaceOpeningExemptsItsCompleteSixNeighborShell() {
|
public void caveSurfaceOpeningExemptsItsCompleteSixNeighborShell() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
162L,
|
162L,
|
||||||
161L,
|
161L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -505,7 +505,7 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
192L,
|
192L,
|
||||||
191L,
|
191L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -598,12 +598,12 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void acceptedRidgeBoreRetainsItsExactPlanOnTheImmutableTile() {
|
public void acceptedCaveCourseRetainsItsExactPlanOnTheImmutableTile() {
|
||||||
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
HydrologyTerrainSample terrain = HydrologyTerrainSample.openLand(80, 0D, "parent");
|
||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
82L,
|
82L,
|
||||||
81L,
|
81L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -959,7 +959,7 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
102L,
|
102L,
|
||||||
101L,
|
101L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
@@ -1034,7 +1034,7 @@ public class HydrologyCaveCourseFilterTest {
|
|||||||
HydraulicSegment ridge = new HydraulicSegment(
|
HydraulicSegment ridge = new HydraulicSegment(
|
||||||
92L,
|
92L,
|
||||||
91L,
|
91L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
|
|||||||
+64
-129
@@ -16,6 +16,57 @@ import static org.junit.Assert.assertSame;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class HydrologyFootprintCompilerTest {
|
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
|
@Test
|
||||||
public void surfaceChannelNeverRaisesTerrainOrPublishesUnsupportedFluid() {
|
public void surfaceChannelNeverRaisesTerrainOrPublishesUnsupportedFluid() {
|
||||||
HydraulicSegment segment = new HydraulicSegment(
|
HydraulicSegment segment = new HydraulicSegment(
|
||||||
@@ -78,7 +129,7 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
RiverFootprint footprint = new HydrologyFootprintCompiler(
|
RiverFootprint footprint = new HydrologyFootprintCompiler(
|
||||||
HydrologyPlannerSettings.defaults(),
|
HydrologyPlannerSettings.defaults(),
|
||||||
terrain,
|
terrain,
|
||||||
HydrologyGeometrySampler.deterministic(1L, terrain)
|
HydrologyGeometrySampler.deterministic(terrain)
|
||||||
).compile(List.of(course));
|
).compile(List.of(course));
|
||||||
|
|
||||||
for (int x = 0; x <= 8; x++) {
|
for (int x = 0; x <= 8; x++) {
|
||||||
@@ -162,7 +213,7 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void surfaceChannelAtTerrainLevelIsReportedAsUncontained() {
|
public void surfaceChannelAtTerrainLevelHasNoContainingBank() {
|
||||||
HydraulicSegment segment = new HydraulicSegment(
|
HydraulicSegment segment = new HydraulicSegment(
|
||||||
15L,
|
15L,
|
||||||
14L,
|
14L,
|
||||||
@@ -180,7 +231,7 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
HydrologyFootprintCompiler compiler = compiler(terrain);
|
HydrologyFootprintCompiler compiler = compiler(terrain);
|
||||||
RiverFootprint footprint = compiler.compile(List.of(course));
|
RiverFootprint footprint = compiler.compile(List.of(course));
|
||||||
|
|
||||||
assertFalse(compiler.surfaceBanksContained(course));
|
assertTrue(unsupportedBankCells(footprint, 14L) > 0);
|
||||||
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
for (HydrologyColumnSample sample : footprint.columns().values()) {
|
||||||
assertTrue(sample.terrainHeight() <= sample.naturalHeight());
|
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
|
@Test
|
||||||
public void compactValidationMatchesFullRasterAcrossOverlapsOceanAndSurfaceOnlyCourses() {
|
public void compactValidationMatchesFullRasterAcrossOverlapsOceanAndSurfaceOnlyCourses() {
|
||||||
RiverCourse mixed = new RiverCourse(
|
RiverCourse mixed = new RiverCourse(
|
||||||
@@ -1389,64 +1395,6 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
int sourceDepth = source.fluidHeadY() - source.bedY();
|
int sourceDepth = source.fluidHeadY() - source.bedY();
|
||||||
int cruiseDepth = cruise.fluidHeadY() - cruise.bedY();
|
int cruiseDepth = cruise.fluidHeadY() - cruise.bedY();
|
||||||
assertTrue(Math.abs(sourceDepth - cruiseDepth) <= 1);
|
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
|
@Test
|
||||||
@@ -1519,17 +1467,17 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
RiverFootprint lowBankFootprint = lowBankCompiler.compile(List.of(course));
|
RiverFootprint lowBankFootprint = lowBankCompiler.compile(List.of(course));
|
||||||
HydrologyColumnSample lowBank = lowBankFootprint.sample(12, lowBankZ).orElseThrow();
|
HydrologyColumnSample lowBank = lowBankFootprint.sample(12, lowBankZ).orElseThrow();
|
||||||
|
|
||||||
assertTrue(highCompiler.surfaceBanksContained(course));
|
assertEquals(0, unsupportedBankCells(highFootprint, 528L));
|
||||||
assertEquals(70, lowBank.naturalHeight());
|
assertEquals(70, lowBank.naturalHeight());
|
||||||
assertEquals(70, lowBank.terrainHeight());
|
assertEquals(70, lowBank.terrainHeight());
|
||||||
assertFalse(lowBankCompiler.surfaceBanksContained(course));
|
assertTrue(unsupportedBankCells(lowBankFootprint, 528L) > 0);
|
||||||
for (HydrologyColumnSample sample : lowBankFootprint.columns().values()) {
|
for (HydrologyColumnSample sample : lowBankFootprint.columns().values()) {
|
||||||
assertTrue(sample.terrainHeight() <= sample.naturalHeight());
|
assertTrue(sample.terrainHeight() <= sample.naturalHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void surfaceIncisionContainmentUsesFinalTerrainHeight() {
|
public void publishedSurfaceChannelStaysWithinTheConfiguredIncision() {
|
||||||
HydraulicSegment channel = new HydraulicSegment(
|
HydraulicSegment channel = new HydraulicSegment(
|
||||||
529L,
|
529L,
|
||||||
528L,
|
528L,
|
||||||
@@ -1543,28 +1491,16 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
List.of(new HydrologyPoint(0, 70, 0), new HydrologyPoint(24, 70, 0))
|
List.of(new HydrologyPoint(0, 70, 0), new HydrologyPoint(24, 70, 0))
|
||||||
);
|
);
|
||||||
RiverCourse course = course(528L, RiverCourseType.SURFACE, channel);
|
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.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 footprint = compiler.compile(List.of(course));
|
||||||
RiverFootprint excessiveFootprint = excessive.compile(List.of(course));
|
|
||||||
assertFalse(
|
assertTrue(
|
||||||
"center=" + excessiveFootprint.sample(12, 0),
|
"center=" + footprint.sample(12, 0),
|
||||||
excessive.surfaceIncisionContained(course)
|
maximumSurfaceCut(footprint, 528L)
|
||||||
|
<= HydrologyPlannerSettings.defaults().surface().maximumIncision()
|
||||||
);
|
);
|
||||||
assertFalse(excessive.surfaceIncisionContained(course, excessiveFootprint));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1592,7 +1528,6 @@ public class HydrologyFootprintCompilerTest {
|
|||||||
HydrologyFootprintCompiler compiler = compiler(terrain);
|
HydrologyFootprintCompiler compiler = compiler(terrain);
|
||||||
|
|
||||||
assertTrue(compiler.compile(List.of(course)).isEmpty());
|
assertTrue(compiler.compile(List.of(course)).isEmpty());
|
||||||
assertFalse(compiler.surfaceBanksContained(course));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public class HydrologyModelTest {
|
|||||||
HydraulicSegment containedLip = new HydraulicSegment(
|
HydraulicSegment containedLip = new HydraulicSegment(
|
||||||
4L,
|
4L,
|
||||||
9L,
|
9L,
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.SURFACE_POOL,
|
||||||
80,
|
80,
|
||||||
80,
|
80,
|
||||||
4,
|
4,
|
||||||
|
|||||||
+2
-19
@@ -252,8 +252,7 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(256, 16, 4, 1_089, 256,
|
new HydrologyPlannerSettings.Routing(256, 16, 1_089, 256, 16, 8, 0.5D, 12D, 0.5D, 0.2D),
|
||||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.2D),
|
|
||||||
new HydrologyPlannerSettings.Surface(
|
new HydrologyPlannerSettings.Surface(
|
||||||
true,
|
true,
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
@@ -261,18 +260,10 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
|||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
5,
|
5,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
12,
|
12,
|
||||||
1.5D,
|
1.5D,
|
||||||
4,
|
|
||||||
10,
|
|
||||||
true,
|
|
||||||
96,
|
|
||||||
10
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
true,
|
true,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
@@ -343,16 +334,8 @@ public class HydrologyPlannerCrossTileCaveAdmissionIntegrationTest {
|
|||||||
baseSurface.maximumWidth(),
|
baseSurface.maximumWidth(),
|
||||||
baseSurface.minimumDepth(),
|
baseSurface.minimumDepth(),
|
||||||
baseSurface.maximumDepth(),
|
baseSurface.maximumDepth(),
|
||||||
baseSurface.minimumSurfaceInset(),
|
|
||||||
baseSurface.maximumSurfaceInset(),
|
|
||||||
64,
|
64,
|
||||||
baseSurface.shoreWidth(),
|
baseSurface.shoreWidth(),
|
||||||
baseSurface.minimumTerrainBlendWidth(),
|
|
||||||
baseSurface.maximumTerrainBlendWidth(),
|
|
||||||
baseSurface.ridgeTunnelsEnabled(),
|
|
||||||
baseSurface.maximumRidgeTunnelLength(),
|
|
||||||
baseSurface.ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
base.hydraulics(),
|
base.hydraulics(),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
|
|||||||
+9
-28
@@ -639,33 +639,31 @@ public class HydrologyPlannerGlobalInvariantTest {
|
|||||||
boolean undergroundEnabled,
|
boolean undergroundEnabled,
|
||||||
List<HydrologyPlannerSettings.DeepFluid> deepFluids
|
List<HydrologyPlannerSettings.DeepFluid> deepFluids
|
||||||
) {
|
) {
|
||||||
return settingsWithRefinement(
|
return plannerSettings(
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
surfaceEnabled,
|
surfaceEnabled,
|
||||||
undergroundEnabled,
|
undergroundEnabled,
|
||||||
deepFluids,
|
deepFluids
|
||||||
4
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HydrologyPlannerSettings settingsWithRefinement(
|
private HydrologyPlannerSettings plannerSettings(
|
||||||
HydrologyPlannerSettings.Source surfaceSources,
|
HydrologyPlannerSettings.Source surfaceSources,
|
||||||
HydrologyPlannerSettings.Source undergroundSources,
|
HydrologyPlannerSettings.Source undergroundSources,
|
||||||
boolean surfaceEnabled,
|
boolean surfaceEnabled,
|
||||||
boolean undergroundEnabled,
|
boolean undergroundEnabled,
|
||||||
List<HydrologyPlannerSettings.DeepFluid> deepFluids,
|
List<HydrologyPlannerSettings.DeepFluid> deepFluids
|
||||||
int refinementSpacing
|
|
||||||
) {
|
) {
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(
|
new HydrologyPlannerSettings.Routing(
|
||||||
TILE_SIZE,
|
TILE_SIZE,
|
||||||
16,
|
16,
|
||||||
refinementSpacing,
|
|
||||||
512,
|
512,
|
||||||
256,
|
256,
|
||||||
new HydrologyPlannerSettings.Branching(16, 8),
|
16,
|
||||||
|
8,
|
||||||
0.5D,
|
0.5D,
|
||||||
12D,
|
12D,
|
||||||
0.5D,
|
0.5D,
|
||||||
@@ -678,18 +676,10 @@ public class HydrologyPlannerGlobalInvariantTest {
|
|||||||
4,
|
4,
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
128,
|
128,
|
||||||
1D,
|
1D,
|
||||||
1,
|
|
||||||
2,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
undergroundEnabled,
|
undergroundEnabled,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
@@ -724,13 +714,12 @@ public class HydrologyPlannerGlobalInvariantTest {
|
|||||||
boolean surfaceEnabled,
|
boolean surfaceEnabled,
|
||||||
boolean undergroundEnabled
|
boolean undergroundEnabled
|
||||||
) {
|
) {
|
||||||
HydrologyPlannerSettings base = settingsWithRefinement(
|
HydrologyPlannerSettings base = plannerSettings(
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
surfaceEnabled,
|
surfaceEnabled,
|
||||||
undergroundEnabled,
|
undergroundEnabled,
|
||||||
List.of(),
|
List.of()
|
||||||
8
|
|
||||||
);
|
);
|
||||||
HydrologyPlannerSettings.Surface surface = base.surface();
|
HydrologyPlannerSettings.Surface surface = base.surface();
|
||||||
HydrologyPlannerSettings.Underground underground = base.underground();
|
HydrologyPlannerSettings.Underground underground = base.underground();
|
||||||
@@ -744,16 +733,8 @@ public class HydrologyPlannerGlobalInvariantTest {
|
|||||||
surface.minimumWidth(),
|
surface.minimumWidth(),
|
||||||
surface.minimumDepth(),
|
surface.minimumDepth(),
|
||||||
surface.maximumDepth(),
|
surface.maximumDepth(),
|
||||||
surface.minimumSurfaceInset(),
|
|
||||||
surface.maximumSurfaceInset(),
|
|
||||||
surface.maximumIncision(),
|
surface.maximumIncision(),
|
||||||
surface.shoreWidth(),
|
surface.shoreWidth(),
|
||||||
surface.minimumTerrainBlendWidth(),
|
|
||||||
surface.maximumTerrainBlendWidth(),
|
|
||||||
surface.ridgeTunnelsEnabled(),
|
|
||||||
surface.maximumRidgeTunnelLength(),
|
|
||||||
surface.ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
base.hydraulics(),
|
base.hydraulics(),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
|
|||||||
+3
-3
@@ -38,7 +38,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
|||||||
settings,
|
settings,
|
||||||
detailSampler,
|
detailSampler,
|
||||||
routingSampler,
|
routingSampler,
|
||||||
HydrologyGeometrySampler.deterministic(17L, detailSampler),
|
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||||
-4096,
|
-4096,
|
||||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||||
);
|
);
|
||||||
@@ -70,7 +70,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
|||||||
settings,
|
settings,
|
||||||
detailSampler,
|
detailSampler,
|
||||||
routingSampler,
|
routingSampler,
|
||||||
HydrologyGeometrySampler.deterministic(19L, detailSampler),
|
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||||
-4096,
|
-4096,
|
||||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||||
);
|
);
|
||||||
@@ -108,7 +108,7 @@ public class HydrologyPlannerRoutingSamplerTest {
|
|||||||
settings,
|
settings,
|
||||||
detailSampler,
|
detailSampler,
|
||||||
routingSampler,
|
routingSampler,
|
||||||
HydrologyGeometrySampler.deterministic(23L, detailSampler),
|
HydrologyGeometrySampler.deterministic(detailSampler),
|
||||||
-4096,
|
-4096,
|
||||||
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
footprint -> new HydrologyTerrainCaveVoxelView(detailSampler, settings.seaLevel(), -4096, 4096)
|
||||||
);
|
);
|
||||||
|
|||||||
+18
-32
@@ -11,11 +11,19 @@ import static org.junit.Assert.assertTrue;
|
|||||||
|
|
||||||
public class HydrologyPlannerSettingsTest {
|
public class HydrologyPlannerSettingsTest {
|
||||||
@Test
|
@Test
|
||||||
public void branchingUsesIndependentSurfaceAndUndergroundCourseFloors() {
|
public void routingUsesIndependentSurfaceAndUndergroundCourseFloors() {
|
||||||
HydrologyPlannerSettings.Branching branching = new HydrologyPlannerSettings.Branching(384, 192);
|
HydrologyPlannerSettings.Routing routing = HydrologyPlannerSettings.defaults().routing();
|
||||||
|
|
||||||
assertEquals(384, branching.minimumCourseLength(true));
|
assertEquals(384, routing.minimumCourseLength(true));
|
||||||
assertEquals(192, branching.minimumCourseLength(false));
|
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
|
@Test
|
||||||
@@ -63,10 +71,10 @@ public class HydrologyPlannerSettingsTest {
|
|||||||
HydrologyPlannerSettings.Routing routing = new HydrologyPlannerSettings.Routing(
|
HydrologyPlannerSettings.Routing routing = new HydrologyPlannerSettings.Routing(
|
||||||
512,
|
512,
|
||||||
512,
|
512,
|
||||||
64,
|
|
||||||
4,
|
4,
|
||||||
256,
|
256,
|
||||||
new HydrologyPlannerSettings.Branching(0, 0),
|
0,
|
||||||
|
0,
|
||||||
0D,
|
0D,
|
||||||
0D,
|
0D,
|
||||||
0D,
|
0D,
|
||||||
@@ -80,25 +88,10 @@ public class HydrologyPlannerSettingsTest {
|
|||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
0,
|
||||||
1D,
|
1D,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults());
|
HydrologyPlannerSettings.Banks.defaults());
|
||||||
HydrologyPlannerSettings.Hydraulics hydraulics = new HydrologyPlannerSettings.Hydraulics(
|
HydrologyPlannerSettings.Hydraulics hydraulics = new HydrologyPlannerSettings.Hydraulics(1);
|
||||||
8,
|
|
||||||
8,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
HydrologyPlannerSettings.Grotto grotto = new HydrologyPlannerSettings.Grotto(true, 1, 1, 1, 1);
|
HydrologyPlannerSettings.Grotto grotto = new HydrologyPlannerSettings.Grotto(true, 1, 1, 1, 1);
|
||||||
HydrologyPlannerSettings.Outlets outlets = new HydrologyPlannerSettings.Outlets(
|
HydrologyPlannerSettings.Outlets outlets = new HydrologyPlannerSettings.Outlets(
|
||||||
true,
|
true,
|
||||||
@@ -168,20 +161,13 @@ public class HydrologyPlannerSettingsTest {
|
|||||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Surface(
|
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Surface(
|
||||||
true,
|
true,
|
||||||
new HydrologyPlannerSettings.Source(true, 1D, 0, 0, 1, 0),
|
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));
|
null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inconsistentHydraulicThresholdsAreRejected() {
|
public void nonPositiveWaterfallThresholdsAreRejected() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Hydraulics(
|
assertThrows(IllegalArgumentException.class, () -> new HydrologyPlannerSettings.Hydraulics(0));
|
||||||
8,
|
|
||||||
16,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -522,35 +522,14 @@ public class HydrologyPlannerTest {
|
|||||||
assertFalse("diagnostics=" + tile.diagnosticCandidates(), surfaceCourses(tile).isEmpty());
|
assertFalse("diagnostics=" + tile.diagnosticCandidates(), surfaceCourses(tile).isEmpty());
|
||||||
boolean aggregateTransition = false;
|
boolean aggregateTransition = false;
|
||||||
for (RiverCourse course : surfaceCourses(tile)) {
|
for (RiverCourse course : surfaceCourses(tile)) {
|
||||||
double recovery = Double.POSITIVE_INFINITY;
|
|
||||||
boolean transitionActive = false;
|
|
||||||
for (HydraulicSegment segment : course.segments()) {
|
for (HydraulicSegment segment : course.segments()) {
|
||||||
boolean surfaceDrop = segment.type().isSurface() && segment.type().isDrop();
|
if (segment.drop() < settings.hydraulics().waterfallMinimumDrop()) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (segment.type() == HydrologyFeatureType.UNDERGROUND_DROP
|
if (segment.type() == HydrologyFeatureType.WATERFALL
|
||||||
&& segment.drop() >= settings.hydraulics().waterfallMinimumDrop()) {
|
|| segment.type() == HydrologyFeatureType.UNDERGROUND_DROP) {
|
||||||
aggregateTransition = true;
|
aggregateTransition = true;
|
||||||
}
|
}
|
||||||
if (transitionActive && segment.receivingPool()) {
|
|
||||||
transitionActive = false;
|
|
||||||
} else if (!transitionActive && Double.isFinite(recovery)) {
|
|
||||||
recovery += segmentLength(segment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue("courses=" + surfaceCourses(tile), aggregateTransition);
|
assertTrue("courses=" + surfaceCourses(tile), aggregateTransition);
|
||||||
@@ -597,10 +576,8 @@ public class HydrologyPlannerTest {
|
|||||||
new HydrologyPlannerSettings.Routing(
|
new HydrologyPlannerSettings.Routing(
|
||||||
routing.tileSize(),
|
routing.tileSize(),
|
||||||
routing.sampleSpacing(),
|
routing.sampleSpacing(),
|
||||||
routing.refinementSpacing(),
|
|
||||||
routing.maximumRouteNodes(),
|
routing.maximumRouteNodes(),
|
||||||
routing.maximumRouteLength(),
|
routing.maximumRouteLength(), 96, 0,
|
||||||
new HydrologyPlannerSettings.Branching(96, 0),
|
|
||||||
routing.valleyPreference(),
|
routing.valleyPreference(),
|
||||||
routing.uphillPenalty(),
|
routing.uphillPenalty(),
|
||||||
routing.slopePenalty(),
|
routing.slopePenalty(),
|
||||||
@@ -792,7 +769,7 @@ public class HydrologyPlannerTest {
|
|||||||
333L,
|
333L,
|
||||||
settings,
|
settings,
|
||||||
coast,
|
coast,
|
||||||
HydrologyGeometrySampler.deterministic(333L, coast),
|
HydrologyGeometrySampler.deterministic(coast),
|
||||||
-4096,
|
-4096,
|
||||||
footprint -> solidCaveView()
|
footprint -> solidCaveView()
|
||||||
).plan(TILE);
|
).plan(TILE);
|
||||||
@@ -1134,16 +1111,8 @@ public class HydrologyPlannerTest {
|
|||||||
base.surface().maximumWidth(),
|
base.surface().maximumWidth(),
|
||||||
base.surface().minimumDepth(),
|
base.surface().minimumDepth(),
|
||||||
8,
|
8,
|
||||||
base.surface().minimumSurfaceInset(),
|
|
||||||
base.surface().maximumSurfaceInset(),
|
|
||||||
128,
|
128,
|
||||||
base.surface().shoreWidth(),
|
base.surface().shoreWidth(),
|
||||||
base.surface().minimumTerrainBlendWidth(),
|
|
||||||
base.surface().maximumTerrainBlendWidth(),
|
|
||||||
base.surface().ridgeTunnelsEnabled(),
|
|
||||||
base.surface().maximumRidgeTunnelLength(),
|
|
||||||
base.surface().ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults());
|
HydrologyPlannerSettings.Banks.defaults());
|
||||||
HydrologyPlannerSettings shaped = new HydrologyPlannerSettings(
|
HydrologyPlannerSettings shaped = new HydrologyPlannerSettings(
|
||||||
base.seaLevel(),
|
base.seaLevel(),
|
||||||
@@ -1432,16 +1401,8 @@ public class HydrologyPlannerTest {
|
|||||||
surface.maximumWidth(),
|
surface.maximumWidth(),
|
||||||
surface.minimumDepth(),
|
surface.minimumDepth(),
|
||||||
surface.maximumDepth(),
|
surface.maximumDepth(),
|
||||||
surface.minimumSurfaceInset(),
|
|
||||||
surface.maximumSurfaceInset(),
|
|
||||||
surface.maximumIncision(),
|
surface.maximumIncision(),
|
||||||
surface.shoreWidth(),
|
surface.shoreWidth(),
|
||||||
surface.minimumTerrainBlendWidth(),
|
|
||||||
surface.maximumTerrainBlendWidth(),
|
|
||||||
surface.ridgeTunnelsEnabled(),
|
|
||||||
32,
|
|
||||||
surface.ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
base.hydraulics(),
|
base.hydraulics(),
|
||||||
base.underground(),
|
base.underground(),
|
||||||
@@ -1772,8 +1733,7 @@ public class HydrologyPlannerTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(128, 16, 4, 512, 256,
|
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 0, 0, 0.5D, 12D, 0.5D, 0.1D),
|
||||||
new HydrologyPlannerSettings.Branching(0, 0), 0.5D, 12D, 0.5D, 0.1D),
|
|
||||||
new HydrologyPlannerSettings.Surface(
|
new HydrologyPlannerSettings.Surface(
|
||||||
surfaceDensity > 0D || surfaceSources.maximumPerTile() > 0,
|
surfaceDensity > 0D || surfaceSources.maximumPerTile() > 0,
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
@@ -1781,18 +1741,10 @@ public class HydrologyPlannerTest {
|
|||||||
18,
|
18,
|
||||||
2,
|
2,
|
||||||
4,
|
4,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
10,
|
10,
|
||||||
1.5D,
|
1.5D,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
true,
|
|
||||||
64,
|
|
||||||
8
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
undergroundDensity > 0D,
|
undergroundDensity > 0D,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
@@ -1842,10 +1794,8 @@ public class HydrologyPlannerTest {
|
|||||||
new HydrologyPlannerSettings.Routing(
|
new HydrologyPlannerSettings.Routing(
|
||||||
512,
|
512,
|
||||||
64,
|
64,
|
||||||
4,
|
|
||||||
1024,
|
1024,
|
||||||
2048,
|
2048, 64, 32,
|
||||||
new HydrologyPlannerSettings.Branching(64, 32),
|
|
||||||
1.5D,
|
1.5D,
|
||||||
24D,
|
24D,
|
||||||
2D,
|
2D,
|
||||||
@@ -1858,18 +1808,10 @@ public class HydrologyPlannerTest {
|
|||||||
surface.maximumWidth(),
|
surface.maximumWidth(),
|
||||||
surface.minimumDepth(),
|
surface.minimumDepth(),
|
||||||
surface.maximumDepth(),
|
surface.maximumDepth(),
|
||||||
surface.minimumSurfaceInset(),
|
|
||||||
surface.maximumSurfaceInset(),
|
|
||||||
96,
|
96,
|
||||||
surface.shoreWidth(),
|
surface.shoreWidth(),
|
||||||
surface.minimumTerrainBlendWidth(),
|
|
||||||
surface.maximumTerrainBlendWidth(),
|
|
||||||
surface.ridgeTunnelsEnabled(),
|
|
||||||
192,
|
|
||||||
surface.ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 4, 12, 5),
|
new HydrologyPlannerSettings.Hydraulics(5),
|
||||||
base.underground(),
|
base.underground(),
|
||||||
new HydrologyPlannerSettings.Outlets(
|
new HydrologyPlannerSettings.Outlets(
|
||||||
true,
|
true,
|
||||||
@@ -2172,16 +2114,8 @@ public class HydrologyPlannerTest {
|
|||||||
surface.maximumWidth(),
|
surface.maximumWidth(),
|
||||||
surface.minimumDepth(),
|
surface.minimumDepth(),
|
||||||
surface.maximumDepth(),
|
surface.maximumDepth(),
|
||||||
surface.minimumSurfaceInset(),
|
|
||||||
surface.maximumSurfaceInset(),
|
|
||||||
surface.maximumIncision(),
|
surface.maximumIncision(),
|
||||||
surface.shoreWidth(),
|
surface.shoreWidth(),
|
||||||
surface.minimumTerrainBlendWidth(),
|
|
||||||
surface.maximumTerrainBlendWidth(),
|
|
||||||
surface.ridgeTunnelsEnabled(),
|
|
||||||
surface.maximumRidgeTunnelLength(),
|
|
||||||
surface.ridgeTunnelHeadroom()
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
settings.hydraulics(),
|
settings.hydraulics(),
|
||||||
settings.underground(),
|
settings.underground(),
|
||||||
|
|||||||
+2
-11
@@ -192,8 +192,7 @@ public class HydrologyStyledGeometryTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(128, 16, 4, 512, 256,
|
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
|
||||||
new HydrologyPlannerSettings.Surface(
|
new HydrologyPlannerSettings.Surface(
|
||||||
surfaceDensity > 0D,
|
surfaceDensity > 0D,
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
@@ -201,18 +200,10 @@ public class HydrologyStyledGeometryTest {
|
|||||||
18,
|
18,
|
||||||
2,
|
2,
|
||||||
4,
|
4,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
10,
|
10,
|
||||||
1.5D,
|
1.5D,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
true,
|
|
||||||
96,
|
|
||||||
8
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
undergroundDensity > 0D,
|
undergroundDensity > 0D,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
|
|||||||
@@ -243,10 +243,10 @@ public class HydrologyTileCacheTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 64,
|
new HydrologyPlannerSettings.Routing(64, 16, 128, 64, 0, 0, 0D, 0D, 0D, 0D),
|
||||||
new HydrologyPlannerSettings.Branching(0, 0), 0D, 0D, 0D, 0D),
|
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 4, 1D,
|
||||||
new HydrologyPlannerSettings.Surface(false, disabled, 2, 4, 1, 2, 2, 4, 4, 1D, 2, 4, false, 0, 0, HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
new HydrologyPlannerSettings.Hydraulics(3),
|
||||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||||
new HydrologyPlannerSettings.Outlets(
|
new HydrologyPlannerSettings.Outlets(
|
||||||
false,
|
false,
|
||||||
@@ -282,10 +282,9 @@ public class HydrologyTileCacheTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(64, 16, 4, 128, 96,
|
new HydrologyPlannerSettings.Routing(64, 16, 128, 96, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 20, 1.5D, tileBoundedBanks()),
|
||||||
new HydrologyPlannerSettings.Surface(true, surfaceSources, 4, 8, 2, 3, 4, 8, 20, 1.5D, 2, 4, true, 96, 8, tileBoundedBanks()),
|
new HydrologyPlannerSettings.Hydraulics(3),
|
||||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 2, 8, 3),
|
|
||||||
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
new HydrologyPlannerSettings.Underground(false, disabled, -32, 32, 2, 4, 1, 2, 3, 4, false),
|
||||||
new HydrologyPlannerSettings.Outlets(
|
new HydrologyPlannerSettings.Outlets(
|
||||||
true,
|
true,
|
||||||
|
|||||||
+4
-4
@@ -114,14 +114,14 @@ public class IrisHydrologyRuntimeSettingsTest {
|
|||||||
assertEquals(8, settings.hydraulics().waterfallMinimumDrop());
|
assertEquals(8, settings.hydraulics().waterfallMinimumDrop());
|
||||||
assertEquals(96, settings.outlets().mouthLevelingDistance());
|
assertEquals(96, settings.outlets().mouthLevelingDistance());
|
||||||
assertEquals(4, settings.routing().refinementSpacing());
|
assertEquals(4, settings.routing().refinementSpacing());
|
||||||
assertEquals(500, settings.routing().branching().minimumSurfaceCourseLength());
|
assertEquals(500, settings.routing().minimumSurfaceCourseLength());
|
||||||
assertEquals(250, settings.routing().branching().minimumUndergroundCourseLength());
|
assertEquals(250, settings.routing().minimumUndergroundCourseLength());
|
||||||
assertEquals(2.5D, settings.routing().valleyPreference(), 0D);
|
assertEquals(2.5D, settings.routing().valleyPreference(), 0D);
|
||||||
assertEquals(30D, settings.routing().uphillPenalty(), 0D);
|
assertEquals(30D, settings.routing().uphillPenalty(), 0D);
|
||||||
assertEquals(3D, settings.routing().slopePenalty(), 0D);
|
assertEquals(3D, settings.routing().slopePenalty(), 0D);
|
||||||
assertEquals(0.4D, settings.routing().confluenceAttraction(), 0D);
|
assertEquals(0.4D, settings.routing().confluenceAttraction(), 0D);
|
||||||
assertEquals(2, IrisHydrologyRuntime.refinementSpacing(50));
|
assertEquals(2, HydrologyPlannerSettings.Routing.refinementSpacing(50));
|
||||||
assertEquals(1, IrisHydrologyRuntime.refinementSpacing(45));
|
assertEquals(1, HydrologyPlannerSettings.Routing.refinementSpacing(45));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+1
-1
@@ -172,7 +172,7 @@ public class ErosionFieldCompilerTest {
|
|||||||
return new HydrologyPlannerSettings.Surface(
|
return new HydrologyPlannerSettings.Surface(
|
||||||
true,
|
true,
|
||||||
defaults.sources(),
|
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)
|
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
|
@Test
|
||||||
public void sameCourseSurfaceFluidOwnsAChangedRidgeBoundary() {
|
public void sameCourseSurfaceFluidOwnsAChangedCaveBoundary() {
|
||||||
long courseId = 33L;
|
long courseId = 33L;
|
||||||
HydrologyColumnLayer ridge = layerForCourse(
|
HydrologyColumnLayer ridge = layerForCourse(
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
34L,
|
34L,
|
||||||
courseId,
|
courseId,
|
||||||
10L,
|
10L,
|
||||||
@@ -1115,7 +1115,7 @@ public class MantleHydrologyComponentTest {
|
|||||||
"river"
|
"river"
|
||||||
);
|
);
|
||||||
HydrologyColumnLayer cave = layer(
|
HydrologyColumnLayer cave = layer(
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
72L,
|
72L,
|
||||||
15L,
|
15L,
|
||||||
20,
|
20,
|
||||||
@@ -1158,7 +1158,7 @@ public class MantleHydrologyComponentTest {
|
|||||||
"river"
|
"river"
|
||||||
);
|
);
|
||||||
HydrologyColumnLayer cave = layer(
|
HydrologyColumnLayer cave = layer(
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
72L,
|
72L,
|
||||||
15L,
|
15L,
|
||||||
20,
|
20,
|
||||||
@@ -1192,7 +1192,7 @@ public class MantleHydrologyComponentTest {
|
|||||||
"river"
|
"river"
|
||||||
);
|
);
|
||||||
HydrologyColumnLayer cave = layer(
|
HydrologyColumnLayer cave = layer(
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
74L,
|
74L,
|
||||||
17L,
|
17L,
|
||||||
20,
|
20,
|
||||||
@@ -1245,7 +1245,7 @@ public class MantleHydrologyComponentTest {
|
|||||||
"lava"
|
"lava"
|
||||||
);
|
);
|
||||||
HydrologyColumnLayer cave = layer(
|
HydrologyColumnLayer cave = layer(
|
||||||
HydrologyFeatureType.RIDGE_BORE,
|
HydrologyFeatureType.UNDERGROUND_POOL,
|
||||||
76L,
|
76L,
|
||||||
19L,
|
19L,
|
||||||
17,
|
17,
|
||||||
@@ -1530,8 +1530,7 @@ public class MantleHydrologyComponentTest {
|
|||||||
);
|
);
|
||||||
return new HydrologyPlannerSettings(
|
return new HydrologyPlannerSettings(
|
||||||
63,
|
63,
|
||||||
new HydrologyPlannerSettings.Routing(128, 16, 8, 512, 256,
|
new HydrologyPlannerSettings.Routing(128, 16, 512, 256, 16, 8, 0.5D, 12D, 0.5D, 0.1D),
|
||||||
new HydrologyPlannerSettings.Branching(16, 8), 0.5D, 12D, 0.5D, 0.1D),
|
|
||||||
new HydrologyPlannerSettings.Surface(
|
new HydrologyPlannerSettings.Surface(
|
||||||
true,
|
true,
|
||||||
surfaceSources,
|
surfaceSources,
|
||||||
@@ -1539,18 +1538,10 @@ public class MantleHydrologyComponentTest {
|
|||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
128,
|
128,
|
||||||
0D,
|
0D,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()),
|
HydrologyPlannerSettings.Banks.defaults()),
|
||||||
new HydrologyPlannerSettings.Hydraulics(8, 16, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
false,
|
false,
|
||||||
disabledSources,
|
disabledSources,
|
||||||
|
|||||||
@@ -1576,7 +1576,7 @@ public final class HydrologyPackProbe {
|
|||||||
publishedMorphology.observe(
|
publishedMorphology.observe(
|
||||||
tile,
|
tile,
|
||||||
settings.surface().minimumWidth(),
|
settings.surface().minimumWidth(),
|
||||||
settings.routing().branching().minimumSurfaceCourseLength()
|
settings.routing().minimumSurfaceCourseLength()
|
||||||
);
|
);
|
||||||
HydrologyPlannerSettings.Routing routing = settings.routing();
|
HydrologyPlannerSettings.Routing routing = settings.routing();
|
||||||
int sampleSpacing = routing.sampleSpacing();
|
int sampleSpacing = routing.sampleSpacing();
|
||||||
@@ -1704,7 +1704,7 @@ public final class HydrologyPackProbe {
|
|||||||
List<ChannelIncision> incisions = channelIncisions(
|
List<ChannelIncision> incisions = channelIncisions(
|
||||||
tile.footprint(),
|
tile.footprint(),
|
||||||
scopedCourseIds,
|
scopedCourseIds,
|
||||||
settings.surface().minimumSurfaceInset(),
|
settings.surface().banks().inset(),
|
||||||
settings.surface().maximumIncision()
|
settings.surface().maximumIncision()
|
||||||
);
|
);
|
||||||
for (ChannelIncision incision : incisions) {
|
for (ChannelIncision incision : incisions) {
|
||||||
|
|||||||
@@ -220,10 +220,10 @@ public final class HydrologyPlannerProbe {
|
|||||||
new HydrologyPlannerSettings.Routing(
|
new HydrologyPlannerSettings.Routing(
|
||||||
128,
|
128,
|
||||||
16,
|
16,
|
||||||
4,
|
|
||||||
512,
|
512,
|
||||||
256,
|
256,
|
||||||
new HydrologyPlannerSettings.Branching(32, 16),
|
32,
|
||||||
|
16,
|
||||||
0.5D,
|
0.5D,
|
||||||
12D,
|
12D,
|
||||||
0.5D,
|
0.5D,
|
||||||
@@ -236,18 +236,11 @@ public final class HydrologyPlannerProbe {
|
|||||||
18,
|
18,
|
||||||
2,
|
2,
|
||||||
4,
|
4,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
10,
|
10,
|
||||||
1.5D,
|
1.5D,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
true,
|
|
||||||
96,
|
|
||||||
8,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()
|
HydrologyPlannerSettings.Banks.defaults()
|
||||||
),
|
),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 28, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
undergroundDensity > 0D,
|
undergroundDensity > 0D,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
@@ -438,10 +431,10 @@ public final class HydrologyPlannerProbe {
|
|||||||
new HydrologyPlannerSettings.Routing(
|
new HydrologyPlannerSettings.Routing(
|
||||||
256,
|
256,
|
||||||
16,
|
16,
|
||||||
4,
|
|
||||||
1_089,
|
1_089,
|
||||||
256,
|
256,
|
||||||
new HydrologyPlannerSettings.Branching(32, 16),
|
32,
|
||||||
|
16,
|
||||||
0.5D,
|
0.5D,
|
||||||
12D,
|
12D,
|
||||||
0.5D,
|
0.5D,
|
||||||
@@ -454,18 +447,11 @@ public final class HydrologyPlannerProbe {
|
|||||||
20,
|
20,
|
||||||
2,
|
2,
|
||||||
5,
|
5,
|
||||||
4,
|
|
||||||
8,
|
|
||||||
12,
|
12,
|
||||||
1.5D,
|
1.5D,
|
||||||
4,
|
|
||||||
10,
|
|
||||||
true,
|
|
||||||
96,
|
|
||||||
10,
|
|
||||||
HydrologyPlannerSettings.Banks.defaults()
|
HydrologyPlannerSettings.Banks.defaults()
|
||||||
),
|
),
|
||||||
new HydrologyPlannerSettings.Hydraulics(12, 40, 1, 3, 8, 4),
|
new HydrologyPlannerSettings.Hydraulics(4),
|
||||||
new HydrologyPlannerSettings.Underground(
|
new HydrologyPlannerSettings.Underground(
|
||||||
true,
|
true,
|
||||||
undergroundSources,
|
undergroundSources,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public final class HydrologyPlannerProbeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requiredCoverageExcludesTheRemovedRidgeBore() {
|
public void requiredCoverageExcludesTheUnproducedRidgeBore() {
|
||||||
assertFalse(HydrologyPlannerProbe.REQUIRED_FEATURE_TYPES.contains(HydrologyFeatureType.RIDGE_BORE));
|
assertFalse(HydrologyPlannerProbe.REQUIRED_FEATURE_TYPES.contains(HydrologyFeatureType.RIDGE_BORE));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
EnumSet.complementOf(EnumSet.of(HydrologyFeatureType.RIDGE_BORE)),
|
EnumSet.complementOf(EnumSet.of(HydrologyFeatureType.RIDGE_BORE)),
|
||||||
|
|||||||
Reference in new issue
Block a user