wip(assembler): round L33 -- SurfaceWorld can be an upper strate; FloorProfileBlend measures seams

Route planning for an upper SurfaceWorld failed on long candidate chords over steep relief; chords
are now capped to the arrival/departure radii on an 8 m centre grid with an origin-proximity cost
(21.5 m walk, about 4 deg). The departure passage starts at the SW ground and tunnels down through rock.
FI -> SW -> TN fixture: all 4 styles pass every passage audit on both compilers. FloorProfileBlend
now checks endpoint height/tangent seams (step and tangent-step negative controls detected). Owner
world hashes unchanged; 30/30 determinism; cost within noise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-21 22:30:36 +02:00
1 parent d0158c6019
commit b7a47bef95
17 files changed
+1116 -32

No files matched your search

+9 -3
View File
@@ -820,7 +820,9 @@ namespace StandaloneStreamBenchmark
const auto& b=passage.controlPoints[i];
const double dx=qToMetres(b.positionSubvoxels[0]-a.positionSubvoxels[0]);
const double dy=qToMetres(b.positionSubvoxels[1]-a.positionSubvoxels[1]);
const double dz=qToMetres(b.positionSubvoxels[2]-a.positionSubvoxels[2]);
const double floorA=qToMetres(a.positionSubvoxels[2]-a.radiusSubvoxels)+1.13;
const double floorB=qToMetres(b.positionSubvoxels[2]-b.radiusSubvoxels)+1.13;
const double dz=floorB-floorA;
const double horizontal=std::hypot(dx,dy);
if(horizontal>1.0e-6&&std::abs(dz)/horizontal
<std::tan(0.5*3.14159265358979323846/180.0))
@@ -1313,6 +1315,9 @@ namespace StandaloneStreamBenchmark
++audit.wallSections;
audit.wallFailures+=!wallSolid;
crossingWallFailures+=!wallSolid;
if(!wallSolid&&crossingWallFailures<=8)
std::printf("[PassageRockColumnWallProbe] id=%s segment=%zu xyz_m=(%.3f,%.3f,%.3f) axis_m=(%.3f,%.3f) centerline_radius_m=%.3f bore_radius_m=%.3f wall_probe_radius_m=%.3f\n",
passage.stableId.c_str(),segment,x,y,z,axisX,axisY,radial,radius,wallRadius);
}
double crossingMinimumSurfaceRadius=std::numeric_limits<double>::infinity();
double crossingMaximumSurfaceRadius=0.0;
@@ -1378,12 +1383,13 @@ namespace StandaloneStreamBenchmark
&&crossingWallFailures==0&&std::isfinite(measuredWall)
&&measuredWall>=1.50&&crossingSurfaceRelief>=0.20;
audit.passed&=columnPass;
std::printf("[PassageRockColumnAudit] id=%s segments=%zu..%zu span_m=%.3f axis_m=(%.3f,%.3f) connected=%d/2 route_support=%llu/%llu wall_margin_m=%.3f threshold_m=1.500 radii_m=%.3f..%.3f relief_p2p_m=%.3f nominal_radius_m=%.3f status=%s\n",
std::printf("[PassageRockColumnAudit] id=%s segments=%zu..%zu span_m=%.3f axis_m=(%.3f,%.3f) connected=%d/2 route_support=%llu/%llu wall_failures=%llu wall_margin_m=%.3f threshold_m=1.500 radii_m=%.3f..%.3f relief_p2p_m=%.3f nominal_radius_m=%.3f status=%s\n",
passage.stableId.c_str(),crossing.firstSegment,crossing.lastSegment,
crossing.unsupportedLengthMetres,axisX,axisY,
static_cast<int>(topCapConnected)+static_cast<int>(bottomCapConnected),
static_cast<unsigned long long>(probeCount-crossingRouteFailures),
static_cast<unsigned long long>(probeCount),measuredWall,
static_cast<unsigned long long>(probeCount),
static_cast<unsigned long long>(crossingWallFailures),measuredWall,
crossingMinimumSurfaceRadius,crossingMaximumSurfaceRadius,
crossingSurfaceRelief,qToMetres(crossing.columnNominalRadiusSubvoxels),
columnPass?"PASS":"FAIL");
+212 -10
View File
@@ -7,6 +7,7 @@
#include <array>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <cstdio>
#include <filesystem>
#include <fstream>
@@ -44,7 +45,8 @@ namespace StandaloneWorldAssemblyPrototype
inline bool BuildFiniteStrateRoute(VoxelForgeCore::WorldAssemblyRecipeV1& recipe,
VoxelForgeCore::WorldAssemblyStratumPlanV1& stratum,std::uint64_t& tested,
std::uint64_t& gradeRejected,std::uint64_t& placementRejected,
std::uint64_t& sweepRejected,std::int64_t arrivalRadiusSubvoxels,
std::uint64_t& sweepRejected,std::uint32_t coreVoxelSizeMicrons,
std::int64_t arrivalRadiusSubvoxels,
std::int64_t departureRadiusSubvoxels,std::string& error)
{
using namespace VoxelForgeCore;
@@ -63,9 +65,20 @@ namespace StandaloneWorldAssemblyPrototype
struct Candidate
{
std::int64_t score=0;
std::uint64_t endpointProximityCost=0;
std::int32_t centerX=0,centerY=0,direction=0;
std::vector<WorldAssemblyRoutePointV1> points;
};
struct GradeSegmentAudit
{
std::uint64_t failures=0;
double maximumGrade=0.0;
std::int64_t fromGround=0,toGround=0,fromX=0,fromY=0,toX=0,toY=0;
};
std::array<GradeSegmentAudit,32> placementValidGradeSegments{};
std::uint64_t gradeFailCandidates=0;
double minimumGround=std::numeric_limits<double>::infinity();
double maximumGround=-std::numeric_limits<double>::infinity();
auto& constraints=stratum.routeConstraints;
constraints.version=1;
@@ -84,10 +97,112 @@ namespace StandaloneWorldAssemblyPrototype
if(!finalField.isValid())
{error="route planner received an invalid final composed field";return false;}
std::vector<Candidate> candidates;
constexpr std::int32_t halfLength=128;
constexpr std::int32_t waypointSpacing=8;
for(std::int32_t centerY=-256;centerY<=256;centerY+=64)
for(std::int32_t centerX=-256;centerX<=256;centerX+=64)
std::vector<std::int32_t> candidateHalfLengths{128};
std::int32_t candidateCenterSpacing=64;
if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0)
{
// A centered line cannot join two bounded mouths when its chord is
// longer than the sum of their placement radii. Leave 3 m for the
// capsule and terrain-profile repair, then search centers at 8 m
// spacing so asymmetric arrival/departure radii can both be reached.
constexpr std::int64_t placementMarginQ=12*WorldAssemblySubvoxelsPerVoxel;
const std::int64_t availableLengthVoxels=std::max<std::int64_t>(1,
(arrivalRadiusSubvoxels+departureRadiusSubvoxels-placementMarginQ)
/WorldAssemblySubvoxelsPerVoxel);
const std::int32_t maximumHalfLength=static_cast<std::int32_t>(std::min<std::int64_t>(128,
std::max<std::int64_t>(1,availableLengthVoxels/2)));
candidateHalfLengths.clear();
for(const std::int32_t numerator:std::array<std::int32_t,6>{{8,7,6,5,4,3}})
{
const std::int32_t halfLength=std::max(1,maximumHalfLength*numerator/8);
if(std::find(candidateHalfLengths.begin(),candidateHalfLengths.end(),halfLength)
==candidateHalfLengths.end())candidateHalfLengths.push_back(halfLength);
}
candidateCenterSpacing=32;
}
const double coreVoxelMetres=static_cast<double>(coreVoxelSizeMicrons)/1000000.0;
if(std::getenv("VOXELFORGE_AUDIT_LEGACY_ROUTE_GRADE"))
{
constexpr std::int32_t legacyCenterSpacing=64;
constexpr std::int32_t legacyWaypointSpacing=8;
std::array<GradeSegmentAudit,32> legacySegments{};
std::uint64_t legacyGradeFailCandidates=0;
double legacyMinimumGround=std::numeric_limits<double>::infinity();
double legacyMaximumGround=-std::numeric_limits<double>::infinity();
for(std::int32_t centerY=-256;centerY<=256;centerY+=legacyCenterSpacing)
for(std::int32_t centerX=-256;centerX<=256;centerX+=legacyCenterSpacing)
for(const Direction& direction:directions)
{
bool candidateGradeFail=false;
std::int64_t previousGround=0,previousX=0,previousY=0;
for(std::int32_t index=0;index<=32;++index)
{
const std::int64_t along=(index-16)*legacyWaypointSpacing;
const std::int64_t x=centerX+std::llround(
static_cast<double>(along)*direction.x/65536.0);
const std::int64_t y=centerY+std::llround(
static_cast<double>(along)*direction.y/65536.0);
const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)),
WorldAssemblyFixed(static_cast<double>(y)),0);
const double groundMetres=static_cast<double>(column.groundHeightSubvoxels)
*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
legacyMinimumGround=std::min(legacyMinimumGround,groundMetres);
legacyMaximumGround=std::max(legacyMaximumGround,groundMetres);
if(index>0)
{
const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround(
std::hypot(static_cast<double>(x-previousX),
static_cast<double>(y-previousY))*WorldAssemblySubvoxelsPerVoxel));
const std::int64_t riseQ=std::abs(
column.groundHeightSubvoxels-previousGround);
if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16)
{
candidateGradeFail=true;
GradeSegmentAudit& segment=legacySegments[
static_cast<std::size_t>(index-1)];
++segment.failures;
const double grade=horizontalQ>0
?static_cast<double>(riseQ)/static_cast<double>(horizontalQ)
:std::numeric_limits<double>::infinity();
if(grade>segment.maximumGrade)
{
segment.maximumGrade=grade;
segment.fromGround=previousGround;
segment.toGround=column.groundHeightSubvoxels;
segment.fromX=previousX;segment.fromY=previousY;
segment.toX=x;segment.toY=y;
}
}
}
previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y;
}
if(candidateGradeFail)++legacyGradeFailCandidates;
}
std::printf("[WorldAssemblerLegacyRouteGradeProfile] candidates=648 grade_fail_candidates=%llu ground_range_m=%.3f..%.3f grade_limit_deg=15.000 chord_m=%.3f waypoint_step_m=%.3f center_step_m=%.3f\n",
static_cast<unsigned long long>(legacyGradeFailCandidates),
legacyMinimumGround,legacyMaximumGround,256.0*coreVoxelMetres,
legacyWaypointSpacing*coreVoxelMetres,legacyCenterSpacing*coreVoxelMetres);
const double metresPerSubvoxel=coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
for(std::size_t segmentIndex=0;segmentIndex<legacySegments.size();++segmentIndex)
{
const GradeSegmentAudit& segment=legacySegments[segmentIndex];
if(segment.failures==0)continue;
std::printf("[WorldAssemblerLegacyRouteGradeSegment] index=%zu rejected_candidates=%llu max_grade_deg=%.3f ground_m=%.3f->%.3f xy_m=(%.3f,%.3f)->(%.3f,%.3f)\n",
segmentIndex,static_cast<unsigned long long>(segment.failures),
std::atan(segment.maximumGrade)*57.29577951308232,
segment.fromGround*metresPerSubvoxel,segment.toGround*metresPerSubvoxel,
segment.fromX*coreVoxelMetres,segment.fromY*coreVoxelMetres,
segment.toX*coreVoxelMetres,segment.toY*coreVoxelMetres);
}
}
std::printf("[WorldAssemblerRouteCandidateEnvelope] max_chord_m=%.3f length_variants=%zu center_step_m=%.3f arrival_radius_m=%.3f departure_radius_m=%.3f\n",
2.0*candidateHalfLengths.front()*coreVoxelMetres,candidateHalfLengths.size(),
candidateCenterSpacing*coreVoxelMetres,
arrivalRadiusSubvoxels*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel,
departureRadiusSubvoxels*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel);
for(const std::int32_t candidateHalfLength:candidateHalfLengths)
for(std::int32_t centerY=-256;centerY<=256;centerY+=candidateCenterSpacing)
for(std::int32_t centerX=-256;centerX<=256;centerX+=candidateCenterSpacing)
for(std::int32_t directionIndex=0;directionIndex<static_cast<std::int32_t>(directions.size());++directionIndex)
{
Candidate candidate;
@@ -95,22 +210,36 @@ namespace StandaloneWorldAssemblyPrototype
candidate.points.reserve(33);
std::int64_t previousGround=0,previousX=0,previousY=0;
bool gradePass=true,placementPass=true;
std::array<GradeSegmentAudit,32> candidateGradeSegments{};
for(std::int32_t index=0;index<=32;++index)
{
const std::int64_t along=(index-16)*waypointSpacing;
const std::int64_t along=(index-16)*candidateHalfLength/16;
const std::int64_t x=centerX+std::llround(
static_cast<double>(along)*directions[directionIndex].x/65536.0);
const std::int64_t y=centerY+std::llround(
static_cast<double>(along)*directions[directionIndex].y/65536.0);
const std::int64_t xQ=WorldAssemblyFixed(static_cast<double>(x));
const std::int64_t yQ=WorldAssemblyFixed(static_cast<double>(y));
if(arrivalRadiusSubvoxels>0&&departureRadiusSubvoxels>0
&&(index==0||index==32))
{
const std::uint64_t radiusSquared=static_cast<std::uint64_t>(
xQ*xQ+yQ*yQ);
candidate.endpointProximityCost+=radiusSquared*(index==0?16ull:1ull);
}
const auto inRadius=[](std::int64_t xValue,std::int64_t yValue,std::int64_t radius)
{return radius<=0||xValue*xValue+yValue*yValue<=radius*radius;};
if((index==0&&!inRadius(xQ,yQ,arrivalRadiusSubvoxels))
||(index==32&&!inRadius(xQ,yQ,departureRadiusSubvoxels)))
{placementPass=false;break;}
placementPass=false;
const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)),
WorldAssemblyFixed(static_cast<double>(y)),0);
const double metresPerSubvoxel=static_cast<double>(coreVoxelSizeMicrons)
/(WorldAssemblySubvoxelsPerVoxel*1000000.0);
const double groundMetres=static_cast<double>(column.groundHeightSubvoxels)
*metresPerSubvoxel;
minimumGround=std::min(minimumGround,groundMetres);
maximumGround=std::max(maximumGround,groundMetres);
const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround(
std::hypot(static_cast<double>(x-previousX),static_cast<double>(y-previousY))
*WorldAssemblySubvoxelsPerVoxel));
@@ -118,7 +247,23 @@ namespace StandaloneWorldAssemblyPrototype
{
const std::int64_t riseQ=std::abs(column.groundHeightSubvoxels-previousGround);
if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16)
{gradePass=false;break;}
{
gradePass=false;
GradeSegmentAudit& segment=candidateGradeSegments[
static_cast<std::size_t>(index-1)];
++segment.failures;
const double grade=horizontalQ>0
?static_cast<double>(riseQ)/static_cast<double>(horizontalQ)
:std::numeric_limits<double>::infinity();
if(grade>segment.maximumGrade)
{
segment.maximumGrade=grade;
segment.fromGround=previousGround;
segment.toGround=column.groundHeightSubvoxels;
segment.fromX=previousX;segment.fromY=previousY;
segment.toX=x;segment.toY=y;
}
}
candidate.score+=riseQ*65536/std::max<std::int64_t>(1,horizontalQ);
}
WorldAssemblyRoutePointV1 point;
@@ -131,13 +276,60 @@ namespace StandaloneWorldAssemblyPrototype
candidate.points.push_back(point);
previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y;
}
candidate.score/=32;
++tested;
if(!gradePass)++gradeFailCandidates;
if(placementPass&&gradePass)candidates.push_back(std::move(candidate));
else if(!placementPass)++placementRejected;
else ++gradeRejected;
else
{
++gradeRejected;
for(std::size_t segmentIndex=0;segmentIndex<candidateGradeSegments.size();
++segmentIndex)
{
const GradeSegmentAudit& rejected=candidateGradeSegments[segmentIndex];
if(rejected.failures==0)continue;
GradeSegmentAudit& aggregate=placementValidGradeSegments[segmentIndex];
aggregate.failures+=rejected.failures;
if(rejected.maximumGrade>aggregate.maximumGrade)
{
aggregate.maximumGrade=rejected.maximumGrade;
aggregate.fromGround=rejected.fromGround;
aggregate.toGround=rejected.toGround;
aggregate.fromX=rejected.fromX;aggregate.fromY=rejected.fromY;
aggregate.toX=rejected.toX;aggregate.toY=rejected.toY;
}
}
}
}
if(gradeRejected>0||placementRejected>0)
{
const double metresPerSubvoxel=static_cast<double>(coreVoxelSizeMicrons)
/(WorldAssemblySubvoxelsPerVoxel*1000000.0);
std::printf("[WorldAssemblerRouteGradeProfile] tested=%llu grade_fail_candidates=%llu grade_rejected_after_placement=%llu placement_rejected=%llu ground_range_m=%.3f..%.3f grade_limit_deg=15.000\n",
static_cast<unsigned long long>(tested),
static_cast<unsigned long long>(gradeFailCandidates),
static_cast<unsigned long long>(gradeRejected),
static_cast<unsigned long long>(placementRejected),minimumGround,maximumGround);
for(std::size_t segmentIndex=0;segmentIndex<placementValidGradeSegments.size();
++segmentIndex)
{
const GradeSegmentAudit& segment=placementValidGradeSegments[segmentIndex];
if(segment.failures==0)continue;
const double gradeDegrees=std::atan(segment.maximumGrade)*57.29577951308232;
std::printf("[WorldAssemblerRouteGradeSegment] index=%zu rejected_candidates=%llu max_grade_deg=%.3f ground_m=%.3f->%.3f xy_m=(%.3f,%.3f)->(%.3f,%.3f)\n",
segmentIndex,static_cast<unsigned long long>(segment.failures),gradeDegrees,
segment.fromGround*metresPerSubvoxel,segment.toGround*metresPerSubvoxel,
segment.fromX*coreVoxelSizeMicrons/1000000.0,
segment.fromY*coreVoxelSizeMicrons/1000000.0,
segment.toX*coreVoxelSizeMicrons/1000000.0,
segment.toY*coreVoxelSizeMicrons/1000000.0);
}
}
std::stable_sort(candidates.begin(),candidates.end(),[](const Candidate& a,const Candidate& b)
{
if(a.endpointProximityCost!=b.endpointProximityCost)
return a.endpointProximityCost<b.endpointProximityCost;
if(a.score!=b.score)return a.score<b.score;
if(a.centerY!=b.centerY)return a.centerY<b.centerY;
if(a.centerX!=b.centerX)return a.centerX<b.centerX;
@@ -165,6 +357,15 @@ namespace StandaloneWorldAssemblyPrototype
if(liftQ>0)
std::printf("[WorldAssemblerRouteRepaired] uniform_lift_q=%lld support_limit_q=%lld\n",
static_cast<long long>(liftQ),static_cast<long long>(SupportDepthQ));
const double metresPerSubvoxel=coreVoxelMetres
/WorldAssemblySubvoxelsPerVoxel;
std::printf("[WorldAssemblerRouteAccepted] arrival_xy_m=(%.3f,%.3f) departure_xy_m=(%.3f,%.3f) endpoint_proximity_cost=%llu average_grade_q16=%lld\n",
candidate.points.front().positionSubvoxels[0]*metresPerSubvoxel,
candidate.points.front().positionSubvoxels[1]*metresPerSubvoxel,
candidate.points.back().positionSubvoxels[0]*metresPerSubvoxel,
candidate.points.back().positionSubvoxels[1]*metresPerSubvoxel,
static_cast<unsigned long long>(candidate.endpointProximityCost),
static_cast<long long>(candidate.score));
return true;
}
if(audit.blockedCapsuleSamples==0||liftQ>=MaximumRepairLiftQ)break;
@@ -410,7 +611,8 @@ namespace StandaloneWorldAssemblyPrototype
}
std::uint64_t routeCandidates=0,routeGradeRejected=0,routePlacementRejected=0,routeSweepRejected=0;
if(!BuildFiniteStrateRoute(recipe,stratum,routeCandidates,routeGradeRejected,
routePlacementRejected,routeSweepRejected,arrivalRadiusQ,departureRadiusQ,error))return false;
routePlacementRejected,routeSweepRejected,owner.CoreVoxelSizeMicrons,
arrivalRadiusQ,departureRadiusQ,error))return false;
std::printf("[WorldAssemblerRoutePlan] candidates=%llu grade_rejected=%llu placement_rejected=%llu sweep_rejected=%llu accepted_points=%zu capsule_m=0.34x1.76 corridor_radius_vox=4 support_probe_points=5 minimum_support_probes=%u arrival_radius_m=%.3f departure_radius_m=%.3f status=PASS\n",
static_cast<unsigned long long>(routeCandidates),
static_cast<unsigned long long>(routeGradeRejected),