proto: liminal pass 2 - hills to the horizon, swept road over a cloud floor, pillar grid (L142)
Captures stream LOD0-8 (hills repeat at 80 m to the horizon). Road: cubic swept solid deck, 376.8 m, 8 m wide, max 12.06 deg, 17 supports, cloud floor ~45 m below; walk audit 0 blocked/unsupported, 300 m negative control fails as expected. 15x15 identical pillar grid at 76 m. Owner canonical hashes unchanged; fast tier, Clang/GCC green. 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
9c6d261d01
commit
6cd9e4da76
17 files changed
+1129
-98
No files matched your search
@@ -176,7 +176,7 @@ namespace
|
||||
{
|
||||
const auto value=static_cast<std::uint8_t>(kind);
|
||||
return value>=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::carveEllipsoid)
|
||||
&&value<=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::fillPlatform);
|
||||
&&value<=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::fillSweptDeckSegment);
|
||||
}
|
||||
bool LayoutStampIsMotif(ResolvedSdfStampKindV1 kind)
|
||||
{return kind==ResolvedSdfStampKindV1::fillMonolith
|
||||
@@ -598,6 +598,14 @@ namespace
|
||||
<<",\"irregularity_wavelength_um\":"<<stamp.irregularityWavelengthMicrometres
|
||||
<<",\"irregularity_seed\":"<<stamp.irregularitySeed
|
||||
<<",\"yaw_quarter_turns\":"<<static_cast<unsigned>(stamp.yawQuarterTurns);
|
||||
if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment)
|
||||
out<<",\"sweep_endpoints_um\":[["
|
||||
<<stamp.sweepEndpointsMicrometres[0][0]<<','
|
||||
<<stamp.sweepEndpointsMicrometres[0][1]<<','
|
||||
<<stamp.sweepEndpointsMicrometres[0][2]<<"],["
|
||||
<<stamp.sweepEndpointsMicrometres[1][0]<<','
|
||||
<<stamp.sweepEndpointsMicrometres[1][1]<<','
|
||||
<<stamp.sweepEndpointsMicrometres[1][2]<<"]]";
|
||||
if(s.stampVocabularyVersion>=ResolvedLayoutStampVocabularyVersionV3)
|
||||
out<<",\"rounding_radius_um\":"<<stamp.roundingRadiusMicrometres
|
||||
<<",\"minimum_spacing_um\":"<<stamp.minimumSpacingMicrometres
|
||||
@@ -1134,8 +1142,9 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
}
|
||||
else if(stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV1
|
||||
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV2
|
||||
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3)
|
||||
add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1, 2 or 3");
|
||||
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV3
|
||||
&&stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV4)
|
||||
add("stamp_vocabulary_version","resolved stamps require supported vocabulary version 1, 2, 3 or 4");
|
||||
std::vector<std::string> stampIds;
|
||||
for(const auto& stamp:stamps)
|
||||
{
|
||||
@@ -1145,6 +1154,8 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
else stampIds.push_back(stamp.stableId);
|
||||
const bool motif=LayoutStampIsMotif(stamp.kind);
|
||||
if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3
|
||||
||(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment
|
||||
&&stampVocabularyVersion<ResolvedLayoutStampVocabularyVersionV4)
|
||||
||(motif&&stampVocabularyVersion<ResolvedLayoutStampVocabularyVersionV3))
|
||||
add("stamp_kind","stamp has an unsupported kind or orientation");
|
||||
bool validExtents=true;
|
||||
@@ -1159,6 +1170,24 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
||(stamp.irregularityAmplitudeMicrometres>0
|
||||
&&stamp.irregularityWavelengthMicrometres<=0))
|
||||
add("stamp_parameters",stamp.stableId+" has invalid or unbounded geometry parameters");
|
||||
if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment)
|
||||
{
|
||||
double lengthSquared=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const auto a=stamp.sweepEndpointsMicrometres[0][axis];
|
||||
const auto b=stamp.sweepEndpointsMicrometres[1][axis];
|
||||
if(a<-1000000000000ll||a>1000000000000ll
|
||||
||b<-1000000000000ll||b>1000000000000ll)
|
||||
add("stamp_sweep",stamp.stableId+" has an unbounded endpoint");
|
||||
const double delta=static_cast<double>(stamp.sweepEndpointsMicrometres[1][axis])
|
||||
-stamp.sweepEndpointsMicrometres[0][axis];
|
||||
lengthSquared+=delta*delta;
|
||||
}
|
||||
if(!(lengthSquared>0.0)
|
||||
||std::sqrt(lengthSquared)>2.0*stamp.halfExtentsMicrometres[0]+1.0)
|
||||
add("stamp_sweep",stamp.stableId+" has invalid endpoints or longitudinal extent");
|
||||
}
|
||||
if(motif)
|
||||
{
|
||||
const auto minimumExtent=*std::min_element(stamp.halfExtentsMicrometres.begin(),
|
||||
@@ -1186,16 +1215,39 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
|
||||
const std::int64_t pad=motif
|
||||
?(stamp.smoothWidthMicrometres+5)/6+stamp.irregularityAmplitudeMicrometres
|
||||
:stamp.smoothWidthMicrometres+stamp.irregularityAmplitudeMicrometres;
|
||||
const std::array<std::int64_t,3> extents={
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
|
||||
stamp.halfExtentsMicrometres[2]+pad};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
if(stamp.boundsMinimumMicrometres[axis]
|
||||
!=stamp.positionMicrometres[axis]-extents[axis]
|
||||
||stamp.boundsMaximumMicrometres[axis]
|
||||
!=stamp.positionMicrometres[axis]+extents[axis])
|
||||
add("stamp_bounds",stamp.stableId+" conservative bounds do not match its parameters");
|
||||
if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment)
|
||||
{
|
||||
double radiusSquared=0.0;
|
||||
for(const auto extent:stamp.halfExtentsMicrometres)
|
||||
{
|
||||
const double expanded=static_cast<double>(extent+pad);
|
||||
radiusSquared+=expanded*expanded;
|
||||
}
|
||||
const auto radius=static_cast<std::int64_t>(std::ceil(std::sqrt(radiusSquared)));
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const auto minimum=std::min(stamp.sweepEndpointsMicrometres[0][axis],
|
||||
stamp.sweepEndpointsMicrometres[1][axis]);
|
||||
const auto maximum=std::max(stamp.sweepEndpointsMicrometres[0][axis],
|
||||
stamp.sweepEndpointsMicrometres[1][axis]);
|
||||
if(stamp.boundsMinimumMicrometres[axis]!=minimum-radius
|
||||
||stamp.boundsMaximumMicrometres[axis]!=maximum+radius)
|
||||
add("stamp_bounds",stamp.stableId+" conservative sweep bounds do not match its parameters");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::array<std::int64_t,3> extents={
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
|
||||
stamp.halfExtentsMicrometres[2]+pad};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
if(stamp.boundsMinimumMicrometres[axis]
|
||||
!=stamp.positionMicrometres[axis]-extents[axis]
|
||||
||stamp.boundsMaximumMicrometres[axis]
|
||||
!=stamp.positionMicrometres[axis]+extents[axis])
|
||||
add("stamp_bounds",stamp.stableId+" conservative bounds do not match its parameters");
|
||||
}
|
||||
std::string safetyReason;
|
||||
if(!LayoutStampSafe(*this,stamp,&safetyReason))
|
||||
add("stamp_placement",stamp.stableId+" is unsafe: "+safetyReason);
|
||||
@@ -1497,6 +1549,13 @@ std::optional<ResolvedLayoutSnapshotV3> ResolvedLayoutSnapshotV3::FromJson(
|
||||
target[axis]=values[axis].Integer();
|
||||
};
|
||||
readTriplet("position_um",stamp.positionMicrometres);
|
||||
const auto& sweepEndpoints=v.Get("sweep_endpoints_um").AsArray();
|
||||
for(std::size_t endpoint=0;endpoint<2&&endpoint<sweepEndpoints.size();++endpoint)
|
||||
{
|
||||
const auto& values=sweepEndpoints[endpoint].AsArray();
|
||||
for(std::size_t axis=0;axis<3&&axis<values.size();++axis)
|
||||
stamp.sweepEndpointsMicrometres[endpoint][axis]=values[axis].Integer();
|
||||
}
|
||||
readTriplet("bounds_min_um",stamp.boundsMinimumMicrometres);
|
||||
readTriplet("bounds_max_um",stamp.boundsMaximumMicrometres);
|
||||
readTriplet("half_extents_um",stamp.halfExtentsMicrometres);
|
||||
@@ -1619,7 +1678,10 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
std::sort(ordered.begin(),ordered.end(),[](const auto& a,const auto& b)
|
||||
{return a.stableId<b.stableId;});
|
||||
ResolvedLayoutSnapshotV3 candidate=layout;
|
||||
candidate.stampVocabularyVersion=ResolvedLayoutStampVocabularyVersionV1;
|
||||
const bool hasSweptDeck=std::any_of(ordered.begin(),ordered.end(),[](const auto& request)
|
||||
{return request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment;});
|
||||
candidate.stampVocabularyVersion=hasSweptDeck
|
||||
?ResolvedLayoutStampVocabularyVersionV4:ResolvedLayoutStampVocabularyVersionV1;
|
||||
candidate.stamps.clear();candidate.stamps.reserve(ordered.size());
|
||||
for(std::size_t requestIndex=0;requestIndex<ordered.size();++requestIndex)
|
||||
{
|
||||
@@ -1630,6 +1692,8 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
if(!LayoutStampKindValid(request.kind)||request.yawQuarterTurns>3
|
||||
||request.placementRadiusMicrometres<0
|
||||
||request.placementRadiusMicrometres>100000000
|
||||
||(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment
|
||||
&&request.placementRadiusMicrometres!=0)
|
||||
||request.smoothWidthMicrometres<0||request.smoothWidthMicrometres>10000000
|
||||
||request.irregularityAmplitudeMicrometres<0
|
||||
||request.irregularityAmplitudeMicrometres>10000000
|
||||
@@ -1648,6 +1712,23 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
for(const auto coordinate:request.anchorPositionMicrometres)
|
||||
if(coordinate<-1000000000000ll||coordinate>1000000000000ll)
|
||||
{error="stamp request "+request.stableId+" has an unbounded anchor";return false;}
|
||||
if(request.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment)
|
||||
{
|
||||
double lengthSquared=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const auto a=request.sweepEndpointsMicrometres[0][axis];
|
||||
const auto b=request.sweepEndpointsMicrometres[1][axis];
|
||||
if(a<-1000000000000ll||a>1000000000000ll
|
||||
||b<-1000000000000ll||b>1000000000000ll)
|
||||
{error="stamp request "+request.stableId+" has an unbounded sweep endpoint";return false;}
|
||||
const double delta=static_cast<double>(b)-a;
|
||||
lengthSquared+=delta*delta;
|
||||
}
|
||||
if(!(lengthSquared>0.0)
|
||||
||std::sqrt(lengthSquared)>2.0*request.halfExtentsMicrometres[0]+1.0)
|
||||
{error="stamp request "+request.stableId+" has invalid swept-segment extents";return false;}
|
||||
}
|
||||
|
||||
// The shared JSON value type stores numbers as IEEE-754 doubles; keep the
|
||||
// serialized seed in its exact integer range so the canonical round trip holds.
|
||||
@@ -1666,6 +1747,7 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
{
|
||||
ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId;
|
||||
stamp.strateIndex=request.strateIndex;stamp.kind=request.kind;
|
||||
stamp.sweepEndpointsMicrometres=request.sweepEndpointsMicrometres;
|
||||
stamp.halfExtentsMicrometres=request.halfExtentsMicrometres;
|
||||
stamp.smoothWidthMicrometres=request.smoothWidthMicrometres;
|
||||
stamp.irregularityAmplitudeMicrometres=request.irregularityAmplitudeMicrometres;
|
||||
@@ -1687,14 +1769,36 @@ bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
|
||||
stamp.positionMicrometres[axis]=request.anchorPositionMicrometres[axis]+offset[axis];
|
||||
const std::int64_t pad=stamp.smoothWidthMicrometres
|
||||
+stamp.irregularityAmplitudeMicrometres;
|
||||
const std::array<std::int64_t,3> extents={
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
|
||||
stamp.halfExtentsMicrometres[2]+pad};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
if(stamp.kind==ResolvedSdfStampKindV1::fillSweptDeckSegment)
|
||||
{
|
||||
stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis];
|
||||
stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis];
|
||||
double radiusSquared=0.0;
|
||||
for(const auto extent:stamp.halfExtentsMicrometres)
|
||||
{
|
||||
const double expanded=static_cast<double>(extent+pad);
|
||||
radiusSquared+=expanded*expanded;
|
||||
}
|
||||
const std::int64_t radius=static_cast<std::int64_t>(std::ceil(std::sqrt(radiusSquared)));
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const auto minimum=std::min(stamp.sweepEndpointsMicrometres[0][axis],
|
||||
stamp.sweepEndpointsMicrometres[1][axis]);
|
||||
const auto maximum=std::max(stamp.sweepEndpointsMicrometres[0][axis],
|
||||
stamp.sweepEndpointsMicrometres[1][axis]);
|
||||
stamp.boundsMinimumMicrometres[axis]=minimum-radius;
|
||||
stamp.boundsMaximumMicrometres[axis]=maximum+radius;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::array<std::int64_t,3> extents={
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
|
||||
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
|
||||
stamp.halfExtentsMicrometres[2]+pad};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis];
|
||||
stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis];
|
||||
}
|
||||
}
|
||||
if(!LayoutStampSafe(candidate,stamp))continue;
|
||||
candidate.stamps.push_back(std::move(stamp));placed=true;break;
|
||||
|
||||
Reference in new issue
Block a user