core: Tunnel Network cave planner with a continuous backbone floor (L134, evaluator v230)
Backbone rooms and edges share one floor profile h(s); side branches keep flat floors; overlap backing capped at the lower floor. Default seed: route audit 0 blocked / 0 unsupported / 0 grade over 51,975 capsule samples; passages open; fast tier, seams, Clang/GCC W1/W8/W12 green. Open: seed 1 (24 blocked at the 2-3 arrival mouth) and seed 2 (22 unsupported at passage 1-2) fail composed audits; near-ready +6..+14% on layers 1-3. Not for merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
4a97023b24
commit
a3c8e3687d
23 files changed
+338
-53
No files matched your search
@@ -1247,7 +1247,7 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
else if(cavernGraphVocabularyVersion!=ResolvedLayoutCavernGraphVocabularyVersionV1
|
||||
&&cavernGraphVocabularyVersion!=ResolvedLayoutCavernGraphVocabularyVersionV2)
|
||||
add("cavern_graph_vocabulary_version",
|
||||
"cavern graph records require vocabulary version 1");
|
||||
"cavern graph records require a supported vocabulary version");
|
||||
if(cavernGraphVocabularyVersion!=0)
|
||||
{
|
||||
if(cavernRooms.empty()||cavernEdges.empty())
|
||||
@@ -1447,9 +1447,13 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
previous->floorProfileEndDistanceMicrometres);
|
||||
if(low!=previousHigh
|
||||
||std::abs(endpointZ(*previous,false)-endpointZ(*edge,true))>1000
|
||||
||std::abs(endpointSlope(*previous,false)-slope0)>0.000001)
|
||||
add("cavern_floor_profile_joint",profileId+
|
||||
" has a gap, height step, or slope step between adjacent edges");
|
||||
||std::abs(endpointSlope(*previous,false)-slope0)>0.00001)
|
||||
add("cavern_floor_profile_joint",profileId+" between "+previous->stableId
|
||||
+" and "+edge->stableId+" has distance gap="
|
||||
+std::to_string(low-previousHigh)+" um height step="
|
||||
+std::to_string(endpointZ(*previous,false)-endpointZ(*edge,true))
|
||||
+" um slope step="
|
||||
+std::to_string(endpointSlope(*previous,false)-slope0));
|
||||
}
|
||||
previous=edge;
|
||||
(void)high;
|
||||
@@ -2320,7 +2324,9 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
points[2][axis]=routeStart[axis]+(delta*2)/3;
|
||||
}
|
||||
points[1][0]+=perpX;points[1][1]+=perpY;
|
||||
points[2][0]-=perpX;points[2][1]-=perpY;
|
||||
// Keep both control points on the same side of the mouth axis. Opposite
|
||||
// offsets create a tight hairpin whose descending bores overlap in XY.
|
||||
points[2][0]+=perpX;points[2][1]+=perpY;
|
||||
return points;
|
||||
};
|
||||
const auto routeLength=[&](const std::array<FPoint,4>& points)
|
||||
@@ -2545,8 +2551,15 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
room.floorGradientQ16=node.floorGradientQ16;
|
||||
room.halfExtentsMicrometres={halfX,halfY,halfZ};
|
||||
room.centerMicrometres={node.point[0]+(-pathAxisY)*centerOffset/routeLengthXY,
|
||||
node.point[1]+pathAxisX*centerOffset/routeLengthXY,
|
||||
node.point[2]+fractional(halfZ,floorCut)};
|
||||
node.point[1]+pathAxisX*centerOffset/routeLengthXY,0};
|
||||
// Keep the local floor plane on the backbone profile at the route point,
|
||||
// then place each offset primitive from that plane at its own XY centre.
|
||||
room.floorMicrometres=node.point[2]
|
||||
+(static_cast<std::int64_t>(room.floorGradientQ16[0])
|
||||
*(room.centerMicrometres[0]-node.point[0])
|
||||
+static_cast<std::int64_t>(room.floorGradientQ16[1])
|
||||
*(room.centerMicrometres[1]-node.point[1]))/65536;
|
||||
room.centerMicrometres[2]=room.floorMicrometres+fractional(halfZ,floorCut);
|
||||
if(component>0)
|
||||
{
|
||||
const std::int64_t headroom=std::max<std::int64_t>(0,
|
||||
@@ -2557,11 +2570,6 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
%static_cast<std::uint64_t>(jitterRange+1)):0;
|
||||
room.centerMicrometres[2]+=ceilingJitter;
|
||||
}
|
||||
room.floorMicrometres=node.point[2]
|
||||
-(static_cast<std::int64_t>(room.floorGradientQ16[0])
|
||||
*(room.centerMicrometres[0]-node.point[0])
|
||||
+static_cast<std::int64_t>(room.floorGradientQ16[1])
|
||||
*(room.centerMicrometres[1]-node.point[1]))/65536;
|
||||
room.smoothWidthMicrometres=smooth;
|
||||
room.irregularityAmplitudeMicrometres=irregularity;
|
||||
room.irregularityWavelengthMicrometres=settings.irregularityWavelengthMicrometres;
|
||||
@@ -2665,9 +2673,8 @@ bool PlanResolvedCavernNetworkV1(const ResolvedLayoutSnapshotV3& layout,
|
||||
branch.point={parent.point[0]+(-pathAxisY)*branchLength/pathAxisLength*direction,
|
||||
parent.point[1]+pathAxisX*branchLength/pathAxisLength*direction,
|
||||
parent.point[2]};
|
||||
branch.floorProfileStableId=parent.floorProfileStableId;
|
||||
branch.floorProfileDistanceMicrometres=parent.floorProfileDistanceMicrometres;
|
||||
branch.floorGradientQ16=parent.floorGradientQ16;
|
||||
// A side branch leaves the backbone laterally, so it has its own local flat
|
||||
// floor and must not reference the parent's one-dimensional h(s) profile.
|
||||
makeCompound(branch,false,rooms);
|
||||
const std::string branchEdgeId="tunnel-network/strate-"
|
||||
+std::to_string(strateIndex)+"/side-edge-"+std::to_string(branchCount);
|
||||
|
||||
Reference in new issue
Block a user