mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 13:01:52 +00:00
plan/findings.md: main's new sections first, this PR's section appended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+20
-59
@@ -6,16 +6,13 @@ on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
# Pushes to main run on the org's self-hosted runners (`self-hosted-fast`): everything but
|
||||
# cargo-deny, which is a container action. Every pull request (fork or not) and Run workflow
|
||||
# use Blacksmith's hosted runners (blacksmith.sh; ephemeral VMs like GitHub's, outside the
|
||||
# org's 20-runner cap), so PRs never queue behind main. To fall back when Blacksmith minutes
|
||||
# run out, change the `blacksmith-*` labels below back to `ubuntu-latest`. The
|
||||
# self-hosted runners keep their Cargo build directory and the C++ reference build between jobs
|
||||
# (scripts/ci/warm-target.sh) instead of using actions/cache, and refuse any other job.
|
||||
# The org shares 20 concurrent runners across all its repositories. A new push to a
|
||||
# PR supersedes the run on its previous head, so cancel it. Runs on main are keyed
|
||||
# by commit, so they never queue behind or cancel each other: every merge is checked.
|
||||
# Every job runs on Blacksmith's hosted runners (blacksmith.sh; ephemeral VMs, sponsored
|
||||
# minutes, outside the org's 20-runner cap): pushes to main, every pull request (fork or not)
|
||||
# and Run workflow. Builds are cached with actions/cache (Swatinem/rust-cache and the C++
|
||||
# reference build cache below). To fall back when the sponsorship ends, change the
|
||||
# `blacksmith-*` labels back to `ubuntu-latest`. A new push to a PR supersedes the run on its
|
||||
# previous head, so cancel it. Runs on main are keyed by commit, so they never queue behind or
|
||||
# cancel each other: every merge is checked.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
@@ -26,54 +23,38 @@ env:
|
||||
# Must match ATTRIBUTION.md / AGENTS.md (full SHA so a shallow fetch works).
|
||||
UPSTREAM_REPO: https://github.com/NVIDIA-Omniverse/usd-brep
|
||||
UPSTREAM_COMMIT: c9c5979f04cea8c38213004d4f04df0dcfb40d05 # c9c5979
|
||||
# True when the job runs on the org's self-hosted-fast runners (same test as runs-on).
|
||||
# Blacksmith runners also report runner.environment == 'self-hosted', so steps branch
|
||||
# on this instead.
|
||||
ON_ORG_RUNNERS: ${{ github.event_name == 'push' }}
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: rustup show active-toolchain || rustup toolchain install
|
||||
- run: cargo fmt --all --check
|
||||
|
||||
clippy:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
if: env.ON_ORG_RUNNERS == 'true'
|
||||
run: scripts/ci/warm-target.sh
|
||||
- if: env.ON_ORG_RUNNERS != 'true'
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: ". -> bin"
|
||||
- run: cargo clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
test:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
if: env.ON_ORG_RUNNERS == 'true'
|
||||
run: scripts/ci/warm-target.sh
|
||||
- if: env.ON_ORG_RUNNERS != 'true'
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: ". -> bin"
|
||||
- run: cargo test --workspace
|
||||
|
||||
wasm:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
if: env.ON_ORG_RUNNERS == 'true'
|
||||
run: scripts/ci/warm-target.sh
|
||||
- if: env.ON_ORG_RUNNERS != 'true'
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: ". -> bin"
|
||||
- run: rustup target add wasm32-unknown-unknown
|
||||
@@ -81,14 +62,10 @@ jobs:
|
||||
|
||||
# Same packaging check the release workflow runs before publishing (no secrets).
|
||||
publish-dry-run:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
if: env.ON_ORG_RUNNERS == 'true'
|
||||
run: scripts/ci/warm-target.sh
|
||||
- if: env.ON_ORG_RUNNERS != 'true'
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: ". -> bin"
|
||||
- run: cargo publish -p solidcore --locked --dry-run
|
||||
@@ -102,7 +79,7 @@ jobs:
|
||||
command: check licenses bans sources
|
||||
|
||||
difftest:
|
||||
runs-on: ${{ github.event_name == 'push' && 'self-hosted-fast' || 'blacksmith-8vcpu-ubuntu-2404' }}
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
needs: [test]
|
||||
env:
|
||||
SOLIDCORE_CPP_DIR: ${{ github.workspace }}/.cpp
|
||||
@@ -128,27 +105,14 @@ jobs:
|
||||
|| git -C upstream fetch origin
|
||||
git -C upstream checkout --detach "$UPSTREAM_COMMIT"
|
||||
|
||||
# Preinstalled on the self-hosted runners, which have no sudo.
|
||||
- name: Install C++ build tools
|
||||
if: steps.green.outputs.any == 'true' && env.ON_ORG_RUNNERS != 'true'
|
||||
if: steps.green.outputs.any == 'true'
|
||||
run: sudo apt-get update && sudo apt-get install -y ninja-build cmake g++
|
||||
|
||||
# The C++ build lives outside cargo's target dir (bin/): rust-cache's post-step
|
||||
# cleans bin/ before this cache saves, which once cached an empty bin/cpp.
|
||||
# The self-hosted runners keep their C++ build in their home instead: their newer
|
||||
# compiler and glibc must never reach GitHub's runners through this cache.
|
||||
- name: Keep the C++ reference build (self-hosted runner)
|
||||
if: steps.green.outputs.any == 'true' && env.ON_ORG_RUNNERS == 'true'
|
||||
env:
|
||||
KEY: ${{ env.UPSTREAM_COMMIT }}-${{ hashFiles('harness/cpp/CMakeLists.txt', 'harness/cpp/build.sh', 'harness/cpp/stubs/**', 'harness/cpp/patches/**') }}
|
||||
run: |
|
||||
dir="$HOME/cpp/$KEY"
|
||||
# Only the current build is kept.
|
||||
find "$HOME/cpp" -mindepth 1 -maxdepth 1 ! -name "$KEY" -exec rm -rf {} + 2>/dev/null || true
|
||||
mkdir -p "$dir"
|
||||
echo "SOLIDCORE_CPP_DIR=$dir" >> "$GITHUB_ENV"
|
||||
- name: Cache C++ reference build
|
||||
if: steps.green.outputs.any == 'true' && env.ON_ORG_RUNNERS != 'true'
|
||||
if: steps.green.outputs.any == 'true'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cpp
|
||||
@@ -165,11 +129,8 @@ jobs:
|
||||
harness/cpp/build.sh --jobs "$(nproc)"
|
||||
fi
|
||||
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
if: steps.green.outputs.any == 'true' && env.ON_ORG_RUNNERS == 'true'
|
||||
run: scripts/ci/warm-target.sh
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: steps.green.outputs.any == 'true' && env.ON_ORG_RUNNERS != 'true'
|
||||
if: steps.green.outputs.any == 'true'
|
||||
with:
|
||||
workspaces: ". -> bin"
|
||||
key: difftest
|
||||
|
||||
@@ -84,6 +84,7 @@ use solidcore::surface::surface::p2::TsectCurveType;
|
||||
use solidcore::surface::surface::Surface;
|
||||
use solidcore::surface::volume::Volume;
|
||||
use solidcore::topology::brep::p1 as bp1;
|
||||
use solidcore::topology::brep::p5 as bp5;
|
||||
use solidcore::topology::brep::p7;
|
||||
use solidcore::topology::brep_cache::{arena_identity, BrepCache, CacheObject, CacheSource};
|
||||
use solidcore::topology::edge as ed;
|
||||
@@ -3389,7 +3390,7 @@ fn run_part2_op(
|
||||
// (a null B-rep where a combination would run, or a mate that is not a vertex
|
||||
// where upstream dereferences it, is the port's InvalidInput, reported as -2
|
||||
// like the shim's guard)
|
||||
let Some(r) = status(ti.check_for_squeeze_vertices(two, bv, ov), o)? else {
|
||||
let Some(r) = status(ti.check_for_squeeze_vertices(k, two, bv, ov), o)? else {
|
||||
return Ok(());
|
||||
};
|
||||
o.push(r.deleted_vertices.len() as f64);
|
||||
@@ -3423,7 +3424,7 @@ fn run_part2_op(
|
||||
o.push(NULL_DEREF);
|
||||
return Ok(());
|
||||
}
|
||||
let Some(r) = status(ti.fix_gaps(two, &vs), o)? else {
|
||||
let Some(r) = status(ti.fix_gaps(k, two, &vs), o)? else {
|
||||
return Ok(());
|
||||
};
|
||||
o.push(flag(r.modified_topology));
|
||||
@@ -3558,6 +3559,62 @@ fn run_part2_op(
|
||||
}
|
||||
|
||||
impl IntersectorBrepP2<H> for Two {
|
||||
fn brep_faces(&self, brep: H) -> solidcore::Result<Vec<H>> {
|
||||
let b = self.brep_r(brep)?;
|
||||
Ok(bp1::faces(b, None)?
|
||||
.into_iter()
|
||||
.map(|f| hd(brep.b, K_FACE, f.index()))
|
||||
.collect())
|
||||
}
|
||||
fn brep_combine_coincident_vertices(
|
||||
&mut self,
|
||||
k: &mut Kernel,
|
||||
brep: H,
|
||||
surviving: H,
|
||||
to_delete: H,
|
||||
) -> solidcore::Result<Option<H>> {
|
||||
if brep.kind != K_BREP {
|
||||
return Err(invalid("not a B-rep handle"));
|
||||
}
|
||||
let vertex = |h: H| -> solidcore::Result<VertexId> {
|
||||
if h.kind == K_VERTEX && h.b == brep.b {
|
||||
Ok(vid(h))
|
||||
} else {
|
||||
Err(invalid("not a vertex of this B-rep"))
|
||||
}
|
||||
};
|
||||
let (surviving, to_delete) = (vertex(surviving)?, vertex(to_delete)?);
|
||||
let slot = usize::try_from(brep.b).map_err(|_| invalid("bad B-rep"))?;
|
||||
let (breps, envs) = (&mut self.breps, &mut self.env);
|
||||
let b = breps
|
||||
.get_mut(slot)
|
||||
.and_then(Option::as_mut)
|
||||
.ok_or_else(|| invalid("handle names an absent B-rep"))?;
|
||||
let env = envs.get_mut(slot).ok_or_else(|| invalid("bad B-rep"))?;
|
||||
// (SmVertex::SetPoint notifies under the vertex environment's identities, as
|
||||
// set_vertex_point)
|
||||
let this = env.this;
|
||||
let key_of = move |e: EntityRef| match e {
|
||||
EntityRef::Vertex(_) => this,
|
||||
e => glue_key_of(e),
|
||||
};
|
||||
let mut notify = ed::NotifyEnv {
|
||||
records: &mut env.records,
|
||||
attributes: &mut env.attributes,
|
||||
context: None,
|
||||
key_of: &key_of,
|
||||
};
|
||||
let mut deleted_edge = None;
|
||||
bp5::combine_with_notifications(
|
||||
k,
|
||||
b,
|
||||
surviving,
|
||||
to_delete,
|
||||
&mut deleted_edge,
|
||||
Some(&mut notify),
|
||||
)?;
|
||||
Ok(deleted_edge.map(|e| hd(brep.b, K_EDGE, e.index())))
|
||||
}
|
||||
fn vertex_edges(&self, vertex: H) -> solidcore::Result<Vec<H>> {
|
||||
let b = self.brep_r(vertex)?;
|
||||
Ok(vx::edges(b, vid(vertex), None)?
|
||||
|
||||
@@ -1298,10 +1298,11 @@ fn rust_probe(branch: Probe, tolerance: f64) -> RResult<Output> {
|
||||
executive.set_merge_results(matches!(branch, Probe::RemoveEmpty));
|
||||
executive.remove_excess_faces(&kernel, &original, &mut Brep::new())
|
||||
}
|
||||
Probe::SideWallNull => executive.build_side_wall_of_edgeuse(&kernel, None),
|
||||
Probe::SideWallNull => executive.build_side_wall_of_edgeuse(&kernel, &mut original, None),
|
||||
Probe::SideWallUnmapped => {
|
||||
let edge = unit_wire(&mut original, 0.0)?;
|
||||
executive.build_side_wall_of_edgeuse(&kernel, Some(primary(&original, edge)?))
|
||||
let eu = primary(&original, edge)?;
|
||||
executive.build_side_wall_of_edgeuse(&kernel, &mut original, Some(eu))
|
||||
}
|
||||
Probe::FillEmpty => {
|
||||
executive.fill_gap_edgeuses(&kernel, EdgeId::from_index(u32::MAX), &[], &[])
|
||||
|
||||
@@ -65,6 +65,8 @@ fn harness(msg: impl Into<String>) -> HarnessError {
|
||||
|
||||
/// "Upstream would dereference null" in a status slot.
|
||||
const NULL_DEREF: f64 = -2.0;
|
||||
/// The shim's HANG-39 rejection of a corner blend (C++ not run; see `run_cpp`).
|
||||
const HANG34_GUARD: f64 = -34.0;
|
||||
|
||||
/// The type codes `IsKindOf` is asked about (as the shim's `KIND_TYPES`).
|
||||
const KIND_TYPES: [i64; 9] = [16011, 16050, 12060, 11001, 16012, 16001, 16010, 16999, 0];
|
||||
@@ -221,6 +223,14 @@ enum OpIn {
|
||||
eu2: i64,
|
||||
dir: u8,
|
||||
},
|
||||
/// A ruled `CreateEdgeEdgeBlend` with `eu2` in a second B-rep `other` (not a file
|
||||
/// block): each rail is read from its own arena.
|
||||
EdgeEdgeBlend2 {
|
||||
other: BrepIn,
|
||||
eu1: i64,
|
||||
eu2: i64,
|
||||
dir: u8,
|
||||
},
|
||||
ParallelProj {
|
||||
curve: CrvIn,
|
||||
vec: [f64; 3],
|
||||
@@ -441,6 +451,23 @@ fn resolve(op: &OpIn, c: [usize; 10]) -> Option<OpIn> {
|
||||
eu2: sel(eu2, n_eu),
|
||||
dir: dir % 3,
|
||||
},
|
||||
// (eu2 indexes the second B-rep: the FFI checks it against that B-rep's counts)
|
||||
OpIn::EdgeEdgeBlend2 {
|
||||
other,
|
||||
eu1,
|
||||
eu2,
|
||||
dir,
|
||||
} => {
|
||||
if n_eu == 0 {
|
||||
return None;
|
||||
}
|
||||
OpIn::EdgeEdgeBlend2 {
|
||||
other,
|
||||
eu1: sel(eu1, n_eu),
|
||||
eu2,
|
||||
dir: dir % 3,
|
||||
}
|
||||
}
|
||||
other @ (OpIn::Degenerate { .. }
|
||||
| OpIn::AddDeleted { .. }
|
||||
| OpIn::LockBox
|
||||
@@ -453,6 +480,24 @@ fn resolve(op: &OpIn, c: [usize; 10]) -> Option<OpIn> {
|
||||
|
||||
/// An op naming an entity kind the B-rep lacks (e.g. a face op on a wire B-rep): no code
|
||||
/// runs on either side, so the case is rejected (not counted as a pass).
|
||||
/// Inputs the FFI refuses, rejected on both sides before anything runs: a non-positive
|
||||
/// `ParallelProj` angle tolerance or an approximation tolerance below the smallest normal
|
||||
/// double (non-positive: the projector subdivides to it; subnormal: upstream spins,
|
||||
/// HANG-32). (A `CornerBlend` tangency tolerance below 1e-20 is rejected by the shim,
|
||||
/// only where upstream reaches the cross-tangent approximation: HANG-39.)
|
||||
fn refused_input(op: &OpIn) -> Option<Output> {
|
||||
match op {
|
||||
OpIn::ParallelProj { tol, ang, .. }
|
||||
if tol.is_some_and(|t| t < f64::MIN_POSITIVE) || ang.is_some_and(|a| a <= 0.0) =>
|
||||
{
|
||||
Some(Output::rejected(
|
||||
"projection tolerance the FFI refuses (non-positive, or subnormal: HANG-32)",
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn no_entity() -> Output {
|
||||
Output::rejected("no entity of the op's kind in this B-rep: nothing runs on either side")
|
||||
}
|
||||
@@ -649,6 +694,16 @@ fn op_args(op: &OpIn) -> Result<(Op, Vec<f64>), HarnessError> {
|
||||
a.extend([f64::from(*f), *eu1 as f64, *eu2 as f64, f64::from(*dir)]);
|
||||
Op::EdgeEdgeBlend
|
||||
}
|
||||
OpIn::EdgeEdgeBlend2 {
|
||||
other,
|
||||
eu1,
|
||||
eu2,
|
||||
dir,
|
||||
} => {
|
||||
a.extend(brep_block_of(Some(other), false, false)?);
|
||||
a.extend([*eu1 as f64, *eu2 as f64, f64::from(*dir)]);
|
||||
Op::EdgeEdgeBlend2
|
||||
}
|
||||
OpIn::ParallelProj {
|
||||
curve,
|
||||
vec,
|
||||
@@ -827,12 +882,21 @@ fn run_cpp(i: &Inputs) -> Result<Output, HarnessError> {
|
||||
let Some(op) = resolve(&i.op, c) else {
|
||||
return Ok(no_entity());
|
||||
};
|
||||
if let Some(refused) = refused_input(&op) {
|
||||
return Ok(refused);
|
||||
}
|
||||
let (code, args) = op_args(&op)?;
|
||||
let mut input = brep_block(i)?;
|
||||
input.extend(args);
|
||||
let path = path_of(i.brep.as_ref())?;
|
||||
let out = ffi::eval(code, &path, &input).map_err(|e| harness(format!("c++: {e}")))?;
|
||||
let body = out.get(1..).ok_or_else(|| harness("c++: empty output"))?;
|
||||
if matches!(op, OpIn::CornerBlend { .. }) && body.first() == Some(&HANG34_GUARD) {
|
||||
return Ok(Output::rejected(
|
||||
"HANG-39: a tangency tolerance below 1e-20 where upstream reaches the \
|
||||
cross-tangent approximation (tens of seconds or more): nothing runs on either side",
|
||||
));
|
||||
}
|
||||
Ok(guarded_output(body.to_vec()))
|
||||
}
|
||||
|
||||
@@ -1872,6 +1936,12 @@ fn run_rust_op(
|
||||
}
|
||||
}
|
||||
Err(e) if e.is_unported() => return Err(e.into()),
|
||||
// UB-195: an empty rational-curve drop is where upstream reads sUVCurves[0]
|
||||
// of an empty array; the port's InvalidInput there is that null dereference
|
||||
Err(SolidError::InvalidInput {
|
||||
operation: "nurbs::b_spline_surface_n_lib::p1::create_non_rational_curve",
|
||||
..
|
||||
}) => o.extend([NULL_DEREF, 0.0]),
|
||||
// upstream resets the output array before failing
|
||||
Err(e) => o.extend([status_of(&e), 0.0]),
|
||||
}
|
||||
@@ -1885,9 +1955,42 @@ fn run_rust_op(
|
||||
let id = |i: i64| (i >= 0).then(|| EdgeuseId::from_index(i as u32));
|
||||
match bp1::create_edge_edge_blend(
|
||||
k,
|
||||
b,
|
||||
u64::from(*f),
|
||||
b,
|
||||
id(*eu1),
|
||||
None,
|
||||
id(*eu2),
|
||||
u64::from(*dir),
|
||||
None,
|
||||
) {
|
||||
Ok(s) => {
|
||||
o.push(0.0);
|
||||
put_surface(&mut o, &s)?;
|
||||
}
|
||||
Err(e) if e.is_unported() => return Err(e.into()),
|
||||
Err(e) => o.push(status_of(&e)),
|
||||
}
|
||||
}
|
||||
OpIn::EdgeEdgeBlend2 {
|
||||
other,
|
||||
eu1,
|
||||
eu2,
|
||||
dir,
|
||||
} => {
|
||||
// the second B-rep in its own arena, imported from its own C++ export
|
||||
let block2 = brep_block_of(Some(other), false, false)?;
|
||||
let ex2 = ffi::eval(Op::Export, "", &block2)
|
||||
.map_err(|e| harness(format!("c++ export of the second B-rep: {e}")))?;
|
||||
let (_, graph_at2) =
|
||||
ffi::counts(&ex2).ok_or_else(|| harness("the second B-rep does not build"))?;
|
||||
let (mut b2, _) = import(&ex2, graph_at2)?;
|
||||
let id = |i: i64| (i >= 0).then(|| EdgeuseId::from_index(i as u32));
|
||||
match bp1::create_edge_edge_blend(
|
||||
k,
|
||||
0,
|
||||
b,
|
||||
id(*eu1),
|
||||
Some(&mut b2),
|
||||
id(*eu2),
|
||||
u64::from(*dir),
|
||||
None,
|
||||
@@ -1986,6 +2089,9 @@ fn run_rust(i: &Inputs) -> Result<Output, HarnessError> {
|
||||
let Some(op) = resolve(&i.op, c) else {
|
||||
return Ok(no_entity());
|
||||
};
|
||||
if let Some(refused) = refused_input(&op) {
|
||||
return Ok(refused);
|
||||
}
|
||||
let mut k = Kernel::default();
|
||||
match run_rust_op(&mut k, &mut b, &types, &op) {
|
||||
Ok(Ok(o)) => Ok(guarded_output(o)),
|
||||
|
||||
@@ -696,7 +696,7 @@ fn read_curve(rd: &mut Rd<'_>, uv: bool) -> Result<Option<SmCurve>, HarnessError
|
||||
return Err(harness("export: CrvOnSurf base is not a B-spline surface"));
|
||||
};
|
||||
let k = Kernel::default();
|
||||
let cos = CrvOnSurf::new(&k, uv_curve, base.clone(), None, 0)
|
||||
let cos = CrvOnSurf::new(&k, uv_curve, base.clone(), None, 1)
|
||||
.map_err(|e| harness(format!("export CrvOnSurf: {e}")))?;
|
||||
return Ok(Some(SmCurve::from(cos)));
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ use solidcore::topology::proto_topology::p1::{
|
||||
VertexDefId,
|
||||
VertexDefinition,
|
||||
};
|
||||
use solidcore::topology::proto_topology::p3::NoMates;
|
||||
use solidcore::topology::topology::{Topology, TopologyRecords};
|
||||
use solidcore::SolidError;
|
||||
use solidcore_ffi::units::topology_proto_topology_p1::{
|
||||
@@ -3700,7 +3701,10 @@ fn run_proto(
|
||||
}
|
||||
if !skip {
|
||||
// (the shim's intersector relates nothing: GetOtherMate is always null)
|
||||
match st3(r.mgr.glue_coincident_brep_vertices(k, &r.pool, &mut solidcore::topology::proto_topology::p3::NoMates))? {
|
||||
let glued = r
|
||||
.mgr
|
||||
.glue_coincident_brep_vertices(k, &r.pool, &mut NoMates);
|
||||
match st3(glued)? {
|
||||
Ok(deleted) => {
|
||||
let ids = r.kill_curves(deleted);
|
||||
out.push(ids.len() as f64);
|
||||
|
||||
@@ -307,18 +307,14 @@ fn is_unit(v: [f64; 3]) -> bool {
|
||||
(v.iter().map(|c| c * c).sum::<f64>().sqrt() - 1.0).abs() <= 1e-9
|
||||
}
|
||||
|
||||
/// Largest distance from the view plane at which the eye of
|
||||
/// `SM_SO_PERSPECTIVE_INTERSECT` counts as lying on it.
|
||||
const EYE_ON_PLANE_TOL: f64 = 1e-3;
|
||||
|
||||
/// The contract of the projected intersections (ops 16, 17 and 18): upstream
|
||||
/// asserts unit vectors (`GlobalCurveSolve` asserts `|cpOptVectors[0]| == 1`,
|
||||
/// `SmVector3d::PerspectiveProjectPointToPlane` a unit normal) and the solver does
|
||||
/// not unitize the view-plane normal (16), the rotation axis and plane x axis (17)
|
||||
/// or the plane normal (18), so non-unit ones are outside the contract. A
|
||||
/// perspective eye on (or within [`EYE_ON_PLANE_TOL`] of) the view plane is also
|
||||
/// excluded: Rust and C++ disagree there, see
|
||||
/// <https://github.com/tangency-labs/solidcore/issues/59>.
|
||||
/// perspective eye on the view plane is allowed: the projections collapse onto
|
||||
/// the eye or turn into NaN, which upstream handles deterministically
|
||||
/// (<https://github.com/tangency-labs/solidcore/issues/59>).
|
||||
fn check_projection_vectors(code: i32, vecs: &[[f64; 3]; 3]) -> Result<(), FfiError> {
|
||||
let [v0, v1, v2] = *vecs;
|
||||
let units_ok = match code {
|
||||
@@ -330,14 +326,6 @@ fn check_projection_vectors(code: i32, vecs: &[[f64; 3]; 3]) -> Result<(), FfiEr
|
||||
if !units_ok {
|
||||
return Err(bad("projection option vectors must be unit vectors"));
|
||||
}
|
||||
if code == 18 {
|
||||
let dist = (v2[0] - v0[0]) * v1[0] + (v2[1] - v0[1]) * v1[1] + (v2[2] - v0[2]) * v1[2];
|
||||
if dist.abs() <= EYE_ON_PLANE_TOL {
|
||||
return Err(bad(
|
||||
"perspective eye on the view plane (solidcore issue #59)",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,9 @@
|
||||
//! | `Redistribute` | `edge has_uv seam u0 v0 u1 v1` | `0 swapped`, or `-3` where the Rust side defers (`sm_RedistributeSeamUVTrimCurves`) |
|
||||
//! | `SplitUv` | `eu_orig eu_new P[3] t scaled_zero orient for_tess` | `status`, both edge uses' states (as `topology.edgeuse_p1`'s `SetUv`), both edge tolerances (`sm_MakeVertexSplitUVTrimCurve`) |
|
||||
//! | `BrepIntersect`| `tol ang want_points` | `status n_curves n_points` (with itself; `-3` when the B-rep has faces) |
|
||||
//! | `CornerBlend` | `n eu*n has_tan nt tan*nt tol ang` | `status n_surfaces` (`-3` for two or more edge uses) |
|
||||
//! | `EdgeEdgeBlend`| `flag eu1 eu2 dir` | `status [surface block]` (ruled surfaces; `-3` for a blend) |
|
||||
//! | `CornerBlend` | `n eu*n has_tan nt tan*nt tol ang` | `status n_surfaces surface*n` (`-2` before an upstream null dereference) |
|
||||
//! | `EdgeEdgeBlend`| `flag eu1 eu2 dir` | `status [surface block]` |
|
||||
//! | `EdgeEdgeBlend2`| `[second B-rep block] eu1 eu2 dir` | `status [surface block]` (ruled; `eu2` in the second B-rep) |
|
||||
//! | `ParallelProj` | `curve V[3] has_dist dist has_tol tol has_ang ang want_3d want_uv want_faces` | `status [n3d (curve id)*n3d nuv (curve id)*nuv nf face*nf]` |
|
||||
//! | `Heal` | `op make_uv` | `status [healed B-rep]` (`SmBrep::HealBrep` always returns `SM_SUCCESS`; the healed B-rep follows: the `Export` extras, then the shim's `put_healed` fields) |
|
||||
//!
|
||||
@@ -82,6 +83,7 @@ pub enum Op {
|
||||
EdgeEdgeBlend = 24,
|
||||
ParallelProj = 25,
|
||||
Heal = 26,
|
||||
EdgeEdgeBlend2 = 27,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
@@ -192,7 +194,9 @@ fn attribute_id(rd: &mut Reader<'_>) -> Result<(), FfiError> {
|
||||
fn brep_args(op: Op, rd: &mut Reader<'_>, c: [usize; 10]) -> Result<(), FfiError> {
|
||||
let [n_r, _, _, n_f, _, n_l, n_eu, n_e, n_vu, n_v] = c;
|
||||
match op {
|
||||
Op::Export | Op::LockBox => {}
|
||||
// (EdgeEdgeBlend2's second B-rep block is checked in `eval`: it needs that B-rep's
|
||||
// counts)
|
||||
Op::Export | Op::LockBox | Op::EdgeEdgeBlend2 => {}
|
||||
Op::Lists => {
|
||||
rd.index(9)?;
|
||||
attribute_id(rd)?;
|
||||
@@ -340,6 +344,8 @@ fn brep_args(op: Op, rd: &mut Reader<'_>, c: [usize; 10]) -> Result<(), FfiError
|
||||
return Err(bad("fewer tangency flags than edge uses"));
|
||||
}
|
||||
rd.finite()?;
|
||||
// (HANG-39: the shim rejects a tangency tolerance below 1e-20 only where
|
||||
// upstream reaches the cross-tangent approximation)
|
||||
rd.finite()?;
|
||||
}
|
||||
Op::EdgeEdgeBlend => {
|
||||
@@ -354,13 +360,15 @@ fn brep_args(op: Op, rd: &mut Reader<'_>, c: [usize; 10]) -> Result<(), FfiError
|
||||
rd.flag()?;
|
||||
rd.finite()?;
|
||||
// a used approximation or angle tolerance must be positive (the projector
|
||||
// subdivides to it)
|
||||
// subdivides to it); a subnormal approximation tolerance spins upstream (HANG-32)
|
||||
let has_tol = rd.flag()?;
|
||||
let tol = rd.finite()?;
|
||||
let has_ang = rd.flag()?;
|
||||
let ang = rd.finite()?;
|
||||
if (has_tol && tol <= 0.0) || (has_ang && ang <= 0.0) {
|
||||
return Err(bad("projection tolerances must be positive"));
|
||||
if (has_tol && tol < f64::MIN_POSITIVE) || (has_ang && ang <= 0.0) {
|
||||
return Err(bad(
|
||||
"projection tolerances must be positive (approximation: normal, HANG-32)",
|
||||
));
|
||||
}
|
||||
rd.flag()?;
|
||||
rd.flag()?;
|
||||
@@ -407,6 +415,17 @@ pub fn eval(op: Op, path: &str, input: &[f64]) -> Result<Vec<f64>, FfiError> {
|
||||
let mut rd = Reader { input, at: 0 };
|
||||
brep_block(&mut rd, path)?;
|
||||
let block = input.get(..rd.at).ok_or_else(|| bad("input too short"))?;
|
||||
// HANG-29 (#147): building a face block whose surface has a value near the top of the
|
||||
// double range (a control point at 1e300) never returns: SmFace::CreateUVTrimCurves ->
|
||||
// DropAndTrimCurve -> SmCurve::GlobalCoincidenceChecker recurses without bound. Every
|
||||
// op builds the block, so bound every block value (the +-f64::MAX entries are the
|
||||
// no-weight / no-z sentinels)
|
||||
if block
|
||||
.iter()
|
||||
.any(|v| v.abs() > MAX_BLOCK_COORD && v.abs() != f64::MAX)
|
||||
{
|
||||
return Err(bad("B-rep block value beyond 1e150 (HANG-29)"));
|
||||
}
|
||||
let export = raw(Op::Export, path, block)?;
|
||||
if op == Op::Export {
|
||||
rd.done()?;
|
||||
@@ -417,6 +436,29 @@ pub fn eval(op: Op, path: &str, input: &[f64]) -> Result<Vec<f64>, FfiError> {
|
||||
return Ok(export);
|
||||
};
|
||||
brep_args(op, &mut rd, c)?;
|
||||
if op == Op::EdgeEdgeBlend2 {
|
||||
// a ruled CreateEdgeEdgeBlend with eu2 in a second B-rep (not a file block)
|
||||
let at = rd.at;
|
||||
brep_block(&mut rd, "")?;
|
||||
let block2 = input.get(at..rd.at).ok_or_else(|| bad("input too short"))?;
|
||||
if block2
|
||||
.iter()
|
||||
.any(|v| v.abs() > MAX_BLOCK_COORD && v.abs() != f64::MAX)
|
||||
{
|
||||
return Err(bad("second B-rep block value beyond 1e150 (HANG-29)"));
|
||||
}
|
||||
let export2 = raw(Op::Export, "", block2)?;
|
||||
let Some((c2, _)) = counts(&export2) else {
|
||||
return Err(bad("the second B-rep block does not build"));
|
||||
};
|
||||
rd.below(c[6])?;
|
||||
rd.below(c2[6])?;
|
||||
rd.index(2)?;
|
||||
}
|
||||
rd.done()?;
|
||||
raw(op, path, input)
|
||||
}
|
||||
|
||||
/// The largest B-rep block value the shim is given (HANG-29: face surfaces at 1e154 and
|
||||
/// beyond recurse without bound while their UV trim curves are built).
|
||||
pub const MAX_BLOCK_COORD: f64 = 1e150;
|
||||
|
||||
@@ -1056,6 +1056,60 @@ impl TopologyObjects<H> for ArenaPair<'_> {
|
||||
}
|
||||
|
||||
impl IntersectorBrepP2<H> for ArenaPair<'_> {
|
||||
fn brep_faces(&self, brep: H) -> crate::Result<Vec<H>> {
|
||||
let b = self.brep_r(brep)?;
|
||||
Ok(bp1::faces(b, None)?
|
||||
.into_iter()
|
||||
.map(|f| hd(brep.b, K_FACE, f.index()))
|
||||
.collect())
|
||||
}
|
||||
fn brep_combine_coincident_vertices(
|
||||
&mut self,
|
||||
k: &mut Kernel,
|
||||
brep: H,
|
||||
surviving: H,
|
||||
to_delete: H,
|
||||
) -> crate::Result<Option<H>> {
|
||||
if brep.kind != K_BREP {
|
||||
return Err(invalid("not a B-rep handle"));
|
||||
}
|
||||
let vertex = |h: H| -> crate::Result<VertexId> {
|
||||
if h.kind == K_VERTEX && h.b == brep.b {
|
||||
Ok(vid(h))
|
||||
} else {
|
||||
Err(invalid("not a vertex of this B-rep"))
|
||||
}
|
||||
};
|
||||
let (surviving, to_delete) = (vertex(surviving)?, vertex(to_delete)?);
|
||||
let slot = usize::try_from(brep.b).map_err(|_| invalid("bad B-rep"))?;
|
||||
let breps = &mut self.breps;
|
||||
let b = breps
|
||||
.get_mut(slot)
|
||||
.and_then(Option::as_deref_mut)
|
||||
.ok_or_else(|| invalid("handle names an absent B-rep"))?;
|
||||
let mut notify = ed::NotifyEnv {
|
||||
records: self.records,
|
||||
attributes: self.attributes,
|
||||
context: Some(if brep.b == 1 {
|
||||
self.other_context
|
||||
.as_deref_mut()
|
||||
.unwrap_or(self.primary_context)
|
||||
} else {
|
||||
self.primary_context
|
||||
}),
|
||||
key_of: &|e| super::kernel_adapter::notification_key(self.namespace, brep.b == 1, e),
|
||||
};
|
||||
let mut deleted_edge = None;
|
||||
crate::topology::brep::p5::combine_with_notifications(
|
||||
k,
|
||||
b,
|
||||
surviving,
|
||||
to_delete,
|
||||
&mut deleted_edge,
|
||||
Some(&mut notify),
|
||||
)?;
|
||||
Ok(deleted_edge.map(|e| hd(brep.b, K_EDGE, e.index())))
|
||||
}
|
||||
fn vertex_edges(&self, vertex: H) -> crate::Result<Vec<H>> {
|
||||
let b = self.brep_r(vertex)?;
|
||||
Ok(vx::edges(b, vid(vertex), None)?
|
||||
|
||||
@@ -375,7 +375,7 @@ impl ManifoldIntersector for KernelManifoldIntersector {
|
||||
&mut self.intersector,
|
||||
arena_pair::encode,
|
||||
arena_pair::decode,
|
||||
|ti| ti.fix_gaps(&mut pair, &vertices),
|
||||
|ti| ti.fix_gaps(k, &mut pair, &vertices),
|
||||
)
|
||||
.and_then(|out| {
|
||||
Ok(FixedGaps {
|
||||
@@ -1034,16 +1034,21 @@ mod tests {
|
||||
adapter
|
||||
.delete_faces(&mut kernels, &mut a, &mut attrs, &[], Some(&[]))
|
||||
.unwrap();
|
||||
// (SmBrep::GetFaces is wired since #274, so the walk now reaches the test's
|
||||
// surface-less faces, which upstream dereferences)
|
||||
let err = adapter
|
||||
.intersect_insert_relate(&mut kernels, &mut a, &mut b, &mut attrs)
|
||||
.unwrap_err();
|
||||
assert!(matches!(
|
||||
err,
|
||||
SolidError::Unported {
|
||||
unit: "topology.brep_p1",
|
||||
upstream: "SmBrep::GetFaces"
|
||||
}
|
||||
));
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
SolidError::InvalidInput {
|
||||
operation: "boolean::topology_intersector::p2::intersect_topology",
|
||||
..
|
||||
}
|
||||
),
|
||||
"{err:?}"
|
||||
);
|
||||
assert!(adapter.intersector.proto_topology_manager().is_some());
|
||||
assert_eq!(adapter.merge.intersector.vertices.other(v), Some(ov));
|
||||
assert_eq!(adapter.merge.intersector.vertices.primary(ov), Some(v));
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
//! Deviations:
|
||||
//! - **Handles and B-reps** as in [`p1`](super::p1): objects are handles `O`, the
|
||||
//! B-reps are read and edited through [`IntersectorBrep`] plus [`IntersectorBrepP2`]
|
||||
//! (`SmVertex::GetEdges` / `GetFaces`). `IntersectInsertRelate` takes the handle
|
||||
//! the manager stores for the intersector (`pTI`).
|
||||
//! (`SmVertex::GetEdges` / `GetFaces`, `SmBrep::GetFaces` /
|
||||
//! `CombineCoincidentVertices`). `IntersectInsertRelate`
|
||||
//! takes the handle the manager stores for the intersector (`pTI`).
|
||||
//! - **Out-params** become return values ([`SqueezeVertices`], [`FixGaps`],
|
||||
//! [`EdgeEdgeIntersect`], [`EdgeFaceCoincidence`], `bool` for
|
||||
//! `bChangedClassifications`); on an error status the partly filled out-lists are
|
||||
@@ -57,15 +58,16 @@
|
||||
//! original edge after `MakeEdgeInFace`; the port has no curve owners (the curve
|
||||
//! copy is a new handle), so there is nothing to reset.
|
||||
//! - **Callees not ported yet** are private stubs returning [`SolidError::Unported`],
|
||||
//! each tagged `UNPORTED(<unit>)`: `SmBrep::GetFaces` (`topology.brep_p1`),
|
||||
//! `SmBrep::DeleteFace` (`topology.brep_p3`), `SmBrep::DeleteEdge` /
|
||||
//! `DeleteVertex` (`topology.brep_p4`), `SmBrep::CombineCoincidentVertices`
|
||||
//! (`topology.brep_p5`), `SmFace::Point3DClassify` (`query.face_p1`), and the
|
||||
//! stubs of [`p1`](super::p1) for `SmFace::GetEdges` / `GetVertices` / `GetBrep`
|
||||
//! (`topology.face_p4`), `SmFace::FaceIntersect` (`topology.face_p3`),
|
||||
//! `SmBrep::MakeEdgeInFace` (`topology.brep_p5`). The code after a stub is ported
|
||||
//! in full. `SmBrep::GlueEdgesGeneral` (`topology.brep_p7`) goes through
|
||||
//! [`IntersectorBrep::brep_glue_edges_general`], as in part 1.
|
||||
//! each tagged `UNPORTED(<unit>)`: `SmBrep::DeleteFace` (`topology.brep_p3`),
|
||||
//! `SmBrep::DeleteEdge` / `DeleteVertex` (`topology.brep_p4`),
|
||||
//! `SmFace::Point3DClassify` (`query.face_p1`), and the stubs of [`p1`](super::p1)
|
||||
//! for `SmFace::GetEdges` / `GetVertices` / `GetBrep` (`topology.face_p4`) and
|
||||
//! `SmFace::FaceIntersect` (`topology.face_p3`). The code after a stub is ported in
|
||||
//! full. `SmBrep::GlueEdgesGeneral` (`topology.brep_p7`) goes through
|
||||
//! [`IntersectorBrep::brep_glue_edges_general`] and `SmBrep::MakeEdgeInFace`
|
||||
//! (`topology.brep_p5`) through part 1's `brep_make_edge_in_face`, as in part 1;
|
||||
//! `SmBrep::CombineCoincidentVertices` (`topology.brep_p5`) goes through
|
||||
//! [`IntersectorBrepP2::brep_combine_coincident_vertices`].
|
||||
//! - **Undefined behaviour upstream** (a null or deleted object dereferenced, an
|
||||
//! index past a list, a vertex mated to a non-vertex used as a vertex) is
|
||||
//! [`SolidError::InvalidInput`].
|
||||
@@ -97,9 +99,9 @@ use crate::topology::proto_topology::p3::Mates;
|
||||
use crate::topology::proto_topology::{ProtoEdgeId, ProtoTopologyManager, ProtoVertexId};
|
||||
|
||||
use super::p1::{
|
||||
add_unique, brep_make_edge_in_face, can_imprint, contains, dangling, eval_curve_point,
|
||||
face_brep, face_edges, face_face_intersect_curves, face_vertices, find_common_elements,
|
||||
ignore_soft, intersect_shell_vertices, intersect_wire_lamina_edges, surface_coincidence_check,
|
||||
add_unique, brep_make_edge_in_face, can_imprint, contains, eval_curve_point, face_brep,
|
||||
face_edges, face_face_intersect_curves, face_vertices, find_common_elements, ignore_soft,
|
||||
intersect_shell_vertices, intersect_wire_lamina_edges, surface_coincidence_check,
|
||||
FaceIntersectOutputs, IntersectionCurves, IntersectionResults, IntersectorBrep,
|
||||
TopologyIntersector,
|
||||
};
|
||||
@@ -112,6 +114,20 @@ const OP_CLASS_MATES: &str = "boolean::topology_intersector::p2::fixup_class_mat
|
||||
const OP_SPLIT_PAIR: &str = "boolean::topology_intersector::p2::fixup_split_vertex_pair";
|
||||
const OP_EDGE_EDGE: &str = "boolean::topology_intersector::p2::edge_edge_intersect";
|
||||
const OP_EDGE_FACE_COIN: &str = "boolean::topology_intersector::p2::edge_face_coincidence";
|
||||
const OP_DELETE_FACES: &str = "boolean::topology_intersector::p2::delete_faces";
|
||||
const OP_INSERT_RELATE: &str = "boolean::topology_intersector::p2::intersect_insert_relate";
|
||||
const OP_INTERSECT_TOPOLOGY: &str = "boolean::topology_intersector::p2::intersect_topology";
|
||||
const OP_SET_RELS: &str = "boolean::topology_intersector::p2::set_relationships";
|
||||
const OP: &str = "boolean::topology_intersector::p2";
|
||||
|
||||
/// The error for a handle or state upstream dereferences without checking (part 1's
|
||||
/// `dangling`, with `op` naming the part 2 function).
|
||||
const fn invalid(op: &'static str, reason: &'static str) -> SolidError {
|
||||
SolidError::InvalidInput {
|
||||
operation: op,
|
||||
reason,
|
||||
}
|
||||
}
|
||||
|
||||
/// Most edges the working lists of [`TopologyIntersector::edge_edge_intersect`] may
|
||||
/// hold (the inputs plus every split edge appended again); a bound of the port.
|
||||
@@ -134,6 +150,32 @@ pub trait IntersectorBrepP2<O>: IntersectorBrep<O> {
|
||||
///
|
||||
/// Those of the topology walk.
|
||||
fn vertex_faces(&self, vertex: O) -> Result<Vec<O>>;
|
||||
/// The faces of `brep` in its list order (`SmBrep::GetFaces(rFaces)` with no
|
||||
/// attribute filter, unit `topology.brep_p1`: `topology::brep::p1::faces` on the
|
||||
/// B-rep behind the handle). Upstream's `pOptAttributeId` is dropped: both
|
||||
/// callers in this file pass the default; add it if a caller needs the filtered
|
||||
/// form.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// [`SolidError::InvalidInput`] for an unknown B-rep.
|
||||
fn brep_faces(&self, brep: O) -> Result<Vec<O>>;
|
||||
/// `SmBrep::CombineCoincidentVertices(pSurvivingVertex, pVertexToDelete,
|
||||
/// rpDeletedEdge)` on B-rep `brep` (unit `topology.brep_p5`:
|
||||
/// `topology::brep::p5::combine_with_notifications` on the B-rep behind the
|
||||
/// handle): the deleted edge, if any (`rpDeletedEdge`, null on failure as well).
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Those of the combination; [`SolidError::InvalidInput`] for an unknown B-rep or
|
||||
/// a vertex of another B-rep.
|
||||
fn brep_combine_coincident_vertices(
|
||||
&mut self,
|
||||
k: &mut Kernel,
|
||||
brep: O,
|
||||
surviving: O,
|
||||
to_delete: O,
|
||||
) -> Result<Option<O>>;
|
||||
}
|
||||
|
||||
/// `GetOtherMate` and `RemoveRelationship` over an intersector's mate maps, for
|
||||
@@ -184,12 +226,6 @@ impl<O: Ord + Copy> Mates<O> for MapMates<O> {
|
||||
|
||||
// ---- unported callees ----------------------------------------------------------------------
|
||||
|
||||
/// `SmBrep::GetFaces(rFaces, pOptAttributeId)`.
|
||||
fn brep_faces<O>(_brep: O, _opt_attribute_id: Option<u64>) -> Result<Vec<O>> {
|
||||
// UNPORTED(topology.brep_p1): SmBrep::GetFaces
|
||||
Err(SolidError::unported("SmBrep::GetFaces", "topology.brep_p1"))
|
||||
}
|
||||
|
||||
/// `SmBrep::DeleteFace(pFace, bDeleteEdgesVertices, bDoRegionNesting,
|
||||
/// pOptDeletedEdgesVertices, pOptRegionToKeep)`: the deleted edges and vertices when
|
||||
/// they are asked for.
|
||||
@@ -226,20 +262,6 @@ fn brep_delete_vertex<O>(_brep: O, _vertex: O) -> Result<()> {
|
||||
))
|
||||
}
|
||||
|
||||
/// `SmBrep::CombineCoincidentVertices(pSurvivingVertex, pVertexToDelete,
|
||||
/// rpDeletedEdge)`: the deleted edge, if any.
|
||||
fn brep_combine_coincident_vertices<O>(
|
||||
_brep: O,
|
||||
_surviving: O,
|
||||
_to_delete: O,
|
||||
) -> Result<Option<O>> {
|
||||
// UNPORTED(topology.brep_p5): SmBrep::CombineCoincidentVertices
|
||||
Err(SolidError::unported(
|
||||
"SmBrep::CombineCoincidentVertices",
|
||||
"topology.brep_p5",
|
||||
))
|
||||
}
|
||||
|
||||
/// `SmFace::Point3DClassify(pt, sSrcZoneTol3d, bDoBoundaryIntersections, rPC,
|
||||
/// pOptGuessUV, bTgtLoopsOnly, pOptTgtLoops, bUVSpaceOkay)`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -348,14 +370,14 @@ pub struct EdgeFaceCoincidence<O> {
|
||||
/// The tolerance of a vertex, edge or face handle (`GetTolerance`).
|
||||
fn tol_of<O: Copy>(brep: &impl IntersectorBrep<O>, topo: O) -> Result<f64> {
|
||||
brep.topology_tolerance(topo)
|
||||
.ok_or(dangling("topology handle is unknown"))
|
||||
.ok_or(invalid(OP, "topology handle is unknown"))
|
||||
}
|
||||
|
||||
/// The curve behind a handle (a null dereference upstream for none).
|
||||
fn curve_of<O: Copy>(geometry: &impl ClassGeometry<O>, curve: Option<O>) -> Result<&Curve> {
|
||||
curve
|
||||
.and_then(|c| geometry.curve(c))
|
||||
.ok_or(dangling("curve handle cannot be resolved"))
|
||||
.ok_or(invalid(OP, "curve handle cannot be resolved"))
|
||||
}
|
||||
|
||||
impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
@@ -406,9 +428,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
*slot = Some(copy);
|
||||
}
|
||||
for uv in [&mut c.uv_curves1, &mut c.uv_curves2] {
|
||||
let slot = uv
|
||||
.get_mut(ii)
|
||||
.ok_or(dangling("UV curve list shorter than the 3D list"))?;
|
||||
let slot = uv.get_mut(ii).ok_or(invalid(
|
||||
OP_REGISTER,
|
||||
"UV curve list shorter than the 3D list",
|
||||
))?;
|
||||
if let Some(h) = Self::b_spline_copy(geometry, *slot)? {
|
||||
*slot = Some(h);
|
||||
}
|
||||
@@ -453,7 +476,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
fn as_vertex(mate: Option<O>) -> Result<Option<O>> {
|
||||
match mate {
|
||||
Some(m) if m.class_kind() != ClassObjectKind::Vertex => {
|
||||
Err(dangling("vertex mated to a non-vertex"))
|
||||
Err(invalid(OP, "vertex mated to a non-vertex"))
|
||||
}
|
||||
m => Ok(m),
|
||||
}
|
||||
@@ -469,17 +492,18 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
///
|
||||
/// `SM_ERR` when an existing relationship is better (closer by more than
|
||||
/// `SM_EFF_ZERO_SQRT`); those of `RemoveRelationship` and
|
||||
/// `CombineCoincidentVertices` ([`SolidError::Unported`], `topology.brep_p5`);
|
||||
/// [`IntersectorBrepP2::brep_combine_coincident_vertices`];
|
||||
/// [`SolidError::InvalidInput`] for an unknown vertex, a mate that is not a vertex
|
||||
/// or a missing B-rep.
|
||||
pub fn check_for_squeeze_vertices(
|
||||
&mut self,
|
||||
brep: &mut impl IntersectorBrep<O>,
|
||||
k: &mut Kernel,
|
||||
brep: &mut impl IntersectorBrepP2<O>,
|
||||
brep_vertex: O,
|
||||
other_vertex: O,
|
||||
) -> Result<SqueezeVertices<O>> {
|
||||
let mut out = SqueezeVertices::default();
|
||||
self.check_for_squeeze_vertices_into(brep, brep_vertex, other_vertex, &mut out)?;
|
||||
self.check_for_squeeze_vertices_into(k, brep, brep_vertex, other_vertex, &mut out)?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
@@ -493,7 +517,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
/// As [`TopologyIntersector::check_for_squeeze_vertices`].
|
||||
pub fn check_for_squeeze_vertices_into(
|
||||
&mut self,
|
||||
brep: &mut impl IntersectorBrep<O>,
|
||||
k: &mut Kernel,
|
||||
brep: &mut impl IntersectorBrepP2<O>,
|
||||
brep_vertex: O,
|
||||
other_vertex: O,
|
||||
out: &mut SqueezeVertices<O>,
|
||||
@@ -523,9 +548,9 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
self.remove_relationship(Some(brep_vertex), Some(other_v))?;
|
||||
|
||||
// Combine two vertices which are coincident or nearly so
|
||||
let other = self.other.ok_or(dangling("no other B-rep"))?;
|
||||
let other = self.other.ok_or(invalid(OP_SQUEEZE, "no other B-rep"))?;
|
||||
let deleted_other_edge =
|
||||
brep_combine_coincident_vertices(other, other_vertex, other_v)?;
|
||||
brep.brep_combine_coincident_vertices(k, other, other_vertex, other_v)?;
|
||||
if let Some(e) = deleted_other_edge {
|
||||
out.deleted_edges.push(e);
|
||||
if let Some(b) = self.brep_mate(Some(e)) {
|
||||
@@ -540,7 +565,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
|
||||
// Check for a pre-existing, conflicting relationship.
|
||||
if let Some(brep_v) = brep_v.filter(|&v| v != brep_vertex) {
|
||||
let brep_v = Self::as_vertex(Some(brep_v))?.ok_or(dangling("no B-rep mate"))?;
|
||||
let brep_v =
|
||||
Self::as_vertex(Some(brep_v))?.ok_or(invalid(OP_SQUEEZE, "no B-rep mate"))?;
|
||||
tol_of(brep, brep_v)?;
|
||||
|
||||
let p = brep.vertex_point(other_vertex)?;
|
||||
@@ -552,8 +578,9 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
|
||||
self.remove_relationship(Some(brep_v), Some(other_vertex))?;
|
||||
|
||||
let this = self.brep.ok_or(dangling("no B-rep"))?;
|
||||
let deleted_brep_edge = brep_combine_coincident_vertices(this, brep_vertex, brep_v)?;
|
||||
let this = self.brep.ok_or(invalid(OP_SQUEEZE, "no B-rep"))?;
|
||||
let deleted_brep_edge =
|
||||
brep.brep_combine_coincident_vertices(k, this, brep_vertex, brep_v)?;
|
||||
if let Some(e) = deleted_brep_edge {
|
||||
out.deleted_edges.push(e);
|
||||
if let Some(o) = self.other_mate(Some(e)) {
|
||||
@@ -609,7 +636,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
|
||||
// TargetFace->Brep - to edit
|
||||
face_brep_h = face_brep(f)?;
|
||||
let b = face_brep_h.ok_or(dangling("face without B-rep"))?;
|
||||
let b = face_brep_h.ok_or(invalid(OP_DELETE_FACES, "face without B-rep"))?;
|
||||
|
||||
// delete TargetFace from its Brep (FALSE = don't delete dangling edges and
|
||||
// vertices, we do that below in accordance with pOptKeepAsWires; the rest
|
||||
@@ -639,7 +666,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
// delete the Edge from the Brep
|
||||
let b = brep
|
||||
.edge_brep_handle(e)?
|
||||
.ok_or(dangling("edge without B-rep"))?;
|
||||
.ok_or(invalid(OP_DELETE_FACES, "edge without B-rep"))?;
|
||||
brep_delete_edge(b, e, None)?;
|
||||
}
|
||||
|
||||
@@ -653,7 +680,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
}
|
||||
let b = brep
|
||||
.vertex_brep(v)?
|
||||
.ok_or(dangling("vertex without B-rep"))?;
|
||||
.ok_or(invalid(OP_DELETE_FACES, "vertex without B-rep"))?;
|
||||
brep_delete_vertex(b, v)?;
|
||||
}
|
||||
|
||||
@@ -668,12 +695,13 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
/// # Errors
|
||||
///
|
||||
/// `SM_ERR_NULL_POINTER` when a candidate vertex has no mate; those of
|
||||
/// `CombineCoincidentVertices` ([`SolidError::Unported`], `topology.brep_p5`) and
|
||||
/// of the edge length; [`SolidError::InvalidInput`] for an unknown handle, an edge
|
||||
/// without curve, a mate that is not a vertex or a missing B-rep.
|
||||
/// [`IntersectorBrepP2::brep_combine_coincident_vertices`] and of the edge length;
|
||||
/// [`SolidError::InvalidInput`] for an unknown handle, an edge without curve, a mate
|
||||
/// that is not a vertex or a missing B-rep.
|
||||
#[allow(clippy::neg_cmp_op_on_partial_ord)] // upstream's NaN-safe test
|
||||
pub fn fix_gaps(
|
||||
&mut self,
|
||||
k: &mut Kernel,
|
||||
brep: &mut impl IntersectorBrepP2<O>,
|
||||
single_vertices: &[O],
|
||||
) -> Result<FixGaps<O>> {
|
||||
@@ -682,9 +710,13 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
|
||||
// Look for gaps bigger than the sum of the two vertices' tolerances.
|
||||
for ii in 0..num_single_verts {
|
||||
let v1 = *single_vertices.get(ii).ok_or(dangling("vertex list"))?;
|
||||
let v1 = *single_vertices
|
||||
.get(ii)
|
||||
.ok_or(invalid(OP_FIX_GAPS, "vertex list"))?;
|
||||
for jj in ii + 1..num_single_verts {
|
||||
let v2 = *single_vertices.get(jj).ok_or(dangling("vertex list"))?;
|
||||
let v2 = *single_vertices
|
||||
.get(jj)
|
||||
.ok_or(invalid(OP_FIX_GAPS, "vertex list"))?;
|
||||
|
||||
// Increase tol just a bit. Was 10.0. [B498]
|
||||
let tol_factor = 1.01;
|
||||
@@ -704,10 +736,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
if contains(&edges2, &test) {
|
||||
let curve = brep
|
||||
.edge_curve(test)
|
||||
.ok_or(dangling("edge handle is unknown"))?;
|
||||
.ok_or(invalid(OP_FIX_GAPS, "edge handle is unknown"))?;
|
||||
let ivl = brep
|
||||
.edge_interval(test)
|
||||
.ok_or(dangling("edge handle is unknown"))?;
|
||||
.ok_or(invalid(OP_FIX_GAPS, "edge handle is unknown"))?;
|
||||
let edge_leng = curve_of(brep, curve)?
|
||||
.approximate_length(&ivl, 10, false)?
|
||||
.0;
|
||||
@@ -731,14 +763,15 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
Self::as_vertex(Some(other_v2))?;
|
||||
|
||||
// combine coincident vertices
|
||||
let this = self.brep.ok_or(dangling("no B-rep"))?;
|
||||
let deleted_brep_edge = brep_combine_coincident_vertices(this, v2, v1)?;
|
||||
let this = self.brep.ok_or(invalid(OP_FIX_GAPS, "no B-rep"))?;
|
||||
let deleted_brep_edge =
|
||||
brep.brep_combine_coincident_vertices(k, this, v2, v1)?;
|
||||
out.deleted_vertices.push(v1);
|
||||
out.deleted_edges.push(deleted_brep_edge);
|
||||
|
||||
let other = self.other.ok_or(dangling("no other B-rep"))?;
|
||||
let other = self.other.ok_or(invalid(OP_FIX_GAPS, "no other B-rep"))?;
|
||||
let deleted_other_edge =
|
||||
brep_combine_coincident_vertices(other, other_v2, other_v1)?;
|
||||
brep.brep_combine_coincident_vertices(k, other, other_v2, other_v1)?;
|
||||
ignore_soft(self.remove_relationship(Some(v1), Some(other_v1)))?;
|
||||
if let (Some(db), Some(dother)) = (deleted_brep_edge, deleted_other_edge) {
|
||||
// If these are not already a mated pair, then calling
|
||||
@@ -783,7 +816,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
pub fn intersect_insert_relate(
|
||||
&mut self,
|
||||
k: &mut Kernel,
|
||||
brep: &mut impl IntersectorBrep<O>,
|
||||
brep: &mut impl IntersectorBrepP2<O>,
|
||||
ti: O,
|
||||
) -> Result<Vec<O>> {
|
||||
// Capture Distance (see upstream's [B669] note)
|
||||
@@ -795,8 +828,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
capture_distance = topo_int_tol * 2000.0;
|
||||
}
|
||||
|
||||
let this = self.brep.ok_or(dangling("no B-rep"))?;
|
||||
let other = self.other.ok_or(dangling("no other B-rep"))?;
|
||||
let this = self.brep.ok_or(invalid(OP_INSERT_RELATE, "no B-rep"))?;
|
||||
let other = self
|
||||
.other
|
||||
.ok_or(invalid(OP_INSERT_RELATE, "no other B-rep"))?;
|
||||
self.proto_topo_mgr = Some(ProtoTopologyManager::new(
|
||||
this,
|
||||
other,
|
||||
@@ -829,7 +864,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
}
|
||||
status?;
|
||||
if reads_freed {
|
||||
return Err(dangling(
|
||||
return Err(invalid(
|
||||
OP_INSERT_RELATE,
|
||||
"~SmProtoTopologyManager reads a freed proto edge (UB-175)",
|
||||
));
|
||||
}
|
||||
@@ -848,8 +884,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Those of `CoincidenceCheck` and `SmFace::FaceIntersect` (`SER`);
|
||||
/// [`SolidError::Unported`] for `SmBrep::GetFaces` (`topology.brep_p1`),
|
||||
/// Those of `CoincidenceCheck`, `SmFace::FaceIntersect` (`SER`) and
|
||||
/// [`IntersectorBrepP2::brep_faces`]; [`SolidError::Unported`] for
|
||||
/// `FaceIntersect` (`topology.face_p3`), `Point3DClassify` (`query.face_p1`) and
|
||||
/// the callees of [`intersect_shell_vertices`] / [`intersect_wire_lamina_edges`];
|
||||
/// [`SolidError::InvalidInput`] without a manager or B-reps, or for a face without
|
||||
@@ -858,28 +894,32 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
pub fn intersect_topology(
|
||||
&mut self,
|
||||
k: &Kernel,
|
||||
brep: &mut impl IntersectorBrep<O>,
|
||||
brep: &mut impl IntersectorBrepP2<O>,
|
||||
) -> Result<Vec<O>> {
|
||||
let approx_tol = self.this_approx_tol_3d;
|
||||
let lamina = self.intersect_lamina_edges;
|
||||
let this = self.brep.ok_or(dangling("no B-rep"))?;
|
||||
let other = self.other.ok_or(dangling("no other B-rep"))?;
|
||||
let this = self
|
||||
.brep
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no B-rep"))?;
|
||||
let other = self
|
||||
.other
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no other B-rep"))?;
|
||||
let mut deleted: Vec<O> = Vec::new();
|
||||
|
||||
// Init output
|
||||
self.proto_topo_mgr
|
||||
.as_mut()
|
||||
.ok_or(dangling("no proto topology manager"))?
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no proto topology manager"))?
|
||||
.reset();
|
||||
|
||||
let faces1 = brep_faces(this, None)?;
|
||||
let faces2 = brep_faces(other, None)?;
|
||||
let faces1 = brep.brep_faces(this)?;
|
||||
let faces2 = brep.brep_faces(other)?;
|
||||
|
||||
{
|
||||
let mgr = self
|
||||
.proto_topo_mgr
|
||||
.as_mut()
|
||||
.ok_or(dangling("no proto topology manager"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no proto topology manager"))?;
|
||||
|
||||
// Process ShellVertex Intersections (statuses unchecked).
|
||||
ignore_soft(intersect_shell_vertices(k, brep, this, other, false, mgr))?;
|
||||
@@ -901,10 +941,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
for &f2 in &faces2 {
|
||||
let s1 = brep
|
||||
.face_surface(f1)
|
||||
.ok_or(dangling("face handle is unknown"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "face handle is unknown"))?;
|
||||
let s2 = brep
|
||||
.face_surface(f2)
|
||||
.ok_or(dangling("face handle is unknown"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "face handle is unknown"))?;
|
||||
|
||||
// See if this surface/surface xsect has been saved (status unchecked;
|
||||
// the copies it makes are not deleted upstream).
|
||||
@@ -917,8 +957,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let tol = self.this_approx_tol_3d();
|
||||
|
||||
// Check for coincident surfaces -- partial coincidence is ok.
|
||||
let surf1 = s1.ok_or(dangling("face without surface"))?;
|
||||
let surf2 = s2.ok_or(dangling("face without surface"))?;
|
||||
let surf1 = s1.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "face without surface"))?;
|
||||
let surf2 = s2.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "face without surface"))?;
|
||||
let (are_coincident, _coincident_distance) =
|
||||
surface_coincidence_check(k, brep, surf1, surf2, tol, false)?;
|
||||
let mut coinc_pes = Vec::new();
|
||||
@@ -963,7 +1003,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let mgr = self
|
||||
.proto_topo_mgr
|
||||
.as_mut()
|
||||
.ok_or(dangling("no proto topology manager"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no proto topology manager"))?;
|
||||
|
||||
// for each CurveClassification pair returned from intersector
|
||||
// (SM_ASSERT(sCCs2.GetSize() == lNumCCs) only reports; a shorter
|
||||
@@ -971,7 +1011,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let num_ccs = fi.cc1.len();
|
||||
for kk in 0..num_ccs {
|
||||
let (Some(cc1), Some(cc2)) = (fi.cc1.get_mut(kk), fi.cc2.get_mut(kk)) else {
|
||||
return Err(dangling("classification lists differ"));
|
||||
return Err(invalid(
|
||||
OP_INTERSECT_TOPOLOGY,
|
||||
"classification lists differ",
|
||||
));
|
||||
};
|
||||
let num_ivls = cc1.size();
|
||||
|
||||
@@ -1066,7 +1109,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let mgr = self
|
||||
.proto_topo_mgr
|
||||
.as_mut()
|
||||
.ok_or(dangling("no proto topology manager"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "no proto topology manager"))?;
|
||||
|
||||
// 1. for every ProtoEdge pair - split ProtoEdges at ProtoEdge/ProtoEdge XSects
|
||||
// (the list is re-read after each split: splitting appends proto edges)
|
||||
@@ -1075,13 +1118,13 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let pe1 = *mgr
|
||||
.proto_edges()
|
||||
.get(ii)
|
||||
.ok_or(dangling("proto edge list"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "proto edge list"))?;
|
||||
let mut jj = ii + 1;
|
||||
while jj < mgr.proto_edges().len() {
|
||||
let pe2 = *mgr
|
||||
.proto_edges()
|
||||
.get(jj)
|
||||
.ok_or(dangling("proto edge list"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "proto edge list"))?;
|
||||
// (status unchecked)
|
||||
if let Some(d) = ignore_soft(mgr.split_intersecting_proto_edges(k, brep, pe1, pe2))?
|
||||
{
|
||||
@@ -1099,7 +1142,7 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let pv = *mgr
|
||||
.proto_vertices()
|
||||
.get(ii - 1)
|
||||
.ok_or(dangling("proto vertex list"))?;
|
||||
.ok_or(invalid(OP_INTERSECT_TOPOLOGY, "proto vertex list"))?;
|
||||
let pes = mgr.proto_edges().to_vec();
|
||||
for pe in pes {
|
||||
// a failure is FALSE (the SmBoolean function's error return)
|
||||
@@ -1133,20 +1176,20 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
let mgr = self
|
||||
.proto_topo_mgr
|
||||
.as_ref()
|
||||
.ok_or(dangling("no proto topology manager"))?;
|
||||
.ok_or(invalid(OP_SET_RELS, "no proto topology manager"))?;
|
||||
|
||||
// (the manager is not changed by Relate: collect the pairs first)
|
||||
let mut pairs: Vec<(Option<O>, Option<O>)> = Vec::new();
|
||||
for vd in mgr.all_vertex_definitions()? {
|
||||
let d = mgr
|
||||
.vertex_def(vd)
|
||||
.ok_or(dangling("vertex definition is deleted"))?;
|
||||
.ok_or(invalid(OP_SET_RELS, "vertex definition is deleted"))?;
|
||||
pairs.push((d.final_vertex(1), d.final_vertex(2)));
|
||||
}
|
||||
for ed in mgr.all_edge_definitions()? {
|
||||
let d = mgr
|
||||
.edge_def(ed)
|
||||
.ok_or(dangling("edge definition is deleted"))?;
|
||||
.ok_or(invalid(OP_SET_RELS, "edge definition is deleted"))?;
|
||||
pairs.push((d.final_edge(1), d.final_edge(2)));
|
||||
}
|
||||
|
||||
@@ -1312,11 +1355,15 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
|
||||
// drop the mated vertices to the curve to find their best projection points
|
||||
let drop = |pc: &PointClassification<O>| -> Result<(bool, f64, f64)> {
|
||||
let v = pc
|
||||
.vertex_object()
|
||||
.ok_or(dangling("vertex classification without object"))?;
|
||||
let v = pc.vertex_object().ok_or(invalid(
|
||||
OP_SPLIT_PAIR,
|
||||
"vertex classification without object",
|
||||
))?;
|
||||
if v.class_kind() != ClassObjectKind::Vertex {
|
||||
return Err(dangling("vertex classification of a non-vertex"));
|
||||
return Err(invalid(
|
||||
OP_SPLIT_PAIR,
|
||||
"vertex classification of a non-vertex",
|
||||
));
|
||||
}
|
||||
let point = geometry.vertex_point(v)?;
|
||||
let guess = pc.t_param();
|
||||
@@ -1401,10 +1448,9 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
/// # Errors
|
||||
///
|
||||
/// Unless `ignore_problems`, a failing split (`SER`); `SM_ERR` past
|
||||
/// [`MAX_EDGE_LIST`] edges; [`SolidError::Unported`] for the splits
|
||||
/// (`SmBrep::MakeVertexSplitEdge`, `topology.brep_p9`; `GlueVertices`,
|
||||
/// `topology.brep_p5`); [`SolidError::InvalidInput`] for null handles upstream
|
||||
/// dereferences.
|
||||
/// [`MAX_EDGE_LIST`] edges; those of the splits (`SmBrep::MakeVertexSplitEdge`
|
||||
/// through [`IntersectorBrep`], `GlueVertices` of `topology::brep::p5`);
|
||||
/// [`SolidError::InvalidInput`] for null handles upstream dereferences.
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn edge_edge_intersect(
|
||||
&mut self,
|
||||
@@ -1589,7 +1635,8 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
if !contains(given_verts, &other_v) {
|
||||
continue;
|
||||
}
|
||||
let other_v = other_v.ok_or(dangling("edge without other vertex"))?;
|
||||
let other_v =
|
||||
other_v.ok_or(invalid(OP_EDGE_FACE_COIN, "edge without other vertex"))?;
|
||||
|
||||
// Find all faces that contain both vertices.
|
||||
let faces1 = brep.vertex_faces(v)?;
|
||||
@@ -1605,18 +1652,18 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
// Check for coincidence of pE and pF.
|
||||
let curve_h = brep
|
||||
.edge_curve(e)
|
||||
.ok_or(dangling("edge handle is unknown"))?
|
||||
.ok_or(dangling("edge without curve"))?;
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "edge handle is unknown"))?
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "edge without curve"))?;
|
||||
let surf_h = brep
|
||||
.face_surface(f)
|
||||
.ok_or(dangling("face handle is unknown"))?
|
||||
.ok_or(dangling("face without surface"))?;
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "face handle is unknown"))?
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "face without surface"))?;
|
||||
let edge_dom = brep
|
||||
.edge_interval(e)
|
||||
.ok_or(dangling("edge handle is unknown"))?;
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "edge handle is unknown"))?;
|
||||
let mut face_dom = brep
|
||||
.face_uv_domain(f)
|
||||
.ok_or(dangling("face handle is unknown"))?;
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "face handle is unknown"))?;
|
||||
let edge_zone_tol = tol_of(brep, e)?;
|
||||
|
||||
// (status unchecked: the domain stays GetUVDomain's on failure)
|
||||
@@ -1625,9 +1672,10 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
}
|
||||
|
||||
let sol = {
|
||||
let surface = brep
|
||||
.surface(surf_h)
|
||||
.ok_or(dangling("surface handle cannot be resolved"))?;
|
||||
let surface = brep.surface(surf_h).ok_or(invalid(
|
||||
OP_EDGE_FACE_COIN,
|
||||
"surface handle cannot be resolved",
|
||||
))?;
|
||||
let curve = curve_of(brep, Some(curve_h))?;
|
||||
// (status unchecked: not coincident on failure)
|
||||
ignore_soft(surface.simple_coincidence_checker(
|
||||
@@ -1710,14 +1758,15 @@ impl<O: ClassObject + SolutionObject + Ord> TopologyIntersector<O> {
|
||||
};
|
||||
|
||||
let edge_tol = tol_of(brep, e)?;
|
||||
let face_b = face_brep(f)?.ok_or(dangling("face without B-rep"))?;
|
||||
let face_b =
|
||||
face_brep(f)?.ok_or(invalid(OP_EDGE_FACE_COIN, "face without B-rep"))?;
|
||||
|
||||
// We have to make a copy of the curve: what's passed in gets
|
||||
// installed in the new edge.
|
||||
let copy = curve_of(brep, Some(curve_h))?.clone();
|
||||
let curve_copy = brep
|
||||
.insert_curve(copy)
|
||||
.ok_or(dangling("curve store is full"))?;
|
||||
.ok_or(invalid(OP_EDGE_FACE_COIN, "curve store is full"))?;
|
||||
// (status unchecked: no new edge, loop or face on failure)
|
||||
let made = ignore_soft(brep_make_edge_in_face(
|
||||
brep,
|
||||
|
||||
@@ -1955,6 +1955,130 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::curve::hermite_curve::HermiteCurve;
|
||||
|
||||
/// A full circle of radius 2 in the XY plane (rational quadratic B-spline).
|
||||
fn circle_of_radius_two(start_deg: f64, end_deg: f64) -> Curve {
|
||||
use crate::geom::axis2_placement::Axis2Placement;
|
||||
use crate::nurbs::b_spline_curve::NurbCircleParam;
|
||||
Curve::from(
|
||||
BSplineCurve::create_circle_segment(
|
||||
3,
|
||||
&Axis2Placement::IDENTITY,
|
||||
2.0,
|
||||
start_deg,
|
||||
end_deg,
|
||||
NurbCircleParam::Quadratic,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
/// The reuse path itself (PR #224): an end point drop answered from a cache slot an
|
||||
/// earlier drop filled gives exactly the result of a fresh slot for that drop alone
|
||||
/// (no reuse at all), and lands where it should. Points on and just off the circle
|
||||
/// at 48 angles, so the global solve runs on the pre-filled slot.
|
||||
#[test]
|
||||
fn drop_with_prefilled_cache_slot_matches_fresh_slot_per_drop() {
|
||||
let k = Kernel::default();
|
||||
let full = circle_of_radius_two(0.0, 360.0);
|
||||
let ivl = full.natural_interval();
|
||||
let tol = 1e-6;
|
||||
let drop_at = |p: Point3, slot: &mut Option<CurveCache<CurveHandle>>| {
|
||||
full.drop_point_base_cached(
|
||||
&k,
|
||||
&ivl,
|
||||
p,
|
||||
None,
|
||||
tol,
|
||||
None,
|
||||
SolverOperation::Intersect,
|
||||
slot,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let mut shared = None;
|
||||
let _ = drop_at(Vec3::new(0.0, -2.0, 0.0), &mut shared);
|
||||
assert!(shared.is_some());
|
||||
for i in 0..48 {
|
||||
let a = (f64::from(i) + 0.25) * std::f64::consts::TAU / 48.0;
|
||||
let on = Vec3::new(2.0 * a.cos(), 2.0 * a.sin(), 0.0);
|
||||
for r in [2.0, 2.0 + 0.5 * tol] {
|
||||
let p = Vec3::new(r * a.cos(), r * a.sin(), 0.0);
|
||||
let fresh = drop_at(p, &mut None);
|
||||
let reused = drop_at(p, &mut shared);
|
||||
// `Debug` prints every float exactly: equal strings are equal bits
|
||||
assert_eq!(format!("{fresh:?}"), format!("{reused:?}"), "angle {a}");
|
||||
assert!(
|
||||
reused.success && reused.distance < tol,
|
||||
"angle {a}: {reused:?}"
|
||||
);
|
||||
let q = full.evaluate_point(reused.parameter).unwrap();
|
||||
assert!(q.distance(on) < tol, "angle {a}: {q:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A closed curve is split in three (recursively) and every end drop of the check
|
||||
/// reuses one cache slot per curve (PR #224): checking again with the slots the
|
||||
/// first check filled gives the same result, which covers exactly the upper half of
|
||||
/// the circle.
|
||||
#[test]
|
||||
fn coincidence_with_prefilled_cache_slots_finds_the_half_circle() {
|
||||
use crate::surface::surface::p4::NoObject;
|
||||
|
||||
let k = Kernel::default();
|
||||
let full = circle_of_radius_two(0.0, 360.0);
|
||||
let half = circle_of_radius_two(0.0, 180.0);
|
||||
let (ivl, other_ivl) = (full.natural_interval(), half.natural_interval());
|
||||
let tol = 1e-6;
|
||||
let objects = [None::<NoObject>, None];
|
||||
assert!(full.is_split_needed(&ivl, tol).unwrap());
|
||||
|
||||
let mut caches = [None, None];
|
||||
let mut check = || {
|
||||
full.global_coincidence_checker_at(
|
||||
&k,
|
||||
&ivl,
|
||||
&half,
|
||||
&other_ivl,
|
||||
tol,
|
||||
false,
|
||||
objects,
|
||||
0,
|
||||
&mut caches,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
let filling = check();
|
||||
let prefilled = check();
|
||||
assert!(caches.iter().all(Option::is_some));
|
||||
assert_eq!(format!("{filling:?}"), format!("{prefilled:?}"));
|
||||
|
||||
// every solution end is a point of the upper half on both curves, and the
|
||||
// solutions' angular spans cover [0, pi] without a gap
|
||||
assert!(!prefilled.solutions.is_empty());
|
||||
let mut spans = Vec::new();
|
||||
for s in &prefilled.solutions {
|
||||
let mut angles = [0.0; 2];
|
||||
for (angle, e) in angles.iter_mut().zip([&s.start, &s.end]) {
|
||||
let p = full.evaluate_point(e.param(0).unwrap()).unwrap();
|
||||
let q = half.evaluate_point(e.param(1).unwrap()).unwrap();
|
||||
assert!(p.distance(q) < tol, "{p:?} vs {q:?}");
|
||||
assert!(p.y > -tol && (p.length() - 2.0).abs() < tol, "{p:?}");
|
||||
*angle = p.y.max(0.0).atan2(p.x);
|
||||
}
|
||||
let [a, b] = angles;
|
||||
spans.push((a.min(b), a.max(b)));
|
||||
}
|
||||
spans.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
let mut covered = 0.0_f64;
|
||||
for &(lo, hi) in &spans {
|
||||
assert!(lo <= covered + tol, "gap before {lo} in {spans:?}");
|
||||
covered = covered.max(hi);
|
||||
}
|
||||
assert!(covered >= std::f64::consts::PI - tol, "{spans:?}");
|
||||
}
|
||||
|
||||
fn quarter_line() -> Curve {
|
||||
let c = BSplineCurve::create_line_segment(
|
||||
3,
|
||||
|
||||
@@ -1075,13 +1075,13 @@ fn curve_ref<O: Copy + PartialEq>(tree: &Tree<O>, id: NodeId) -> Result<CurveSpa
|
||||
/// without owner.
|
||||
fn curve_approx_tol_3d(k: &Kernel, curve: &Curve) -> Result<f64> {
|
||||
if curve.owner().is_some() {
|
||||
// UNPORTED(curve.curve_cache): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
return Err(SolidError::Unported {
|
||||
upstream: "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
unit: "curve.curve_cache",
|
||||
unit: "geom.tol",
|
||||
});
|
||||
}
|
||||
Ok(approx_tol_3d(k, SmallTopoType::NormalSize))
|
||||
|
||||
@@ -1389,13 +1389,13 @@ impl Ellipse {
|
||||
|| o.type_code == EDGEUSE_TYPE
|
||||
|| crate::curve::curve::p2::is_kind_of(o.type_code)
|
||||
}) {
|
||||
// UNPORTED(curve.ellipse_p1): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
return Err(SolidError::Unported {
|
||||
upstream: "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
unit: "curve.ellipse_p1",
|
||||
unit: "geom.tol",
|
||||
});
|
||||
}
|
||||
let angle_tol = 0.01; // Preserves behavior
|
||||
|
||||
@@ -702,7 +702,10 @@ impl PseudoBox {
|
||||
points.iter().zip(vectors).any(|(pnt, vec)| {
|
||||
// Calculate D of plane equation, A, B, C are in aVectors
|
||||
let d = -pnt.dot(*vec);
|
||||
corners.iter().all(|c| vec.dot(*c) + d >= EFF_ZERO)
|
||||
// `!any(< EFF_ZERO)`, as upstream's loop: a NaN corner (a perspective eye on the
|
||||
// view plane projects the boxes to NaN) is not below the limit, so the plane
|
||||
// separates. `all(>= EFF_ZERO)` says the opposite for NaN (#59).
|
||||
!corners.iter().any(|c| vec.dot(*c) + d < EFF_ZERO)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -944,13 +944,13 @@ impl<O: SolutionObject> Solution<O> {
|
||||
// pass the call along
|
||||
match self.object(index, OP)? {
|
||||
Some(_) => {
|
||||
// UNPORTED(geom.solution_array): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
Err(SolidError::Unported {
|
||||
upstream: "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
unit: "geom.solution_array",
|
||||
unit: "geom.tol",
|
||||
})
|
||||
}
|
||||
None => Ok(0.0),
|
||||
|
||||
@@ -116,8 +116,8 @@ use crate::topology::{Brep, EdgeId, FaceId, VertexId};
|
||||
// `Brep::this_model_size_estimate`, `Brep::set_this_model_size_estimate`, unit
|
||||
// topology.brep_p1); SmTol::GetScaledZero(const SmBrep&) needs SmBrep::CalculateBoundingBox
|
||||
// (query.brep).
|
||||
// UNPORTED(topology.vertex), UNPORTED(topology.edge), UNPORTED(topology.face_p2),
|
||||
// UNPORTED(topology.edgeuse_p1): SmTol::GetZoneTol3d(const
|
||||
// UNPORTED(geom.tol) (the owner in harness/callgraph/units.json; every call site of
|
||||
// these overloads carries this tag): SmTol::GetZoneTol3d(const
|
||||
// SmObject*), SmTol::GetZoneTol3d(const SmBrepData*), SmTol::GetApproxTol3d(const
|
||||
// SmObject*), SmTol::GetXSectTol3d(const SmObject*, const SmObject*, ..),
|
||||
// SmTol::GetZoneTol3d_ForXSectResult(const SmObject*, const SmObject*),
|
||||
|
||||
@@ -383,11 +383,13 @@ pub fn select_topology_to_keep<C: StitchCallback + ?Sized>(
|
||||
|
||||
// Find the distance from pEdge1->Curve to each face in sEFaces2.
|
||||
for &face2 in &faces2 {
|
||||
let surface2 =
|
||||
fp2::surface(b, face2)?.ok_or_else(|| deref("face without surface"))?;
|
||||
// (upstream reads the surface pointer first but dereferences it only in the
|
||||
// distance call, after breaking on a null curve)
|
||||
let Some(curve1) = edge::curve(b, edge1)? else {
|
||||
break;
|
||||
};
|
||||
let surface2 =
|
||||
fp2::surface(b, face2)?.ok_or_else(|| deref("face without surface"))?;
|
||||
// 0 samples: do a precise measurement; no max distance (status ignored)
|
||||
if let Some(g) = ignored(curve1.surface_max_distance_between(
|
||||
k,
|
||||
@@ -409,11 +411,13 @@ pub fn select_topology_to_keep<C: StitchCallback + ?Sized>(
|
||||
|
||||
// Find the distance from pEdge2->Curve to each face in sEFaces1.
|
||||
for &face1 in &faces1 {
|
||||
let surface1 =
|
||||
fp2::surface(b, face1)?.ok_or_else(|| deref("face without surface"))?;
|
||||
// (upstream reads the surface pointer first but dereferences it only in the
|
||||
// distance call, after breaking on a null curve)
|
||||
let Some(curve2) = edge::curve(b, edge2)? else {
|
||||
break;
|
||||
};
|
||||
let surface1 =
|
||||
fp2::surface(b, face1)?.ok_or_else(|| deref("face without surface"))?;
|
||||
if let Some(g) = ignored(curve2.surface_max_distance_between(
|
||||
k,
|
||||
&edge::interval(b, edge2)?,
|
||||
|
||||
@@ -1864,13 +1864,13 @@ fn curve_global_curve_solve<O: SolutionObject>(
|
||||
|
||||
/// `SmTol::GetZoneTol3d(m_pPointVertex)`.
|
||||
pub(super) fn object_zone_tol_3d<O>(_vertex: Option<O>) -> Result<f64> {
|
||||
// UNPORTED(intersect.topology_solver_p1): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
Err(SolidError::unported(
|
||||
"SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"intersect.topology_solver_p1",
|
||||
"geom.tol",
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
//! `RemoveExcessFaces` borrows the original B-rep immutably (its arenas have no editing flag)
|
||||
//! and uses the existing canonical arena-identity cache adapter; custom geometry owner keys
|
||||
//! or indirect owner chains are explicitly unsupported rather than silently skipped.
|
||||
//! Result-edge enumeration uses arena order, not `SmBrep::GetEdges` linked-list order
|
||||
//! (owned by `topology.brep_p1`); nonempty queries still defer at `NormalizedEvaluate`.
|
||||
//! Result-edge enumeration uses `SmBrep::GetEdges` list order (`topology::brep::p1::edges`);
|
||||
//! nonempty queries still defer at `NormalizedEvaluate`. `BuildSideWallOfEdgeuse` takes
|
||||
//! the original B-rep as an argument (upstream reaches it through the edge use pointer).
|
||||
//! No new input-driven recursion; existing topology walks are cycle-bounded.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
@@ -475,26 +476,34 @@ impl OffsetExecutive {
|
||||
/// Builds a closing ruled side wall, or succeeds without work for null/ambiguous mappings.
|
||||
pub fn build_side_wall_of_edgeuse(
|
||||
&mut self,
|
||||
_kernel: &Kernel,
|
||||
kernel: &Kernel,
|
||||
original_brep: &mut Brep,
|
||||
original: Option<EdgeuseId>,
|
||||
) -> Result<()> {
|
||||
let Some(original) = original else {
|
||||
return Ok(());
|
||||
};
|
||||
let Some(_offset) = self.offset_edgeuse(original) else {
|
||||
let Some(offset) = self.offset_edgeuse(original) else {
|
||||
return Ok(());
|
||||
};
|
||||
// Continuation cpp:2819–2823: CreateFaceFromSurface, then append closing face.
|
||||
// Actual call arguments: ruled blend (0), same direction (1), no options.
|
||||
// The static upstream call pairs an edge use of the original B-rep with one of
|
||||
// the offset B-rep; topology.brep_p1's port (topology::brep::p1::
|
||||
// create_edge_edge_blend) takes both edge uses in one B-rep, and this method has
|
||||
// no original B-rep: the cross-B-rep form is topology.brep_p1's own unported part.
|
||||
// UNPORTED(topology.brep_p1): SmBrep::CreateEdgeEdgeBlend
|
||||
Err(SolidError::unported(
|
||||
"SmBrep::CreateEdgeEdgeBlend",
|
||||
"topology.brep_p1",
|
||||
))
|
||||
let offset_brep = required(self.offset_brep.as_mut())?;
|
||||
// cpp:2812: ruled blend (0) between the original edge use and its offset edge use
|
||||
// (in the offset B-rep), curves in the same direction (1), no blend options
|
||||
let new_surface = crate::topology::brep::p1::create_edge_edge_blend(
|
||||
kernel,
|
||||
0,
|
||||
original_brep,
|
||||
Some(original),
|
||||
Some(offset_brep),
|
||||
Some(offset),
|
||||
1,
|
||||
None,
|
||||
)?;
|
||||
// cpp:2819: m_pOffsetBrep->CreateFaceFromSurface(pNewSurface, natural domain)
|
||||
let domain = new_surface.natural_uv_domain();
|
||||
let new_face = create_face_from_surface(offset_brep, &new_surface, &domain)?;
|
||||
self.closing_faces.push(new_face); // [B549]
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Builds edge cap offsets. Notifications use distinct original/result object keys;
|
||||
@@ -1017,6 +1026,17 @@ fn uv_curve_bounding_box(kernel: &Kernel, curve: &mut Curve) -> Result<Extent3d>
|
||||
.unwrap_or_else(Extent3d::new))
|
||||
}
|
||||
|
||||
/// `SmBrep::CreateFaceFromSurface(pSurface, sDomain, rpNewFace)` (unit
|
||||
/// `topology.brep_p8`): the new face.
|
||||
fn create_face_from_surface(b: &mut Brep, surface: &Surface, domain: &Extent2d) -> Result<FaceId> {
|
||||
let _ = (b, surface, domain);
|
||||
// UNPORTED(topology.brep_p8): SmBrep::CreateFaceFromSurface
|
||||
Err(SolidError::unported(
|
||||
"SmBrep::CreateFaceFromSurface",
|
||||
"topology.brep_p8",
|
||||
))
|
||||
}
|
||||
|
||||
fn required<T>(value: Option<T>) -> Result<T> {
|
||||
value.ok_or_else(|| SolidError::null_pointer(OP))
|
||||
}
|
||||
@@ -1348,6 +1368,29 @@ mod tests {
|
||||
edgeuse
|
||||
}
|
||||
|
||||
/// An edge use on a unit-length B-spline line at height `y`.
|
||||
fn add_bspline_use(brep: &mut Brep, y: f64) -> EdgeuseId {
|
||||
let line = Line::from_points(Vec3::new(0.0, y, 0.0), Vec3::new(1.0, y, 0.0), 3);
|
||||
let curve = Curve::from(line.base_with_nurb().unwrap().into_owned());
|
||||
let edge = brep
|
||||
.add_edge_record(Edge {
|
||||
vertices: [VertexId::from_index(0); 2],
|
||||
edgeuses: Vec::new(),
|
||||
interval: Extent1d::from_raw(0.0, 1.0),
|
||||
tolerance: 0.0,
|
||||
curve: Some(curve),
|
||||
})
|
||||
.unwrap();
|
||||
let edgeuse = brep
|
||||
.add_edgeuse_record(Edgeuse {
|
||||
edge: Some(edge),
|
||||
..Edgeuse::default()
|
||||
})
|
||||
.unwrap();
|
||||
brep.edge_mut(edge).unwrap().edgeuses.push(edgeuse);
|
||||
edgeuse
|
||||
}
|
||||
|
||||
fn plane(z: f64) -> Surface {
|
||||
Surface::from(Plane::new(
|
||||
Vec3::new(0.0, 0.0, z),
|
||||
@@ -1865,20 +1908,28 @@ mod tests {
|
||||
fn sidewalls_handle_null_missing_ambiguous_and_single_mappings() {
|
||||
let kernel = Kernel::default();
|
||||
let mut executive = executive();
|
||||
let original = EdgeuseId::from_index(0);
|
||||
executive.build_side_wall_of_edgeuse(&kernel, None).unwrap();
|
||||
// B-spline edge curves (a Line whose parameterisation was edited carries no NURB)
|
||||
let mut original_brep = Brep::new();
|
||||
let original = add_bspline_use(&mut original_brep, 0.0);
|
||||
let mut offset_brep = Brep::new();
|
||||
let offset = add_bspline_use(&mut offset_brep, 1.0);
|
||||
executive.set_offset_brep(offset_brep);
|
||||
executive
|
||||
.build_side_wall_of_edgeuse(&kernel, Some(original))
|
||||
.build_side_wall_of_edgeuse(&kernel, &mut original_brep, None)
|
||||
.unwrap();
|
||||
executive.relate_edgeuses(original, EdgeuseId::from_index(1));
|
||||
executive
|
||||
.build_side_wall_of_edgeuse(&kernel, &mut original_brep, Some(original))
|
||||
.unwrap();
|
||||
// the ruled blend across the two B-reps runs; the closing face is next
|
||||
executive.relate_edgeuses(original, offset);
|
||||
assert_dependency(
|
||||
executive.build_side_wall_of_edgeuse(&kernel, Some(original)),
|
||||
"SmBrep::CreateEdgeEdgeBlend",
|
||||
"topology.brep_p1",
|
||||
executive.build_side_wall_of_edgeuse(&kernel, &mut original_brep, Some(original)),
|
||||
"SmBrep::CreateFaceFromSurface",
|
||||
"topology.brep_p8",
|
||||
);
|
||||
executive.relate_edgeuses(original, EdgeuseId::from_index(2));
|
||||
executive
|
||||
.build_side_wall_of_edgeuse(&kernel, Some(original))
|
||||
.build_side_wall_of_edgeuse(&kernel, &mut original_brep, Some(original))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
||||
@@ -879,9 +879,9 @@ enum Inside {
|
||||
/// # Errors
|
||||
///
|
||||
/// Those of [`Ellipse::new`] and [`Cone::height`]; a seam line parallel to the
|
||||
/// ellipse plane or of zero length, and a failed NURB to STEP conversion of the domain
|
||||
/// corners (upstream then reads uninitialised values); a STEP inversion failing in the
|
||||
/// generator solve.
|
||||
/// ellipse plane or of zero length (upstream then reads uninitialised values); a STEP
|
||||
/// inversion failing in the generator solve. A failed NURB to STEP conversion of the
|
||||
/// domain corners is ignored as upstream does: the default-constructed domain is used.
|
||||
pub fn ellipse_trim_intervals(
|
||||
k: &Kernel,
|
||||
ellipse_origin: Point3,
|
||||
@@ -924,21 +924,25 @@ pub fn ellipse_trim_intervals(
|
||||
let center_bot = cone.rev.position.origin() + cone.rev.anal_uv_domain.min().y * cone_axis;
|
||||
let center_top = center_bot + height * cone_axis;
|
||||
|
||||
// map given NurbDomain into StepDomain (SmSurface::ConvertDomainFromNURBSToSTEP:
|
||||
// a reversed result is replaced by the NURB domain)
|
||||
let min_step_uv = cone.convert_uv_from_nurbs_to_step(k, uv_domain.min())?;
|
||||
let max_step_uv = cone.convert_uv_from_nurbs_to_step(k, uv_domain.max())?;
|
||||
// map given NurbDomain into StepDomain (SmSurface::ConvertDomainFromNURBSToSTEP,
|
||||
// status ignored: a failed corner conversion leaves the default-constructed
|
||||
// domain, a reversed result is replaced by the NURB domain)
|
||||
let mut anal_uv_domain = Extent2d::new();
|
||||
if anal_uv_domain
|
||||
.set_min_max_coords(
|
||||
min_step_uv.x,
|
||||
min2(min_step_uv.y, max_step_uv.y),
|
||||
max_step_uv.x,
|
||||
max2(min_step_uv.y, max_step_uv.y),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
anal_uv_domain = *uv_domain;
|
||||
if let Some(min_step_uv) = ignored(cone.convert_uv_from_nurbs_to_step(k, uv_domain.min()))? {
|
||||
if let Some(max_step_uv) = ignored(cone.convert_uv_from_nurbs_to_step(k, uv_domain.max()))?
|
||||
{
|
||||
if anal_uv_domain
|
||||
.set_min_max_coords(
|
||||
min_step_uv.x,
|
||||
min2(min_step_uv.y, max_step_uv.y),
|
||||
max_step_uv.x,
|
||||
max2(min_step_uv.y, max_step_uv.y),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
anal_uv_domain = *uv_domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get cone corners [StartLine start, StartLine end, EndLine start EndLine end]
|
||||
|
||||
@@ -2419,13 +2419,13 @@ impl<O: Copy + PartialEq> SurfaceCache<O> {
|
||||
// when no classified neighbor was found - cast a ray
|
||||
if found_class == NodeClass::Unknown {
|
||||
let src_zone_tol_3d = if curr_fields.face.is_some() {
|
||||
// UNPORTED(surface.surface_cache_p1): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
return Err(SolidError::unported(
|
||||
"SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"surface.surface_cache_p1",
|
||||
"geom.tol",
|
||||
));
|
||||
} else {
|
||||
zone_tol_3d(k, SmallTopoType::NormalSize)
|
||||
|
||||
@@ -468,13 +468,13 @@ impl<O: Copy + PartialEq> SurfaceCache<O> {
|
||||
let ang_tol_deg = opts.ang_tol_rad * 180.0 / PI;
|
||||
// SmTol::GetZoneTol3d(m_cpSurface): GetFace() ? its tolerance : the system's
|
||||
let zone_tol = if self.surface().face()?.is_some() {
|
||||
// UNPORTED(surface.surface_cache_p2): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
return Err(SolidError::unported(
|
||||
"SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"surface.surface_cache_p2",
|
||||
"geom.tol",
|
||||
));
|
||||
} else {
|
||||
zone_tol_3d(k, SmallTopoType::NormalSize)
|
||||
|
||||
@@ -1085,13 +1085,13 @@ fn map_to_2d(tol_3d: f64, uv: Point2, dir: Vec2, surface: &Surface) -> Result<f6
|
||||
|
||||
/// `SmTol::GetZoneTol3d(pFace)`.
|
||||
fn face_zone_tol_3d<O>(_face: O) -> Result<f64> {
|
||||
// UNPORTED(surface.trim_srf_cache): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// UNPORTED(geom.tol): SmTol::GetZoneTol3d(const SmObject*) on an opaque handle. Every
|
||||
// arm it dispatches to is ported (topology::{vertex, edge, face::p2, edgeuse::p1}::tolerance,
|
||||
// Brep::tolerance) but each takes `&Brep` and none is in scope here; wire once this code
|
||||
// receives the owning B-rep
|
||||
Err(SolidError::unported(
|
||||
"SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"surface.trim_srf_cache",
|
||||
"geom.tol",
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -96,10 +96,10 @@
|
||||
//! `UnLockBoundingBox` (`query.brep`), `SmBSplineSurface::CreateCornerBlend` with a
|
||||
//! non-B-spline neighbour surface (`nurbs.b_spline_surface_n_lib_p2`, whose port takes
|
||||
//! B-spline neighbours only).
|
||||
//! - `CreateEdgeEdgeBlend` takes the B-rep mutably (the edge use evaluations of
|
||||
//! `topology.edgeuse_p3` take it so); it ignores both `EvaluateBinormal` statuses as
|
||||
//! upstream and goes on with the outputs upstream sees after a failure (undefined, or
|
||||
//! zeroed point, tangent and normal).
|
||||
//! - `CreateEdgeEdgeBlend` takes each edge use's B-rep (the second `None` when both are
|
||||
//! in one B-rep), mutably: the edge use evaluations of `topology.edgeuse_p3` take it so.
|
||||
//! It ignores both `EvaluateBinormal` statuses as upstream and goes on with the outputs
|
||||
//! upstream sees after a failure (undefined, or zeroed point, tangent and normal).
|
||||
//! - `GetShells` dedups with a shell mark record local to the call (upstream marks the
|
||||
//! `SmShell` objects); `SetRegionIsVoidFlagsForNestedSolids` bounds its shell queue at
|
||||
//! `4 * shells + 16` passes.
|
||||
@@ -2431,7 +2431,7 @@ pub fn create_corner_blend(
|
||||
|
||||
// SmSurface::CreateCornerBlend locals
|
||||
let mut ordered_uv: Vec<Option<BSplineCurve>> = Vec::new();
|
||||
let mut ordered_3d: Vec<BSplineCurve> = Vec::new();
|
||||
let mut ordered_3d: Vec<Curve> = Vec::new();
|
||||
let mut ordered_surfs: Vec<Option<BSplineSurface>> = Vec::new();
|
||||
|
||||
// for every ordered Edgeuse - load a trimmed copy of Edgeuse->Edge->Curve to sOrdered3D
|
||||
@@ -2450,11 +2450,8 @@ pub fn create_corner_blend(
|
||||
let mut e_ivl = edge::interval(b, e)?;
|
||||
copy.trim(k, &mut e_ivl, TrimMode::Notify)?;
|
||||
|
||||
// build the sOrdered3D array
|
||||
ordered_3d.push(
|
||||
bspline_part(©)
|
||||
.ok_or_else(|| null("CreateCornerBlend: curve without NURBS data"))?,
|
||||
);
|
||||
// build the sOrdered3D array (any SmCurve, as upstream)
|
||||
ordered_3d.push(copy);
|
||||
|
||||
// When Needed, put in UVTrimCurve and Surface in sOrderedUV and sOrderedSurfs arrays
|
||||
let tangent = tangencies.get(i).copied().unwrap_or(true);
|
||||
@@ -2511,7 +2508,7 @@ pub fn create_corner_blend(
|
||||
let top_curve = BSplineCurve::create_point_curve(pnt)?;
|
||||
|
||||
// add it to the input arrays at the proper location
|
||||
ordered_3d.insert(2 - ii, top_curve);
|
||||
ordered_3d.insert(2 - ii, Curve::from(top_curve));
|
||||
eu_orients.insert(2 - ii, OrientType::Same);
|
||||
ordered_uv.insert(2 - ii, None);
|
||||
ordered_surfs.insert(2 - ii, None);
|
||||
@@ -2525,6 +2522,7 @@ pub fn create_corner_blend(
|
||||
|
||||
// pass the call along (FALSE = bicubic patch through curves and crossTangents)
|
||||
let surfs: Vec<Option<&BSplineSurface>> = ordered_surfs.iter().map(Option::as_ref).collect();
|
||||
let ordered_3d = corner_blend_bspline_curves(&ordered_3d, &ordered_uv, &surfs)?;
|
||||
BSplineSurface::create_corner_blend(
|
||||
&ordered_3d,
|
||||
&eu_orients,
|
||||
@@ -2536,10 +2534,63 @@ pub fn create_corner_blend(
|
||||
)
|
||||
}
|
||||
|
||||
/// The 3D curves `SmBSplineSurface::CreateCornerBlend` gets as `SmBSplineCurve`s (unit
|
||||
/// `nurbs.b_spline_surface_n_lib_p2`, whose port takes B-spline curves). Upstream passes
|
||||
/// any `SmCurve` and converts each, in order, with `sm_CreateNonRationalCurve`
|
||||
/// (SmBSplineSurfaceNLib.cpp:3100-3110), whose `SM_CAST_PTR(SmBSplineCurve, ..)` / `NER`
|
||||
/// returns `SM_ERR_NULL_POINTER` for the first curve of another kind. Its curve count
|
||||
/// check cannot fail here (the padding leaves at least 4 curves) and its earlier NULL UV
|
||||
/// curve / surface check (`:3078-3092`, bicubic patch) returns the same status. Before
|
||||
/// that curve only a rational curve's conversion can fail, so with one there (and the
|
||||
/// NULL check passing) the case is unported.
|
||||
fn corner_blend_bspline_curves(
|
||||
curves: &[Curve],
|
||||
uv_curves: &[Option<BSplineCurve>],
|
||||
surfaces: &[Option<&BSplineSurface>],
|
||||
) -> Result<Vec<BSplineCurve>> {
|
||||
let parts: Vec<Option<BSplineCurve>> = curves.iter().map(bspline_part).collect();
|
||||
if parts.iter().all(Option::is_some) {
|
||||
return Ok(parts.into_iter().flatten().collect());
|
||||
}
|
||||
// the NULL UV curve / surface check (bCreateBilinearPatch == FALSE)
|
||||
let curve_cnt = curves.len();
|
||||
let mut null_count = 0usize;
|
||||
for (uv, srf) in uv_curves.iter().zip(surfaces).take(curve_cnt) {
|
||||
if uv.is_none() || srf.is_none() {
|
||||
null_count += 1;
|
||||
}
|
||||
if ((curve_cnt == 4 && null_count > 1) || (curve_cnt > 4 && null_count > 0))
|
||||
&& (uv.is_none() || srf.is_none())
|
||||
{
|
||||
return Err(SolidError::null_pointer(OP)); // NER(crUVCurves[ii]) / NER(crSurfaces[ii])
|
||||
}
|
||||
}
|
||||
let mut converted = Vec::new();
|
||||
for part in parts {
|
||||
let Some(part) = part else {
|
||||
if converted
|
||||
.iter()
|
||||
.any(|p: &BSplineCurve| p.is_rational().unwrap_or(true))
|
||||
{
|
||||
// UNPORTED(nurbs.b_spline_surface_n_lib_p2): SmBSplineSurface::CreateCornerBlend with a rational curve before a non-B-spline one
|
||||
return Err(SolidError::unported(
|
||||
"SmBSplineSurface::CreateCornerBlend",
|
||||
"nurbs.b_spline_surface_n_lib_p2",
|
||||
));
|
||||
}
|
||||
return Err(SolidError::null_pointer(OP)); // NER(pNurb)
|
||||
};
|
||||
converted.push(part);
|
||||
}
|
||||
Ok(converted)
|
||||
}
|
||||
|
||||
// ---- edge-to-edge blends (SmBrep::CreateEdgeEdgeBlend) ----------------------------------
|
||||
|
||||
/// `CreateEdgeEdgeBlend`: a ruled (`blend_flag` 0) or G1/G2/G3 blend (`1`/`2`/`3`)
|
||||
/// surface between the trimmed NURBS curves of two edges. `curves_dir_flag`: `0`
|
||||
/// surface between the trimmed NURBS curves of two edges: `eu_1` in `b_1`, `eu_2` in
|
||||
/// `b_2` (`None`: also in `b_1`; upstream's edge uses may belong to two B-reps).
|
||||
/// `curves_dir_flag`: `0`
|
||||
/// guesses the pairing from the rail distances, `1` starts both at their curve starts,
|
||||
/// `2` pairs start with end. `opt_ds_def` (its curvature type is overwritten from
|
||||
/// `blend_flag`) tunes a blend.
|
||||
@@ -2554,9 +2605,10 @@ pub fn create_corner_blend(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn create_edge_edge_blend(
|
||||
k: &Kernel,
|
||||
b: &mut Brep,
|
||||
blend_flag: u64,
|
||||
b_1: &mut Brep,
|
||||
eu_1: Option<EdgeuseId>,
|
||||
b_2: Option<&mut Brep>,
|
||||
eu_2: Option<EdgeuseId>,
|
||||
curves_dir_flag: u64,
|
||||
opt_ds_def: Option<&mut DerivSurfDefinition<'_>>,
|
||||
@@ -2564,17 +2616,37 @@ pub fn create_edge_edge_blend(
|
||||
let eu_1 = eu_1.ok_or_else(|| SolidError::null_pointer(OP))?; // NER
|
||||
let eu_2 = eu_2.ok_or_else(|| SolidError::null_pointer(OP))?; // NER
|
||||
|
||||
// eu_2's B-rep: `b_2`, or `b_1` when both edge uses are in one B-rep (each edge use's
|
||||
// reads touch only its own B-rep, as upstream's)
|
||||
let mut b_2 = b_2;
|
||||
macro_rules! b2_mut {
|
||||
() => {
|
||||
match b_2.as_deref_mut() {
|
||||
Some(other) => other,
|
||||
None => &mut *b_1,
|
||||
}
|
||||
};
|
||||
}
|
||||
macro_rules! b2 {
|
||||
() => {
|
||||
match b_2.as_deref() {
|
||||
Some(other) => other,
|
||||
None => &*b_1,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// locals
|
||||
let (Some(edge1), Some(edge2)) = (eu1::edge(b, eu_1)?, eu1::edge(b, eu_2)?) else {
|
||||
let (Some(edge1), Some(edge2)) = (eu1::edge(b_1, eu_1)?, eu1::edge(b2!(), eu_2)?) else {
|
||||
return Err(status(SM_ERR_INVALID_INPUT)); // Could not fetch Edge from Edgeuse
|
||||
};
|
||||
|
||||
// edge locals
|
||||
let ivl1 = edge::interval(b, edge1)?;
|
||||
let mut ivl2 = edge::interval(b, edge2)?;
|
||||
let rail1 = edge::create_trimmed_nurbs_curve(k, b, edge1)?;
|
||||
let rail2 = edge::create_trimmed_nurbs_curve(k, b, edge2)?;
|
||||
let tolerance = max2(edge::tolerance(b, edge1)?, edge::tolerance(b, edge2)?);
|
||||
let ivl1 = edge::interval(b_1, edge1)?;
|
||||
let mut ivl2 = edge::interval(b2!(), edge2)?;
|
||||
let rail1 = edge::create_trimmed_nurbs_curve(k, b_1, edge1)?;
|
||||
let rail2 = edge::create_trimmed_nurbs_curve(k, b2!(), edge2)?;
|
||||
let tolerance = max2(edge::tolerance(b_1, edge1)?, edge::tolerance(b2!(), edge2)?);
|
||||
let (Some(rail1), Some(rail2)) = (rail1, rail2) else {
|
||||
return Err(status(SM_ERR_INVALID_INPUT)); // Could not build BSplineCurves from Edges
|
||||
};
|
||||
@@ -2644,12 +2716,12 @@ pub fn create_edge_edge_blend(
|
||||
|
||||
// face locals
|
||||
let face1 =
|
||||
eu1::face(b, eu_1)?.ok_or_else(|| null("CreateEdgeEdgeBlend: edge use without face"))?;
|
||||
let face2_ =
|
||||
eu1::face(b, eu_2)?.ok_or_else(|| null("CreateEdgeEdgeBlend: edge use without face"))?;
|
||||
eu1::face(b_1, eu_1)?.ok_or_else(|| null("CreateEdgeEdgeBlend: edge use without face"))?;
|
||||
let face2_ = eu1::face(b2!(), eu_2)?
|
||||
.ok_or_else(|| null("CreateEdgeEdgeBlend: edge use without face"))?;
|
||||
let surfaces_present = (
|
||||
face2::surface(b, face1)?.is_some(),
|
||||
face2::surface(b, face2_)?.is_some(),
|
||||
face2::surface(b_1, face1)?.is_some(),
|
||||
face2::surface(b2!(), face2_)?.is_some(),
|
||||
);
|
||||
if !(surfaces_present.0 && surfaces_present.1) {
|
||||
return Err(status(SM_ERR_INVALID_INPUT)); // Could not fetch Surface from Edgeuse
|
||||
@@ -2662,28 +2734,28 @@ pub fn create_edge_edge_blend(
|
||||
tangent: mut edge1_tangent,
|
||||
face_normal: mut face1_normal,
|
||||
..
|
||||
} = evaluate_binormal_status_ignored(k, b, eu_1, ivl1.evaluate(0.5))?;
|
||||
} = evaluate_binormal_status_ignored(k, b_1, eu_1, ivl1.evaluate(0.5))?;
|
||||
let BinormalEval {
|
||||
binormal: edge2_binormal,
|
||||
tangent: mut edge2_tangent,
|
||||
face_normal: mut face2_normal,
|
||||
..
|
||||
} = evaluate_binormal_status_ignored(k, b, eu_2, ivl2.evaluate(0.5))?;
|
||||
if eu1::orientation(b, eu_1)? == OrientType::Opposite {
|
||||
} = evaluate_binormal_status_ignored(k, b2_mut!(), eu_2, ivl2.evaluate(0.5))?;
|
||||
if eu1::orientation(b_1, eu_1)? == OrientType::Opposite {
|
||||
edge1_tangent = -edge1_tangent;
|
||||
}
|
||||
if eu1::orientation(b, eu_2)? == OrientType::Opposite {
|
||||
if eu1::orientation(b2!(), eu_2)? == OrientType::Opposite {
|
||||
edge2_tangent = -edge2_tangent;
|
||||
}
|
||||
let fu_orient = |eu: EdgeuseId| -> Result<OrientType> {
|
||||
let fu_orient = |b: &Brep, eu: EdgeuseId| -> Result<OrientType> {
|
||||
let fu = eu1::faceuse(b, eu)?
|
||||
.ok_or_else(|| null("CreateEdgeEdgeBlend: edge use without face use"))?;
|
||||
eu1::faceuse_orientation(b, fu)
|
||||
};
|
||||
if fu_orient(eu_1)? == OrientType::Opposite {
|
||||
if fu_orient(b_1, eu_1)? == OrientType::Opposite {
|
||||
face1_normal = -face1_normal;
|
||||
}
|
||||
if fu_orient(eu_2)? == OrientType::Opposite {
|
||||
if fu_orient(b2!(), eu_2)? == OrientType::Opposite {
|
||||
face2_normal = -face2_normal;
|
||||
}
|
||||
|
||||
@@ -2742,8 +2814,8 @@ pub fn create_edge_edge_blend(
|
||||
let curve1 = Curve::from(rail1);
|
||||
let curve2 = Curve::from(rail2);
|
||||
// (the face surfaces fetched above; re-borrowed past the edge use evaluations)
|
||||
let surface1 = face2::surface(b, face1)?.ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
let surface2 = face2::surface(b, face2_)?.ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
let surface1 = face2::surface(b_1, face1)?.ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
let surface2 = face2::surface(b2!(), face2_)?.ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
surface1.create_blend_surface(
|
||||
k,
|
||||
&curve1,
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"cases": [
|
||||
{
|
||||
"name": "fuzz_neg_zone_tol_network",
|
||||
"upstream_ref": "SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01490, gave 103 vs C++ 104)",
|
||||
"inputs": {
|
||||
"ang": 0.1,
|
||||
"approx": 0.001,
|
||||
"brep_a": {
|
||||
"kind": "network"
|
||||
},
|
||||
"brep_b": null,
|
||||
"ctor": 0,
|
||||
"ops": [
|
||||
{
|
||||
"a": [
|
||||
0,
|
||||
1,
|
||||
59253
|
||||
],
|
||||
"b": [
|
||||
0,
|
||||
0,
|
||||
20448
|
||||
],
|
||||
"op": "relate"
|
||||
},
|
||||
{
|
||||
"e": [
|
||||
0,
|
||||
1,
|
||||
8864
|
||||
],
|
||||
"op": "set_edge_class",
|
||||
"relative": true,
|
||||
"t0": 0.25588128598617577,
|
||||
"t1": 0.8302201720948407,
|
||||
"tol": -1e+300
|
||||
},
|
||||
{
|
||||
"op": "clear_ssi"
|
||||
},
|
||||
{
|
||||
"a": [
|
||||
0,
|
||||
0,
|
||||
59454
|
||||
],
|
||||
"b": [
|
||||
0,
|
||||
1,
|
||||
54000
|
||||
],
|
||||
"op": "relate"
|
||||
},
|
||||
{
|
||||
"a": [
|
||||
0,
|
||||
1,
|
||||
40680
|
||||
],
|
||||
"b": [
|
||||
0,
|
||||
0,
|
||||
60995
|
||||
],
|
||||
"op": "relate"
|
||||
},
|
||||
{
|
||||
"h": [
|
||||
0,
|
||||
0,
|
||||
28993
|
||||
],
|
||||
"op": "brep_mate"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fuzz_neg_zone_tol_plane_square_torus",
|
||||
"upstream_ref": "SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01531, gave 103 vs C++ 104)",
|
||||
"inputs": {
|
||||
"ang": 0.001,
|
||||
"approx": 1e-05,
|
||||
"brep_a": {
|
||||
"file": "plane_square.smb",
|
||||
"kind": "file",
|
||||
"rebuild": false
|
||||
},
|
||||
"brep_b": {
|
||||
"file": "torus.smb",
|
||||
"kind": "file",
|
||||
"rebuild": true
|
||||
},
|
||||
"ctor": 0,
|
||||
"ops": [
|
||||
{
|
||||
"e": [
|
||||
0,
|
||||
1,
|
||||
59767
|
||||
],
|
||||
"op": "set_edge_class",
|
||||
"relative": true,
|
||||
"t0": -0.09567098569341087,
|
||||
"t1": 0.9880380629003984,
|
||||
"tol": -1e+300
|
||||
},
|
||||
{
|
||||
"capture": 1.0,
|
||||
"op": "mgr_new",
|
||||
"override_tol": 0.0
|
||||
},
|
||||
{
|
||||
"op": "resolve"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fuzz_neg_zone_tol_box_with_large_fillet",
|
||||
"upstream_ref": "SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01875, gave 103 vs C++ 104)",
|
||||
"inputs": {
|
||||
"ang": 0.3490658503988659,
|
||||
"approx": 1e-05,
|
||||
"brep_a": {
|
||||
"file": "box_with_large_fillet.smb",
|
||||
"kind": "file",
|
||||
"rebuild": false
|
||||
},
|
||||
"brep_b": null,
|
||||
"ctor": 0,
|
||||
"ops": [
|
||||
{
|
||||
"e": [
|
||||
0,
|
||||
1,
|
||||
6654
|
||||
],
|
||||
"op": "set_edge_class",
|
||||
"relative": true,
|
||||
"t0": 0.4237108457337439,
|
||||
"t1": 1.1715237836841945,
|
||||
"tol": -1e+300
|
||||
},
|
||||
{
|
||||
"op": "getters"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"cases": [
|
||||
{
|
||||
"fuzz": {
|
||||
"base": "global_same_swap1_inside1",
|
||||
"mutations": [
|
||||
"/same = false",
|
||||
"/cone/7 = 0"
|
||||
],
|
||||
"seed": 849728965383016823
|
||||
},
|
||||
"inputs": {
|
||||
"cone": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
360,
|
||||
1,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"domains": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"op": 3,
|
||||
"other": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
360,
|
||||
1,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"same": false,
|
||||
"tolerance": null
|
||||
},
|
||||
"name": "fuzz_trim_domain_02497",
|
||||
"upstream_ref": "source/SMLib/src/SmCone.cpp:5325 (sm_GetEllipseTrimIntervals ignores ConvertDomainFromNURBSToSTEP status; zero Y axis leaves no polar curve)"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -424,7 +424,13 @@ void run_op(int32_t op, Rd& rd, const char* path, std::vector<double>& o)
|
||||
double dist = rd.num();
|
||||
SmTopology* a = topo(g, t1, i1);
|
||||
SmTopology* c = topo(g, t2, i2);
|
||||
// the edge branch dereferences the surfaces of both edges' faces
|
||||
// the edge branch dereferences the surfaces of both edges' faces. The vertex branch
|
||||
// reaches the edge branch too (its recursive calls, SmStitch.cpp:157, :222), unguarded:
|
||||
// that is safe because no block of this harness builds a face without a surface. The
|
||||
// face kinds, the sheets and SmApiCreateBox always attach one, and none of the 15
|
||||
// upstream .smb files in topology.edgeuse_p1's FILES has a surface-less face (checked
|
||||
// over every face after ReadFromFile; SmallBox.smb and Platform.smb are excluded because
|
||||
// ReadFromFile itself crashes on them).
|
||||
if (t1 == TY_EDGE && t2 == TY_EDGE)
|
||||
for (SmFace* f : g.faces)
|
||||
if (f->GetSurface() == NULL)
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace
|
||||
{
|
||||
// Status of an op the shim refuses because upstream would dereference null (or recurse
|
||||
// without bound).
|
||||
const double ST_HANG34_GUARD = -34.0; // the runner reports the case as rejected
|
||||
const double ST_NULL_DEREF = -2.0;
|
||||
const SmStatus SM_ST_NULL_DEREF = (SmStatus)(-2);
|
||||
// Deepest sm_MarkLoopsToDelete recursion followed (as topology::brep::p1::MAX_LOOP_NESTING).
|
||||
@@ -665,6 +666,7 @@ enum Op
|
||||
OP_EDGE_EDGE_BLEND = 24,
|
||||
OP_PARALLEL_PROJ = 25,
|
||||
OP_HEAL = 26,
|
||||
OP_EDGE_EDGE_BLEND2 = 27,
|
||||
};
|
||||
|
||||
// The type codes IsKindOf is asked about.
|
||||
@@ -800,14 +802,25 @@ void attach(Rd& rd, Graph& g, int64_t id)
|
||||
}
|
||||
|
||||
|
||||
// SmBrep::CreateCornerBlend (SmBrep.cpp:2488-2665) up to the end of its UV phase, replayed
|
||||
// read-only on a copy of the B-rep (surface types preserved): TRUE when the real call would
|
||||
// copy a NULL UV trim curve (`SM_ASSERT(pUVCurve != NULL)` is a release no-op and
|
||||
// `pUVCurve->Copy` dereferences it). The replay keeps upstream's ordering, statuses and
|
||||
// early returns, so it is TRUE exactly when the real call reaches that dereference.
|
||||
static bool corner_blend_uv_null(SmBrep* brep, const SmContext& ctx, const SmTArray<SmEdgeuse*>& eus,
|
||||
const SmTArray<SmBoolean>* tans, double tol)
|
||||
// SmBrep::CreateCornerBlend (SmBrep.cpp:2488-2775) replayed read-only on a copy of the B-rep
|
||||
// (surface types preserved), through SmBSplineSurface::CreateCornerBlend's curve conversion
|
||||
// (SmBSplineSurfaceNLib.cpp:3060-3115, sm_CreateNonRationalCurve :2906-2965). TRUE when the real
|
||||
// call would dereference memory it does not have:
|
||||
// - the UV phase copies a NULL UV trim curve (`SM_ASSERT(pUVCurve != NULL)` is a release no-op
|
||||
// and `pUVCurve->Copy` dereferences it);
|
||||
// - UB-195: a rational B-spline 3D curve with a neighbour surface whose DropCurve succeeds with
|
||||
// no curve, and `sUVCurves[0]` reads the empty array (the `SM_ASSERT(GetSize() == 1)` is a
|
||||
// release no-op).
|
||||
// The replay keeps upstream's ordering, statuses and early returns, so it is TRUE exactly when
|
||||
// the real call reaches one of those dereferences. `reaches_tangents` reports whether the call
|
||||
// gets past the curve conversion into the cross-tangent approximation, the only place the
|
||||
// tangency tolerance is used (four sides with a neighbour surface, or more sides; HANG-39). The
|
||||
// later MakeCurvesCompatible / EditParameterization statuses are not replayed, so it may report
|
||||
// a call that stops there.
|
||||
static bool corner_blend_refused(SmBrep* brep, const SmContext& ctx, const SmTArray<SmEdgeuse*>& eus,
|
||||
const SmTArray<SmBoolean>* tans, double tol, bool& reaches_tangents)
|
||||
{
|
||||
reaches_tangents = false;
|
||||
SmCopyBrepMap rev;
|
||||
SmBrep* copy = new (ctx) SmBrep(*brep, NULL, &rev, TRUE, FALSE);
|
||||
SmObjDelete copy_clean(copy);
|
||||
@@ -884,6 +897,12 @@ static bool corner_blend_uv_null(SmBrep* brep, const SmContext& ctx, const SmTAr
|
||||
if (!found)
|
||||
tol_scale *= 2.5;
|
||||
}
|
||||
// the CreateCornerBlend input arrays (copies owned here)
|
||||
SmTArray<SmCurve*> o3d;
|
||||
SmObjsDelete<SmCurve*> clean3d(&o3d);
|
||||
SmTArray<SmBSplineCurve*> ouv;
|
||||
SmObjsDelete<SmBSplineCurve*> cleanuv(&ouv);
|
||||
SmTArray<SmSurface*> osrf;
|
||||
for (ULONG ii = 0; ii < ordered.GetSize(); ii++)
|
||||
{
|
||||
SmEdgeuse* eu = ordered[ii];
|
||||
@@ -891,11 +910,16 @@ static bool corner_blend_uv_null(SmBrep* brep, const SmContext& ctx, const SmTAr
|
||||
SmCurve* crv = NULL;
|
||||
if (e->GetCurve()->Copy(ctx, crv) != SM_SUCCESS)
|
||||
return false;
|
||||
SmObjDelete crv_clean(crv);
|
||||
o3d.Add(crv);
|
||||
SmExtent1d ivl = e->GetInterval();
|
||||
if (crv->Trim(ivl) != SM_SUCCESS)
|
||||
return false;
|
||||
if (tangencies[ii])
|
||||
if (!tangencies[ii])
|
||||
{
|
||||
ouv.Add(NULL);
|
||||
osrf.Add(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
SmBSplineCurve* uv = NULL;
|
||||
eu->GetOrCreateUVTrimCurve(uv);
|
||||
@@ -904,13 +928,84 @@ static bool corner_blend_uv_null(SmBrep* brep, const SmContext& ctx, const SmTAr
|
||||
SmCurve* uv_copy = NULL;
|
||||
if (uv->Copy(ctx, uv_copy) != SM_SUCCESS)
|
||||
return false;
|
||||
SmObjDelete uv_clean(uv_copy);
|
||||
if (!SM_CAST_PTR(SmBSplineCurve, uv_copy))
|
||||
SmBSplineCurve* uv_b = SM_CAST_PTR(SmBSplineCurve, uv_copy);
|
||||
if (!uv_b)
|
||||
{
|
||||
delete uv_copy;
|
||||
return false;
|
||||
if (eu->GetFace() == NULL)
|
||||
}
|
||||
ouv.Add(uv_b);
|
||||
SmFace* f = eu->GetFace();
|
||||
if (f == NULL)
|
||||
return false;
|
||||
osrf.Add(f->GetSurface());
|
||||
}
|
||||
}
|
||||
// pad to 4 curves with point curves, then move the last entry to the front
|
||||
for (ULONG ii = 0; ii < 2; ii++)
|
||||
{
|
||||
if (o3d.GetSize() >= 4)
|
||||
break;
|
||||
double param = (orients[1] == SM_OT_SAME) ? 1.0 : 0.0;
|
||||
SmPoint3d pnt;
|
||||
if (o3d[1]->EvaluatePoint(param, pnt) != SM_SUCCESS)
|
||||
return false;
|
||||
SmBSplineCurve* top = NULL;
|
||||
if (SmBSplineCurve::CreatePointCurve(ctx, pnt, top) != SM_SUCCESS)
|
||||
return false;
|
||||
o3d.InsertAt(2 - ii, top);
|
||||
orients.InsertAt(2 - ii, SM_OT_SAME);
|
||||
ouv.InsertAt(2 - ii, (SmBSplineCurve*)NULL);
|
||||
osrf.InsertAt(2 - ii, (SmSurface*)NULL);
|
||||
}
|
||||
o3d.InsertAt(0, o3d.GetLast());
|
||||
o3d.RemoveLast();
|
||||
ouv.InsertAt(0, ouv.GetLast());
|
||||
ouv.RemoveLast();
|
||||
osrf.InsertAt(0, osrf.GetLast());
|
||||
osrf.RemoveLast();
|
||||
// SmBSplineSurface::CreateCornerBlend(.., dThisApproxTol3d, .., bCreateBilinearPatch = FALSE)
|
||||
ULONG n = o3d.GetSize();
|
||||
if (n < 4)
|
||||
return false;
|
||||
ULONG nulls = 0;
|
||||
for (ULONG ii = 0; ii < n; ii++)
|
||||
{
|
||||
if (ouv[ii] == NULL || osrf[ii] == NULL)
|
||||
nulls++;
|
||||
if (((n == 4 && nulls > 1) || (n > 4 && nulls > 0)) && (ouv[ii] == NULL || osrf[ii] == NULL))
|
||||
return false; // NER(crUVCurves[ii]) / NER(crSurfaces[ii])
|
||||
}
|
||||
for (ULONG ii = 0; ii < n; ii++)
|
||||
{
|
||||
SmBSplineCurve* nurb = SM_CAST_PTR(SmBSplineCurve, o3d[ii]);
|
||||
if (!nurb)
|
||||
return false; // NER(pNurb)
|
||||
if (!nurb->IsRational())
|
||||
continue; // a plain copy
|
||||
SmBSplineCurve* approx = NULL;
|
||||
if (nurb->ApproximateRationalCurve(ctx, tol / 2.0, approx) != SM_SUCCESS)
|
||||
return false;
|
||||
SmObjDelete approx_clean(approx);
|
||||
if (approx->ReparametrizeWithArcLength() != SM_SUCCESS)
|
||||
return false;
|
||||
if (osrf[ii])
|
||||
{
|
||||
SmExtent1d trim = approx->GetNaturalInterval();
|
||||
SmExtent2d dom = osrf[ii]->GetNaturalUVDomain();
|
||||
double max_dist, deviation;
|
||||
SmTArray<SmBSplineCurve*> dropped;
|
||||
SmObjsDelete<SmBSplineCurve*> dropped_clean(&dropped);
|
||||
if (osrf[ii]->DropCurve(ctx, dom, *approx, trim, tol / 2.0, max_dist, deviation, dropped) != SM_SUCCESS)
|
||||
return false;
|
||||
if (dropped.GetSize() == 0)
|
||||
return true; // UB-195
|
||||
}
|
||||
}
|
||||
reaches_tangents = n > 4;
|
||||
for (ULONG ii = 0; ii < n; ii++)
|
||||
if (osrf[ii] != NULL)
|
||||
reaches_tangents = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1762,7 +1857,8 @@ void run_op(int32_t op, Rd& rd, const char* path, std::vector<double>& o)
|
||||
if (p == NULL || p->GetEdge() == NULL)
|
||||
null_deref = true;
|
||||
}
|
||||
if (!null_deref && corner_blend_uv_null(brep, ctx, eus, has_tan ? &tans : NULL, tol))
|
||||
bool reaches_tangents = false;
|
||||
if (!null_deref && corner_blend_refused(brep, ctx, eus, has_tan ? &tans : NULL, tol, reaches_tangents))
|
||||
null_deref = true;
|
||||
if (null_deref)
|
||||
{
|
||||
@@ -1770,6 +1866,14 @@ void run_op(int32_t op, Rd& rd, const char* path, std::vector<double>& o)
|
||||
o.push_back(0.0); // upstream resets the output array first
|
||||
break;
|
||||
}
|
||||
// HANG-39: a tangency tolerance below what doubles resolve makes the cross-tangent
|
||||
// approximation and the Coons knot merge run for tens of seconds or more; the case
|
||||
// is rejected only where upstream reaches that approximation
|
||||
if (reaches_tangents && ang < 1e-20)
|
||||
{
|
||||
o.push_back(ST_HANG34_GUARD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SmTArray<SmSurface*> blends;
|
||||
SmStatus s = brep->CreateCornerBlend(ctx, eus, has_tan ? &tans : NULL, tol, ang, blends);
|
||||
@@ -1817,6 +1921,32 @@ void run_op(int32_t op, Rd& rd, const char* path, std::vector<double>& o)
|
||||
delete out;
|
||||
break;
|
||||
}
|
||||
case OP_EDGE_EDGE_BLEND2:
|
||||
{
|
||||
// the static SmBrep::CreateEdgeEdgeBlend with the second edge use in another B-rep
|
||||
// (ruled; the FFI checks the second block builds and both indices)
|
||||
SmStatus bst2;
|
||||
Built b2;
|
||||
b2.brep = build(rd, "", bst2);
|
||||
int64_t i1 = rd.idx(), i2 = rd.idx();
|
||||
int64_t dir = rd.idx();
|
||||
if (b2.brep == nullptr)
|
||||
{
|
||||
o.push_back(st(bst2));
|
||||
break;
|
||||
}
|
||||
Graph g2;
|
||||
walk(b2.brep, g2);
|
||||
walk_more(b2.brep, g2);
|
||||
SmSurface* out = nullptr;
|
||||
SmStatus s = SmBrep::CreateEdgeEdgeBlend(ctx, 0, g.edgeuses[(size_t)i1], g2.edgeuses[(size_t)i2],
|
||||
(ULONG)dir, NULL, out);
|
||||
o.push_back(st(s));
|
||||
if (s == SM_SUCCESS)
|
||||
put_surface(o, out);
|
||||
delete out;
|
||||
break;
|
||||
}
|
||||
case OP_PARALLEL_PROJ:
|
||||
{
|
||||
SmBSplineCurve* c = read_curve(rd, ctx);
|
||||
|
||||
+4
-4
@@ -157,7 +157,7 @@ Anything `todo` can be claimed. These need stubs for, or co-porting of, the list
|
||||
- [x] ✅ `curve.composite_curve_p1` (1700 lines) — green, 3093 cases
|
||||
- [x] ✅ `curve.composite_curve_p2` (1345 lines) — green, 661 cases
|
||||
- [ ] 🟡 `curve.curve_p5` (2299 lines) — partial, 3097 cases
|
||||
- [x] ✅ `curve.curve_p9` (1783 lines) — green, 3093 cases
|
||||
- [x] ✅ `curve.curve_p9` (1783 lines) — green, 3111 cases
|
||||
|
||||
### surface (40/40)
|
||||
|
||||
@@ -189,7 +189,7 @@ Anything `todo` can be claimed. These need stubs for, or co-porting of, the list
|
||||
- [x] ✅ `surface.sphere` (2861 lines) — green, 800 cases
|
||||
- [ ] 🟡 `surface.surf_of_extrusion_p2` (1420 lines) — partial, 1373 cases
|
||||
- [x] ✅ `surface.surface_p5` (2321 lines) — green, 3046 cases
|
||||
- [ ] 🟡 `surface.cone_p3` (1939 lines) — partial, 1415 cases
|
||||
- [ ] 🟡 `surface.cone_p3` (1939 lines) — partial, 1416 cases
|
||||
- [ ] 🟡 `surface.surface_p1` (2458 lines) — partial, 806 cases
|
||||
- [x] ✅ `surface.surface_p6` (2150 lines) — green, 2099 cases
|
||||
- [ ] 🟡 `surface.srf_in_volume` (779 lines) — partial, 2036 cases
|
||||
@@ -225,7 +225,7 @@ Anything `todo` can be claimed. These need stubs for, or co-porting of, the list
|
||||
- [ ] 🟡 `topology.topology_traverser` (784 lines) — partial, 909 cases
|
||||
- [ ] 🟡 `topology.brep_p7` (2503 lines) — partial, 316 cases
|
||||
- [ ] 🟡 `topology.face_p1` (2171 lines) — partial, 2312 cases
|
||||
- [ ] 🟡 `topology.brep_p1` (2454 lines) — partial, 2589 cases
|
||||
- [ ] 🟡 `topology.brep_p1` (2454 lines) — partial, 2627 cases
|
||||
- [ ] 🟡 `topology.brep_p6` (1479 lines) — partial, 498 cases
|
||||
- [ ] 🟡 `topology.brep_cache` (389 lines) — partial, 663 cases
|
||||
- [ ] 🔨 `topology.brep_p4` (2113 lines) — in progress: #173 @froglemonade2 (ready for review)
|
||||
@@ -315,7 +315,7 @@ Anything `todo` can be claimed. These need stubs for, or co-porting of, the list
|
||||
|
||||
### boolean (7/9)
|
||||
|
||||
- [ ] 🟡 `boolean.topology_intersector_p1` (2491 lines) — partial, 827 cases
|
||||
- [ ] 🟡 `boolean.topology_intersector_p1` (2491 lines) — partial, 830 cases
|
||||
- [ ] 🟡 `boolean.topology_intersector_p2` (2195 lines) — partial, 841 cases
|
||||
- [ ] 🔨 `boolean.topology_intersector_p3` (1849 lines) — in progress: #211 @oursland (draft)
|
||||
- [ ] 🟡 `boolean.merge_p1` (993 lines) — partial, 248 cases
|
||||
|
||||
+111
-15
@@ -7807,24 +7807,38 @@ PR #203 (on main's #146). Part 2 of `SmTopologyIntersector.cpp`: `RegisterExisti
|
||||
- **Coverage (what the passes complete).** Per op occurrence in non-deferred cases:
|
||||
`RemoveRelationship` 29 success / 35 `SM_ERR`; `CheckForSqueezeVertices` 75 success
|
||||
without a conflicting mate (empty lists) / 26 `SM_ERR` (existing relationship better),
|
||||
every conflict that combines defers (`CombineCoincidentVertices`, `topology.brep_p5`);
|
||||
every conflict that combines defers inside `CombineCoincidentVertices` (wired to
|
||||
`topology.brep_p5` through `IntersectorBrepP2::brep_combine_coincident_vertices`);
|
||||
`DeleteFaces` 68 success, all with an empty face list (a face reaches `SmFace::GetEdges`,
|
||||
`topology.face_p4`); `FixGaps` 119 success without a gap pair / 14
|
||||
`SM_ERR_NULL_POINTER` (gap pair with an unmated vertex); `SetRelationships` 39 success on
|
||||
`SM_ERR_NULL_POINTER` (gap pair with an unmated vertex), a pair that combines defers
|
||||
as in `CheckForSqueezeVertices`; `SetRelationships` 39 success on
|
||||
managers without definitions; `FixupClassMates` 56 success / 17 `SM_ERR` (sizes differ);
|
||||
`FixupSplitVertexPair` 57 success, 6 removing the interval; `EdgeEdgeIntersect` 127
|
||||
success without a split (a split defers on `MakeVertexSplitEdge`, `topology.brep_p9`);
|
||||
`FixupSplitVertexPair` 57 success, 6 removing the interval; `EdgeEdgeIntersect` 136
|
||||
success, none with a non-empty first split list (the 9 that reached
|
||||
`MakeVertexSplitEdge` compare since main's `topology.brep_p9`);
|
||||
`EdgeFaceCoincidence` 128 success without an imprint (`Point3DClassify`,
|
||||
`query.face_p1`); `IntersectTopology` and `IntersectInsertRelate`: no passing case (both
|
||||
start with `SmBrep::GetFaces`, `topology.brep_p1`). The census is the ignored test
|
||||
`units::boolean_topology_intersector_p2::tests::census`. Main's topology.shell fixture changes
|
||||
(the shell-state export and import, `sc_topology_fixture::append_shell_state` /
|
||||
`topology_vertexuse::read_shell_state`, and the GetEdges-first walk) changed 10 generated
|
||||
cases at the merge of main@86f2d3bd: the walk renumbers the handles, so the same seeds
|
||||
select other entities and the C++ reference output itself changes, not only the Rust
|
||||
side. Net -2 passes: 4 pass -> defer (2 at `MakeVertexSplitEdge`, 2 at
|
||||
`CombineCoincidentVertices`) and 2 defer -> pass; the other 4 still pass with a different
|
||||
value count (more in most, gen0767 172 -> 169). 0 fail before and after.
|
||||
`query.face_p1`); `IntersectTopology` 1 success (the smTopoTest pair
|
||||
`RegisterExistingSSI` marks as not intersecting) and `IntersectInsertRelate` none: with
|
||||
`SmBrep::GetFaces` wired to `topology.brep_p1` (`IntersectorBrepP2::brep_faces`), the
|
||||
former 124 `GetFaces` deferrals stop at `SmFace::GetTolerance` (70, `topology.face_p2`),
|
||||
`SmBrep::CalculateBoundingBox` (41, `query.brep`) and `SmFace::FaceIntersect` (12,
|
||||
`topology.face_p3`); 1 passes. With `CombineCoincidentVertices` wired to
|
||||
`topology.brep_p5` (follow-up to #203, after main@36cfad06), its 15 deferrals stop
|
||||
inside it: `SmBrep::SqueezeEdge` 8 (`topology.brep_p3`), `SmBrep::Notify` 4
|
||||
(`topology.brep_p2`), `SmBrep::m_bEditingEnabled` 3 (`topology.brep_p1`); none
|
||||
passes yet, so the shim's `squeeze_breps_ok` assumption (a first block that combines
|
||||
reaches the second) is still unexercised: re-check it when those land. Main's
|
||||
`topology.face_p3` (#139) moved the 3 `CreateUVTrimCurves` deferrals on to
|
||||
`SmFace::GetUpwardLoopuses` (`topology.face_p4`). The census is the ignored test
|
||||
`units::boolean_topology_intersector_p2::tests::census`. Main's topology.shell fixture
|
||||
changes (the shell-state export and import, `sc_topology_fixture::append_shell_state` /
|
||||
`topology_vertexuse::read_shell_state`, and the GetEdges-first walk) changed 10
|
||||
generated cases at the merge of main@86f2d3bd: the walk renumbers the handles, so the
|
||||
same seeds select other entities and the C++ reference output itself changes, not only
|
||||
the Rust side. Net -2 passes: 4 pass -> defer (2 at `MakeVertexSplitEdge`, 2 at
|
||||
`CombineCoincidentVertices`) and 2 defer -> pass; the other 4 still pass with a
|
||||
different value count (more in most, gen0767 172 -> 169). 0 fail before and after.
|
||||
- **Guards.** The shim refuses (`-2`) what upstream dereferences: vertex members of a mate
|
||||
that is not a vertex, edges of a vertex without curve (`FixGaps`,
|
||||
`EdgeFaceCoincidence`), faces without surface, an interval index past a
|
||||
@@ -9044,6 +9058,64 @@ rejected: nothing runs on either side.
|
||||
edge-edge blends reach under `CreateBlendSurface`; UB-11's entry records why that read
|
||||
cannot change a result. Without it, the edge-edge sample reports exactly that one error.
|
||||
|
||||
- **Follow-up to #145's maintainer review (bherbruck, at 5b1b28ae; #145 merged with #196).**
|
||||
- **Corner blend on non-B-spline edge curves.** The ordered 3D curves stay `Curve` through the
|
||||
point-curve padding (upstream copies, trims and evaluates any `SmCurve`). At the
|
||||
`SmBSplineSurface::CreateCornerBlend` call, the first curve that is not B-spline-derived gives
|
||||
`SM_ERR_NULL_POINTER` (1006, `sm_CreateNonRationalCurve`'s `NER(pNurb)`), after upstream's NULL
|
||||
UV curve / surface check, which returns the same status. When a rational curve comes before it,
|
||||
the case defers to `nurbs.b_spline_surface_n_lib_p2`, because that conversion is not run here.
|
||||
It used to report the null-dereference guard (-2). 30 `crv_on_surf_face` corner-blend fixtures
|
||||
(10 B-reps x eus `[0,1,2,3]`, `[3,2,1,0]` and all-non-tangent): 25 pass and 5 defer at
|
||||
`nurbs.b_spline_surface_n_lib_p2`.
|
||||
- **`CreateEdgeEdgeBlend` takes each edge use's B-rep** (`b_2: None` when both are in `b_1`).
|
||||
`offset_executive_p1`'s stub is wired: `build_side_wall_of_edgeuse` takes the original B-rep and
|
||||
now defers at `SmBrep::CreateFaceFromSurface` (`topology.brep_p8`). A new op, `edge_edge_blend2`,
|
||||
compares the ruled blend across two B-reps: distinguishable rails, unequal intervals, all
|
||||
three direction flags and the mate edge use, with the second B-rep imported into its own
|
||||
Rust arena (5 cases).
|
||||
- **Known back-edges left** (`UNPORTED(topology.brep_p1)` sites outside this unit):
|
||||
- `offset_executive_p1.rs:827` (`GetInfiniteRegion` ahead of #175's unported
|
||||
`MakeFaceWithCurves` tail): its own follow-up, in COORD.md.
|
||||
- `intersect/curve_class/p2.rs:267` (from #85): `IsLiveTopologyMember` is ported, but the site
|
||||
holds a generic point-class handle and needs a `ClassObject` → `EntityRef` accessor in
|
||||
`intersect.point_class`.
|
||||
- `topology/brep/p7.rs` `GetInfiniteRegion` / `SetInfiniteRegion`: wired by the brep_p7 owner
|
||||
in #246, together with the region-list head removal and the p7 runner's native infinite region.
|
||||
- **Shared `SmCrvOnSurf` import:** owner flag 1, as the C++ graph builds it. Compared case by case
|
||||
over all 208 green/partial units; it changes no case.
|
||||
- **`SmTol::GetZoneTol3d(const SmObject*)` stubs** are tagged `geom.tol` (the owner in
|
||||
`units.json`; the maintainer's answer), at the 7 call sites and the `geom/tol.rs` header. That
|
||||
moves 26 `curve.curve_p1`, 48 `intersect.topology_solver_p1` and 6 `intersect.topology_solver_p2`
|
||||
deferrals to the `geom.tol` label; nothing else changes.
|
||||
- **`ParallelProj`:** a non-positive angle tolerance, or an approximation tolerance below the
|
||||
smallest normal double (HANG-32: 5e-324 spins upstream), is rejected on both sides instead of
|
||||
failing.
|
||||
- **Fuzz findings on the corner-blend path** (the shim has run the real C++ since the edge-use
|
||||
wiring; the new fixtures give the mutator new shapes):
|
||||
- UB-195 [PSIRT]: `sm_CreateNonRationalCurve` reads `sUVCurves[0]` after a rational curve's
|
||||
`DropCurve` succeeds with no curve. Located with gdb on a `-g` build at
|
||||
SmBSplineSurfaceNLib.cpp:2949. The shim's corner-blend replay now runs on to that drop, and
|
||||
both sides report the guard.
|
||||
- HANG-39: tangency tolerances below about 1e-24 over-refine the cross tangents, and the Coons
|
||||
knot merge then runs for tens of seconds. A tolerance below 1e-20 is rejected only where
|
||||
upstream reaches the cross-tangent approximation: the shim's replay has passed every early
|
||||
return and the curve conversion (four sides with a neighbour surface, or more sides). Calls
|
||||
that stop earlier keep their statuses, which are compared: one edge use gives `SM_ERR`, four
|
||||
non-tangent edge uses give 1006. The later `MakeCurvesCompatible` / `EditParameterization`
|
||||
statuses are not replayed, so a call stopping there can be rejected too.
|
||||
- A face block with a 1e300 control point recurses in `GlobalCoincidenceChecker` while its UV
|
||||
trim curves are built. That is HANG-29 (#147); the reserved HANG-33 was retired as a
|
||||
duplicate. Every block value is bounded at 1e150.
|
||||
- **Open question for the `curve.line` / `topology.edge` / `topology.face_p2` owners.** A Rust
|
||||
`Line` whose parameterisation was edited carries no NURB, and the slicing copies
|
||||
(`topology::edge::bspline_slice` in `CreateTrimmedNURBSCurve`, `topology::face::p2::bspline_slice`,
|
||||
this unit's `bspline_part`) hand on that NURB-less base: a ruled `CreateEdgeEdgeBlend` over such
|
||||
edges fails with `make_nurb` `SM_ERR`. Upstream's `new SmBSplineCurve(*SM_CAST_PTR(..))` copies
|
||||
the base too, and whether its `MakeNurb` then succeeds depends on `SmLine::EditParameterization`.
|
||||
Not changed here; the difftest never builds `Line` edges, and the offset unit test uses B-spline
|
||||
edges.
|
||||
|
||||
## topology.face_p1 (`SmFace.cpp` part 1: `MoveSeam`, `SplitAtSeam`, `CreateOrientedTrimBoundary`, `CalculateUVDomainFromUVTrimCurves`, ...; PR #148, 2026-10-16; partial, no disagreements)
|
||||
|
||||
- **Mostly deferred by design.** Every mutating member starts with `SmFace::Notify`
|
||||
@@ -9853,7 +9925,7 @@ Wiring #146's `UNPORTED(topology.brep_p1)` stubs `SmBrep::GetEdges` / `GetVertic
|
||||
Difftest (`fixtures/heal.stitch_p1/constructed.json`: the SM_API_test box tests, `SmApiStitch(NULL)`, every entry point's null guard, two-square sheets with corner gaps 0, 1e-4 and 5e-3, and boundary cases for the review's mutation probe; generated: unstitched grids of bilinear/biquadratic patches pulled apart by per-face gaps, `SmApiCreateBox`, and the `topology.edgeuse_p1` B-rep blocks): 300 cases, 206 pass (all comparing values), 0 failed, 94 deferred; 1000 seeds 1284 / 868 / 0 / 410 with 6 rejected. No disagreement.
|
||||
|
||||
- **The shim compiles `SmStitch.cpp` with its classes renamed** (`sc_st_Stitch`, `sc_st_Callback`) so the file-statics `sm_CheckInteriorEdge` / `sm_TestAndSplitEdge` are callable; the `#define`s must precede every upstream include (`StdAfx.h` -> `SmSmlibAll.h` declares the classes).
|
||||
- **Coverage.** Values are compared for `SelectTopologyToKeep` (both branches, through the default callback), `StitchVertexPairs` and `StitchEdgesOfVertices` up to their first glue, `sm_CheckInteriorEdge`, `sm_TestAndSplitEdge` up to `MakeVertexSplitEdge`, the API null guards, and `DoSimpleFaceStitch`'s validation statuses: the shim refuses (UB-177) only inputs that pass upstream's validation (a read-only copy of it) and then meet a freed-vertex, repeated-delete-face or repeated-vertex condition (a vertex in more than one entry of the two vertex lists, the self-pair included; a repeated vertex whose first entry would free nothing, because of a skipped squeeze, a short manifold common edge, the making-manifold-solid skip or the loop ending first with `SM_ERR`, is over-refused, deliberately), so every `SM_ERR` of the validation is compared. `UnifyNormals` defers from `SmBrep::CalculateBoundingBox` (query.brep). The glue calls (brep_p5 / brep_p7 / brep_p3 / brep_p9) end every mutating path; when they land, the shim's B-rep digest is compared after each mutation.
|
||||
- **Coverage.** Values are compared for `SelectTopologyToKeep` (both branches, through the default callback), `StitchVertexPairs` and `StitchEdgesOfVertices` up to their first glue, `sm_CheckInteriorEdge`, `sm_TestAndSplitEdge` up to `MakeVertexSplitEdge`, the API null guards, and `DoSimpleFaceStitch`'s validation statuses: the shim refuses (UB-177) only inputs that pass upstream's validation (a read-only copy of it) and then meet a freed-vertex, repeated-delete-face or repeated-vertex condition (a vertex in more than one entry of the two vertex lists, the self-pair included; a repeated vertex whose first entry would free nothing, because of a skipped squeeze, a short manifold common edge, the making-manifold-solid skip or the loop ending first with `SM_ERR`, is over-refused, deliberately), so no validation `SM_ERR` is refused. Today only the empty or mismatched-list `SM_ERR` is compared: on the Rust side the `face_in_brep` check (the `topology.face_p4` stub) runs before the rest of the validation, so those cases defer (review of #196). `UnifyNormals` defers from `SmBrep::CalculateBoundingBox` (query.brep). The glue calls (brep_p5 / brep_p7 / brep_p3 / brep_p9) end every mutating path; when they land, the shim's B-rep digest is compared after each mutation.
|
||||
- **Mutation probe (review S3).** With the boundary fixtures, `SelectTopologyToKeep`'s `tol * 10 -> * 5` (8 failures) and `sm_TestAndSplitEdge`'s `max(tol, edge tol) -> tol` (32) are detected. `sm_CheckInteriorEdge`'s `param_tol * 20 -> * 10` changes a result only for a point 10-20 parametric tolerances from an end that lies within `tol` of a vertex in 3d, which needs a vertex away from its curve end (none of the fixture or generated B-reps has one). `StitchVertexPairs`' `dist < tol -> <=` glues a pair at exactly `tol`, so it turns a pass into a deferral (`GlueVertices`, topology.brep_p5) until the glue lands.
|
||||
- **topology.face_p2 deferrals (49 of 94).** The curve/surface distance measures reach main's existing stub for `SmTol::GetZoneTol3d` of a face-owned surface (`SmFace::GetTolerance`, `surface/surface/p1.rs`, `surface/plane/p2.rs`): surface code cannot reach the face's B-rep. The label is main's (lesson 21).
|
||||
- **Uninitialised reads upstream** (documented in the Deviations): `DoSimpleFaceStitch` reads `dDistToCurve` after an ignored failed `CurveMaxDistanceBetween` (the port reads 0). (`UnifyNormals`' `sPnt` / `sDir` after an ignored failed `NormalizedEvaluate` are not uninitialised: they keep the defined default `SM_UNDEF_DOUBLE`; see the edge-use wiring below.)
|
||||
@@ -10443,6 +10515,30 @@ with maximum relative error 0.
|
||||
only when it walks the selected list. It over-rejects about 3% of generated cases;
|
||||
narrowing it means replaying upstream's list selection and early returns in the shim.
|
||||
|
||||
## surface.cone_p3 / surface.cone_p2: ignored trim-domain conversion status (fuzz after PR #226, 2026-10-20)
|
||||
|
||||
- **Disagreement.** fuzz02497 (a global cone/cone call whose first cone has a zero Y
|
||||
axis, so `MakeNurb` leaves no polar curve): C++ succeeds, Rust returned status 1006.
|
||||
`sm_GetEllipseTrimIntervals` ignores the status of `ConvertDomainFromNURBSToSTEP`
|
||||
(`SmCone.cpp:5325`). When a corner conversion fails (`NER(m_cpCurve)` in
|
||||
`ConvertToPolarParameter`), the domain stays default-constructed (`SmExtent2d::Init`,
|
||||
defined), but `ellipse_trim_intervals` propagated the error. It now ignores the status
|
||||
and keeps `Extent2d::new()`, so the domain matches upstream exactly.
|
||||
Fixture: `surface.cone_p3/fuzz_trim_domain.json`. UB-154 updated: only the line/plane
|
||||
part is undefined.
|
||||
- **Results (Linux):** `PARTIAL surface.cone_p3 cases=1416 passed=1381 failed=0
|
||||
deferred=35 max_rel_err=0e0`, `--perturb` detects 1381/1381; `PASS surface.cone_p2
|
||||
cases=1550`; `--green` 222 units, 114 passed, 108 partial, 0 failed.
|
||||
- **Still open (pre-existing on main, not fixed here).** The same 10,000-case fuzz finds
|
||||
two cases (fuzz00656, `/domains/2 = -1e+300`; fuzz09540, `/domains/5 = 1e+300`) where a
|
||||
huge trim-domain fraction gives a zero-length seam line. Rust's `line_plane_intersect`
|
||||
returns `InvalidInput` (status 1007); upstream ignores that status and reads the
|
||||
uninitialised `dParam` (UB-154), so C++ returns a value. The `surface.cone_p2` shim
|
||||
refuses these inputs (`trim_defined`); the `surface.cone_p3` path reaches the file-static
|
||||
`sm_GetEllipseTrimIntervals` through `IntersectWithCone`, which has no such guard yet.
|
||||
Reproduced with main's unpatched `cone/p2.rs` too. Tracked in issue #276; the
|
||||
`surface.cone_p2` refusals that are now stricter than needed are issue #277.
|
||||
|
||||
### blend.fillet_executive_p3 — dependency and coverage boundaries (PR #244)
|
||||
|
||||
All three executive control-flow bodies are present, including the continuation
|
||||
|
||||
+4
-4
File diff suppressed because one or more lines are too long
+29
-2
@@ -1002,12 +1002,12 @@ meantime, whoever merges renumbers the new entry and every reference to it (here
|
||||
|
||||
#### UB-154. `sm_GetEllipseTrimIntervals` reads the parameter of a failed line/plane intersection
|
||||
- **Location:** `source/SMLib/src/SmCone.cpp:5399`-`5405` and `:5463`-`5477`, `sm_GetEllipseTrimIntervals` (def. `:5282`, file static).
|
||||
- **What happens:** The statuses of `smgu_LinePlaneIntersect` for the two seam lines are ignored and `dParam[0]`, `dParam[1]` (uninitialised) are then compared and used. The same happens with the domain of a failed `ConvertDomainFromNURBSToSTEP` (default-constructed).
|
||||
- **What happens:** The statuses of `smgu_LinePlaneIntersect` for the two seam lines are ignored and `dParam[0]`, `dParam[1]` (uninitialised) are then compared and used. (The status of `ConvertDomainFromNURBSToSTEP` at `:5325` is ignored too, but that is defined: a failed corner conversion, e.g. of a cone without a polar curve, leaves the default-constructed domain, and a reversed one the NURB domain.)
|
||||
- **Trigger:** A seam line of the trimmed cone parallel to the ellipse plane (or of zero length, a zero-height trim domain).
|
||||
- **How found:** read during porting (`surface.cone_p2`, PR #153).
|
||||
- **Confirmed:** no. The shim runs the same calls first and refuses such inputs.
|
||||
- **Severity:** UB (uninitialised read).
|
||||
- **Rust port:** The errors are returned.
|
||||
- **Rust port:** The line/plane errors are returned. The ignored domain conversion is mirrored (fixture `surface.cone_p3/fuzz_trim_domain.json`).
|
||||
|
||||
#### UB-202. `SmCircularCrossSectionFSG::CreateSurfaceFromCurves` indexes past its cross sections in the second pass of a ruled or revolved surface
|
||||
- **Location:** `source/SMLib/src/SmFilletStandardSolver.cpp:3233` (`SmCircularCrossSectionFSG::CreateSurfaceFromCurves`): the first pass skips to the last knot for sweeps and revolves (`:3435`), so it stores three cross sections; the second pass (`m_bApproximateArcs` with differing unique knot counts) indexes `sCrossSections[lKnotIndex]` with `lKnotIndex` the knot index (`:3504`, `:3613`, `:3636`, `:3756`), which is at least 3 for the last knot.
|
||||
@@ -1582,6 +1582,33 @@ meantime, whoever merges renumbers the new entry and every reference to it (here
|
||||
|
||||
### Healer target management
|
||||
|
||||
#### HANG-32. `SmBrep::CreateParallelProjectionCurves` spins on a subnormal approximation tolerance
|
||||
- **Location:** `source/SMLib/src/SmBrep.cpp:4928`-`5012` (`SmBrep::CreateParallelProjectionCurves`, which calls `SmSurface::CreateParallelProjectionCurves` at `:4971`), then `SmSurfaceIntersector` / `SmSurface::LocalPointSolve`; the looping routine is not located.
|
||||
- **What happens:** With `dThisApproxTol3d = 5e-324` (the smallest subnormal double), the projection runs for more than 15 minutes without returning; `1e-100` returns at once.
|
||||
- **Trigger:** a caller-supplied subnormal approximation tolerance.
|
||||
- **How found:** the maintainer's adversarial run in the review of #145 (at `5b1b28ae`).
|
||||
- **Confirmed:** reported from the C++ reference run in that review; not re-run here (a 15-minute hang).
|
||||
- **Severity:** hang. Not file-reachable (a caller tolerance argument).
|
||||
- **Rust port:** unchanged. The `topology.brep_p1` difftest FFI refuses approximation tolerances below the smallest normal double (and the runner reports such cases as rejected on both sides).
|
||||
|
||||
#### HANG-39. `SmBrep::CreateCornerBlend` takes tens of seconds or more with a tangency tolerance below what doubles resolve
|
||||
- **Location:** `source/SMLib/src/SmBrep.cpp:2488`-`2775` -> `SmBSplineSurface::CreateCornerBlend` -> `SmBSplineSurface::CreateCoonsPatch` -> `N_MakeSrfsCompatible` -> `N_SrfInsertKnots` (where a hung run sits).
|
||||
- **What happens:** The cross-tangent curves are approximated to `dTangencyTolRadians` (`SmTangentField::ApproximateCurve`), which refines towards a tolerance no double computation meets; the over-refined curves then make the Coons patch's surface compatibility insert knots for tens of seconds. Measured on `plane_circ.smb` (three edge uses): `1e-23` returns in 0.4 s, `1e-24` in 1 s, `1e-25` in 22 s, `1e-26` in 47 s; `1e-27` and below, `0` and negative tolerances do not return within 60 s.
|
||||
- **Trigger:** a corner blend with a tangency tolerance of `0` (difftest fuzz program of `topology.brep_p1`), negative, or below about `1e-24`.
|
||||
- **How found:** difftest fuzzing of `topology.brep_p1` (the follow-up to #145); located with gdb on the running C++ reference.
|
||||
- **Confirmed:** yes (C++ reference runs, timed).
|
||||
- **Severity:** hang (unbounded slowness). A caller argument: no [PSIRT].
|
||||
- **Rust port:** unchanged. The `topology.brep_p1` shim rejects a tangency tolerance below `1e-20` (four decades of margin above the measured knee) only where its replay of the call reaches the cross-tangent approximation; earlier statuses stay compared.
|
||||
|
||||
#### UB-195. `sm_CreateNonRationalCurve` reads the first dropped curve of an empty array [PSIRT]
|
||||
- **Location:** `source/SMLib/src/SmBSplineSurfaceNLib.cpp:2938`-`2949` (`sm_CreateNonRationalCurve`, rational curve branch), reached from `SmBSplineSurface::CreateCornerBlend` (`:3100`-`3110`) and so from `SmBrep::CreateCornerBlend`.
|
||||
- **What happens:** For a rational B-spline boundary curve with a neighbour surface, the curve is approximated, reparametrised and dropped onto the surface with `DropCurve`. `DropCurve` can return `SM_SUCCESS` with no curve; `SM_ASSERT(sUVCurves.GetSize() == 1)` is a release no-op and `pNewUVTrimCurve = sUVCurves[0]` reads the array's NULL data (SIGSEGV).
|
||||
- **Trigger:** a corner blend whose ordered boundary curves include a rational B-spline edge curve of a tangent edge use whose drop onto its face surface yields no curve, with no earlier status stopping the call. The difftest met it on a face of a perturbed closed surface.
|
||||
- **How found:** difftest fuzzing of `topology.brep_p1` (the follow-up to #145); located with gdb on a `-g` build of the C++ reference.
|
||||
- **Confirmed:** yes (C++ reference run; the fault is at `:2949` with `m_lSize == 0`, `m_pData == NULL`).
|
||||
- **Severity:** crash/UB. **[PSIRT]:** reachable from a B-rep read from a `.smb` file through `SmBrep::CreateCornerBlend`.
|
||||
- **Rust port:** `nurbs::b_spline_surface_n_lib::p1::create_non_rational_curve` returns `InvalidInput` ("no dropped curve"). The `topology.brep_p1` shim refuses exactly those inputs by replaying `SmBrep::CreateCornerBlend` and the curve conversion on a copy of the B-rep up to the drop; the runner reports both sides as the null-dereference guard.
|
||||
|
||||
#### UB-163. Uncached healer props removal leaves targets that resize into NULL props holes
|
||||
- **Location:** `source/SMLib/src/SmHealData.cpp:1332-1333` (`RemoveVertexProps_FromLists` and analogous edge/face helpers), `:1224-1226` (`UpdateTargetLists`); later `Cache_CoinVertices` / `Cache_DegenFaces`.
|
||||
- **What happens:** removing a props record whose topology pointer has never been cached removes the props but not its target. A later nonempty add list resizes every props array from the target count and initializes only the new-target tail, leaving NULL holes for the unmatched old targets. Native coincidence/degeneracy caching can then dereference invalid state. Even a null add causes that resize. A later `Get*Props_ForTgts` can also index past a props list shortened by an uncached removal.
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
{
|
||||
"abs_floors": [],
|
||||
"cases": [
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "fuzz_neg_zone_tol_network",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/boolean.topology_intersector_p1/fuzz_regressions.json#0 (upstream SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01490, gave 103 vs C++ 104))",
|
||||
"values_compared": 46
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "fuzz_neg_zone_tol_plane_square_torus",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/boolean.topology_intersector_p1/fuzz_regressions.json#1 (upstream SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01531, gave 103 vs C++ 104))",
|
||||
"values_compared": 34
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "fuzz_neg_zone_tol_box_with_large_fillet",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/boolean.topology_intersector_p1/fuzz_regressions.json#2 (upstream SmCurveClassification ctor: SmZoneTol3d(-1e300) converts with fabs before ReSet keeps it (main 0cf3e290 --fuzz 2000 fuzz01875, gave 103 vs C++ 104))",
|
||||
"values_compared": 37
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "topo_test_network_relate_mates",
|
||||
@@ -7172,8 +7196,8 @@
|
||||
"cases_both_errored": 3,
|
||||
"cases_deferred": 137,
|
||||
"cases_failed": 0,
|
||||
"cases_passed": 690,
|
||||
"cases_total": 827,
|
||||
"cases_passed": 693,
|
||||
"cases_total": 830,
|
||||
"deferred_by_unit": {
|
||||
"query.brep": 16,
|
||||
"query.face_p1": 7,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4452,7 +4452,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0473",
|
||||
@@ -4752,7 +4752,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0510",
|
||||
@@ -5708,7 +5708,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0629",
|
||||
@@ -6160,7 +6160,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0685",
|
||||
@@ -6580,7 +6580,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0737",
|
||||
@@ -6992,7 +6992,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0788",
|
||||
@@ -7068,7 +7068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0797",
|
||||
@@ -7160,7 +7160,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0808",
|
||||
@@ -10052,7 +10052,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1169",
|
||||
@@ -10104,7 +10104,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1175",
|
||||
@@ -12476,7 +12476,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1471",
|
||||
@@ -12968,7 +12968,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1532",
|
||||
@@ -13532,7 +13532,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1602",
|
||||
@@ -14056,7 +14056,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1667",
|
||||
@@ -15036,7 +15036,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1789",
|
||||
@@ -17440,7 +17440,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2089",
|
||||
@@ -17820,7 +17820,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2136",
|
||||
@@ -18424,7 +18424,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2211",
|
||||
@@ -19060,7 +19060,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2290",
|
||||
@@ -20136,7 +20136,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2424",
|
||||
@@ -21692,7 +21692,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2618",
|
||||
@@ -22040,7 +22040,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2661",
|
||||
@@ -23020,7 +23020,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2783",
|
||||
@@ -23048,7 +23048,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2786",
|
||||
@@ -23596,7 +23596,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2854",
|
||||
@@ -24464,7 +24464,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2962",
|
||||
@@ -24776,7 +24776,7 @@
|
||||
"cases_passed": 3057,
|
||||
"cases_total": 3083,
|
||||
"deferred_by_unit": {
|
||||
"geom.solution_array": 26
|
||||
"geom.tol": 26
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"pass": true,
|
||||
|
||||
@@ -593,6 +593,150 @@
|
||||
"source": "fixture:fixtures/curve.curve_p9/edge.json#73 (upstream synthetic)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_issue_repro",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#0 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_1e-09",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#1 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 417
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_1e-06",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#2 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 305
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_0.0001",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#3 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 41
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_0.001",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#4 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_0.01",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#5 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_0.1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#6 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#7 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_15",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#8 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_off_-1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#9 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_inplane_5_-3",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#10 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_inplane_0_0.5",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#11 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_inplane_-2_0.5",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#12 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_rect_eyez_30",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#13 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 9
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_rect_eyez_1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#14 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 9
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_rect_eyez_0.001",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#15 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 9
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_rect_eyez_0",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#16 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 1
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "eye59_rect_eyez_-5",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/curve.curve_p9/eye_on_plane.json#17 (upstream solidcore#59: perspective eye on or near the view plane)",
|
||||
"values_compared": 12
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cci_projection_nurb_self",
|
||||
@@ -24749,8 +24893,8 @@
|
||||
"cases_both_errored": 0,
|
||||
"cases_deferred": 0,
|
||||
"cases_failed": 0,
|
||||
"cases_passed": 3093,
|
||||
"cases_total": 3093,
|
||||
"cases_passed": 3111,
|
||||
"cases_total": 3111,
|
||||
"deferred_by_unit": {},
|
||||
"max_rel_err": 0.0,
|
||||
"pass": true,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_rayfire_behind_start_single_False",
|
||||
@@ -16,7 +16,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_rayfire_ahead_single_False",
|
||||
@@ -36,7 +36,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_rayfire_behind_start_single_True",
|
||||
@@ -48,7 +48,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_rayfire_ahead_single_True",
|
||||
@@ -452,7 +452,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_pc_line_8_False",
|
||||
@@ -464,7 +464,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "adv_pc_line_8_True",
|
||||
@@ -1656,7 +1656,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "point_vertex_op_8_coincident",
|
||||
@@ -1668,7 +1668,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "point_vertex_op_8_unit_away",
|
||||
@@ -2424,7 +2424,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "point_vertex_rayfire_tolerance_limit",
|
||||
@@ -2436,7 +2436,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "point_vertex_rayfire_behind_start",
|
||||
@@ -2448,7 +2448,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "point_vertex_rayfire_behind_start_swapped",
|
||||
@@ -2716,7 +2716,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "rectangle_point_vertex_rayfire_corner",
|
||||
@@ -4756,7 +4756,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0045",
|
||||
@@ -4796,7 +4796,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0049",
|
||||
@@ -5024,7 +5024,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0077",
|
||||
@@ -6140,7 +6140,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0214",
|
||||
@@ -7308,7 +7308,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0357",
|
||||
@@ -8748,7 +8748,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0534",
|
||||
@@ -9340,7 +9340,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0607",
|
||||
@@ -9680,7 +9680,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0648",
|
||||
@@ -9868,7 +9868,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0671",
|
||||
@@ -11300,7 +11300,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0848",
|
||||
@@ -11384,7 +11384,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0858",
|
||||
@@ -11852,7 +11852,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0916",
|
||||
@@ -12052,7 +12052,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0940",
|
||||
@@ -12680,7 +12680,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1018",
|
||||
@@ -12716,7 +12716,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1022",
|
||||
@@ -12848,7 +12848,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1037",
|
||||
@@ -15920,7 +15920,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1416",
|
||||
@@ -16376,7 +16376,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1472",
|
||||
@@ -16836,7 +16836,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1529",
|
||||
@@ -17216,7 +17216,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1576",
|
||||
@@ -17700,7 +17700,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1636",
|
||||
@@ -19132,7 +19132,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1812",
|
||||
@@ -19772,7 +19772,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1891",
|
||||
@@ -19872,7 +19872,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1903",
|
||||
@@ -21628,7 +21628,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2119",
|
||||
@@ -22744,7 +22744,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2257",
|
||||
@@ -22812,7 +22812,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2265",
|
||||
@@ -23140,7 +23140,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2304",
|
||||
@@ -23296,7 +23296,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2323",
|
||||
@@ -24932,7 +24932,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2525",
|
||||
@@ -26356,7 +26356,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2699",
|
||||
@@ -26976,7 +26976,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2775",
|
||||
@@ -27004,7 +27004,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2778",
|
||||
@@ -27112,7 +27112,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2791",
|
||||
@@ -27648,7 +27648,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2857",
|
||||
@@ -28356,7 +28356,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen2941",
|
||||
@@ -28836,7 +28836,7 @@
|
||||
"cases_passed": 3389,
|
||||
"cases_total": 3532,
|
||||
"deferred_by_unit": {
|
||||
"geom.solution_array": 48,
|
||||
"geom.tol": 48,
|
||||
"topology.edge": 95
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
|
||||
@@ -2432,7 +2432,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "intersect.topology_solver_p1"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_included_without_shape_limit_5_3_0",
|
||||
@@ -2444,7 +2444,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "intersect.topology_solver_p1"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_included_without_shape_limit_5_3_1",
|
||||
@@ -2456,7 +2456,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "intersect.topology_solver_p1"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_included_without_shape_limit_5_4_0",
|
||||
@@ -2468,7 +2468,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "intersect.topology_solver_p1"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_included_without_shape_limit_5_4_1",
|
||||
@@ -2976,7 +2976,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "static_operation_matrix_0_8_0_0",
|
||||
@@ -2996,7 +2996,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "geom.solution_array"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "static_operation_matrix_0_8_1_0",
|
||||
@@ -19573,10 +19573,9 @@
|
||||
"cases_total": 2429,
|
||||
"deferred_by_unit": {
|
||||
"curve.iso_curve": 12,
|
||||
"geom.solution_array": 2,
|
||||
"geom.tol": 6,
|
||||
"intersect.curve_class_p2": 4,
|
||||
"intersect.surface_tracer": 8,
|
||||
"intersect.topology_solver_p1": 4,
|
||||
"topology.edge": 3
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0016",
|
||||
@@ -248,7 +248,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0019",
|
||||
@@ -300,7 +300,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0024",
|
||||
@@ -332,7 +332,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0027",
|
||||
@@ -428,7 +428,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0037",
|
||||
@@ -452,7 +452,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0039",
|
||||
@@ -464,7 +464,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0040",
|
||||
@@ -792,7 +792,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0074",
|
||||
@@ -1004,7 +1004,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0095",
|
||||
@@ -1016,7 +1016,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0096",
|
||||
@@ -1068,7 +1068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0101",
|
||||
@@ -1116,7 +1116,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0105",
|
||||
@@ -1200,7 +1200,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0114",
|
||||
@@ -1256,7 +1256,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0120",
|
||||
@@ -1344,7 +1344,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0128",
|
||||
@@ -1356,7 +1356,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0129",
|
||||
@@ -1576,7 +1576,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0152",
|
||||
@@ -1588,7 +1588,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0153",
|
||||
@@ -1612,7 +1612,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0155",
|
||||
@@ -1656,7 +1656,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0159",
|
||||
@@ -1692,7 +1692,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0163",
|
||||
@@ -1792,7 +1792,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0173",
|
||||
@@ -1884,7 +1884,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0182",
|
||||
@@ -2180,7 +2180,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0213",
|
||||
@@ -2332,7 +2332,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0230",
|
||||
@@ -2616,7 +2616,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0258",
|
||||
@@ -2688,7 +2688,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0266",
|
||||
@@ -2792,7 +2792,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0275",
|
||||
@@ -2968,7 +2968,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0293",
|
||||
@@ -3068,7 +3068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0302",
|
||||
@@ -3088,7 +3088,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0304",
|
||||
@@ -3184,7 +3184,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0313",
|
||||
@@ -3268,7 +3268,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0323",
|
||||
@@ -3428,7 +3428,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0339",
|
||||
@@ -3484,7 +3484,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0345",
|
||||
@@ -3520,7 +3520,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0348",
|
||||
@@ -3612,7 +3612,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0357",
|
||||
@@ -3728,7 +3728,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0368",
|
||||
@@ -3872,7 +3872,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0383",
|
||||
@@ -3900,7 +3900,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0386",
|
||||
@@ -4016,7 +4016,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0397",
|
||||
@@ -4048,7 +4048,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0400",
|
||||
@@ -4144,7 +4144,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0410",
|
||||
@@ -4172,7 +4172,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0413",
|
||||
@@ -4204,7 +4204,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0416",
|
||||
@@ -4412,7 +4412,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0438",
|
||||
@@ -4544,7 +4544,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0451",
|
||||
@@ -4572,7 +4572,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0454",
|
||||
@@ -4596,7 +4596,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0456",
|
||||
@@ -4608,7 +4608,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0457",
|
||||
@@ -4644,7 +4644,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0460",
|
||||
@@ -4792,7 +4792,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0475",
|
||||
@@ -4984,7 +4984,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0494",
|
||||
@@ -5072,7 +5072,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0503",
|
||||
@@ -5092,7 +5092,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0505",
|
||||
@@ -5540,7 +5540,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0550",
|
||||
@@ -5828,7 +5828,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0577",
|
||||
@@ -5888,7 +5888,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0583",
|
||||
@@ -6344,7 +6344,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0629",
|
||||
@@ -6484,7 +6484,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0642",
|
||||
@@ -6732,7 +6732,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0668",
|
||||
@@ -6860,7 +6860,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0681",
|
||||
@@ -6872,7 +6872,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0682",
|
||||
@@ -6992,7 +6992,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0694",
|
||||
@@ -7100,7 +7100,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0705",
|
||||
@@ -7128,7 +7128,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0708",
|
||||
@@ -7296,7 +7296,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0726",
|
||||
@@ -7368,7 +7368,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0733",
|
||||
@@ -7472,7 +7472,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0742",
|
||||
@@ -7520,7 +7520,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0747",
|
||||
@@ -7600,7 +7600,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0755",
|
||||
@@ -7640,7 +7640,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0759",
|
||||
@@ -7840,7 +7840,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0779",
|
||||
@@ -7896,7 +7896,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0785",
|
||||
@@ -7948,7 +7948,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0791",
|
||||
@@ -8028,7 +8028,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0799",
|
||||
@@ -8352,7 +8352,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "mouse_edgeuse_offset_extend",
|
||||
@@ -8576,7 +8576,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cone_mate_extend_local",
|
||||
@@ -8630,11 +8630,11 @@
|
||||
"deferred_by_unit": {
|
||||
"blend.fillet_standard_solver_p1": 4,
|
||||
"curve.crv_on_surf": 25,
|
||||
"geom.tol": 78,
|
||||
"harness:analytic-geometry-export": 70,
|
||||
"intersect.surface_drop_curve": 27,
|
||||
"intersect.surface_drop_lib_p3": 7,
|
||||
"surface.sphere": 2,
|
||||
"surface.surface_cache_p2": 78,
|
||||
"topology.brep_p2": 166,
|
||||
"topology.face_p2": 12,
|
||||
"topology.face_p4": 42
|
||||
|
||||
@@ -8320,7 +8320,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0013",
|
||||
@@ -8676,7 +8676,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0049",
|
||||
@@ -8828,7 +8828,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0063",
|
||||
@@ -8884,7 +8884,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0069",
|
||||
@@ -9148,7 +9148,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0097",
|
||||
@@ -9220,7 +9220,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0104",
|
||||
@@ -9340,7 +9340,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0116",
|
||||
@@ -9600,7 +9600,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0142",
|
||||
@@ -9836,7 +9836,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0165",
|
||||
@@ -10412,7 +10412,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0222",
|
||||
@@ -10664,7 +10664,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0249",
|
||||
@@ -11004,7 +11004,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0283",
|
||||
@@ -11064,7 +11064,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0288",
|
||||
@@ -11476,7 +11476,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0327",
|
||||
@@ -11700,7 +11700,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0348",
|
||||
@@ -11872,7 +11872,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0366",
|
||||
@@ -12240,7 +12240,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0403",
|
||||
@@ -12252,7 +12252,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0404",
|
||||
@@ -12592,7 +12592,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0437",
|
||||
@@ -12820,7 +12820,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0458",
|
||||
@@ -12832,7 +12832,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0459",
|
||||
@@ -12844,7 +12844,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0460",
|
||||
@@ -12904,7 +12904,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0466",
|
||||
@@ -13028,7 +13028,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0478",
|
||||
@@ -13060,7 +13060,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0481",
|
||||
@@ -13132,7 +13132,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0488",
|
||||
@@ -13196,7 +13196,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0495",
|
||||
@@ -13720,7 +13720,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0548",
|
||||
@@ -13864,7 +13864,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0563",
|
||||
@@ -14464,7 +14464,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0621",
|
||||
@@ -14476,7 +14476,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0622",
|
||||
@@ -15068,7 +15068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0681",
|
||||
@@ -15332,7 +15332,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0705",
|
||||
@@ -15812,7 +15812,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0751",
|
||||
@@ -15856,7 +15856,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0755",
|
||||
@@ -16204,7 +16204,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0791",
|
||||
@@ -16228,7 +16228,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0793",
|
||||
@@ -16304,7 +16304,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0800",
|
||||
@@ -16476,7 +16476,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0817",
|
||||
@@ -16520,7 +16520,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0821",
|
||||
@@ -16860,7 +16860,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0853",
|
||||
@@ -17668,7 +17668,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0933",
|
||||
@@ -17692,7 +17692,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0935",
|
||||
@@ -17772,7 +17772,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0942",
|
||||
@@ -18068,7 +18068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen0972",
|
||||
@@ -18604,7 +18604,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1026",
|
||||
@@ -18796,7 +18796,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1044",
|
||||
@@ -18912,7 +18912,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1054",
|
||||
@@ -18924,7 +18924,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1055",
|
||||
@@ -18936,7 +18936,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1056",
|
||||
@@ -19044,7 +19044,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1066",
|
||||
@@ -19488,7 +19488,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1109",
|
||||
@@ -19500,7 +19500,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1110",
|
||||
@@ -19616,7 +19616,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1122",
|
||||
@@ -19832,7 +19832,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1143",
|
||||
@@ -19900,7 +19900,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1150",
|
||||
@@ -19920,7 +19920,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "gen1152",
|
||||
@@ -20417,12 +20417,12 @@
|
||||
"cases_total": 2224,
|
||||
"deferred_by_unit": {
|
||||
"curve.crv_on_surf": 19,
|
||||
"geom.tol": 57,
|
||||
"harness:analytic-geometry-export": 31,
|
||||
"intersect.surface_drop_lib_p3": 36,
|
||||
"surface.cone_p1": 41,
|
||||
"surface.sphere": 12,
|
||||
"surface.surf_of_extrusion_p2": 59,
|
||||
"surface.surface_cache_p2": 57,
|
||||
"topology.face_p2": 397,
|
||||
"topology.face_p3": 2
|
||||
},
|
||||
|
||||
@@ -1589,6 +1589,14 @@
|
||||
"source": "fixture:fixtures/surface.cone_p3/fuzz_height.json#7 (upstream source/SMLib/src/SmCone.cpp:2251-2268 (issue #207; ignored evaluation errors leave initialized height points))",
|
||||
"values_compared": 5
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "fuzz_trim_domain_02497",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/surface.cone_p3/fuzz_trim_domain.json#0 (upstream source/SMLib/src/SmCone.cpp:5325 (sm_GetEllipseTrimIntervals ignores ConvertDomainFromNURBSToSTEP status; zero Y axis leaves no polar curve))",
|
||||
"values_compared": 59
|
||||
},
|
||||
{
|
||||
"both_errored": true,
|
||||
"max_rel_err": 0.0,
|
||||
@@ -11473,8 +11481,8 @@
|
||||
"cases_both_errored": 8,
|
||||
"cases_deferred": 35,
|
||||
"cases_failed": 0,
|
||||
"cases_passed": 1380,
|
||||
"cases_total": 1415,
|
||||
"cases_passed": 1381,
|
||||
"cases_total": 1416,
|
||||
"deferred_by_unit": {
|
||||
"surface.surface_p2": 35
|
||||
},
|
||||
|
||||
@@ -1146,7 +1146,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_plane_find_sector_global",
|
||||
@@ -1210,7 +1210,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_plane_parallel_proj",
|
||||
@@ -1530,7 +1530,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_bspline_parallel_proj",
|
||||
@@ -1850,7 +1850,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "face_bspline_sub_parallel_proj",
|
||||
@@ -2268,6 +2268,343 @@
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#237 (upstream TestFiles/pt_TestFiles/constructed (SmBrep::ReadFromFile))",
|
||||
"values_compared": 17
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#238 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_corner_blend_3210",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#239 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#240 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_quad_cubic_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#241 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_quad_cubic_corner_blend_3210",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#242 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_quad_cubic_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#243 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_sub_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#244 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_sub_corner_blend_3210",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#245 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_open_bicubic_sub_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#246 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#247 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmBSplineSurface::CreateCornerBlend",
|
||||
"unit": "nurbs.b_spline_surface_n_lib_p2"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_corner_blend_3210",
|
||||
"outcome": "deferred",
|
||||
"pass": false,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#248 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#249 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_r3_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#250 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmBSplineSurface::CreateCornerBlend",
|
||||
"unit": "nurbs.b_spline_surface_n_lib_p2"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_r3_corner_blend_3210",
|
||||
"outcome": "deferred",
|
||||
"pass": false,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#251 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_r3_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#252 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#253 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmBSplineSurface::CreateCornerBlend",
|
||||
"unit": "nurbs.b_spline_surface_n_lib_p2"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_corner_blend_3210",
|
||||
"outcome": "deferred",
|
||||
"pass": false,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#254 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#255 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_r3_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#256 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmBSplineSurface::CreateCornerBlend",
|
||||
"unit": "nurbs.b_spline_surface_n_lib_p2"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_r3_corner_blend_3210",
|
||||
"outcome": "deferred",
|
||||
"pass": false,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#257 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_cyl_r3_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#258 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_c0_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#259 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_c0_corner_blend_3210",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#260 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_c0_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#261 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_c0_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#262 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_c0_corner_blend_3210",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#263 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_v_closed_c0_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#264 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_sub_corner_blend_0123",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#265 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmBSplineSurface::CreateCornerBlend",
|
||||
"unit": "nurbs.b_spline_surface_n_lib_p2"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_sub_corner_blend_3210",
|
||||
"outcome": "deferred",
|
||||
"pass": false,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#266 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "cos_u_closed_cyl_sub_corner_blend_0123_no_tangency",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#267 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend) -> SmBSplineSurfaceNLib.cpp:2922 (sm_CreateNonRationalCurve: SmCrvOnSurf edge curves, NER))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "two_breps_ruled_line_line_dir1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#268 (upstream source/SMLib/src/SmBrep.cpp:2810 (static SmBrep::CreateEdgeEdgeBlend, edge uses of two B-reps, ruled))",
|
||||
"values_compared": 34
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "two_breps_ruled_line_line_dir2",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#269 (upstream source/SMLib/src/SmBrep.cpp:2810 (static SmBrep::CreateEdgeEdgeBlend, edge uses of two B-reps, ruled))",
|
||||
"values_compared": 34
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "two_breps_ruled_line_line_dir0",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#270 (upstream source/SMLib/src/SmBrep.cpp:2810 (static SmBrep::CreateEdgeEdgeBlend, edge uses of two B-reps, ruled))",
|
||||
"values_compared": 34
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "two_breps_ruled_line_line_mate_dir1",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#271 (upstream source/SMLib/src/SmBrep.cpp:2810 (static SmBrep::CreateEdgeEdgeBlend, edge uses of two B-reps, ruled))",
|
||||
"values_compared": 34
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "two_breps_ruled_line_cubic_dir0",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#272 (upstream source/SMLib/src/SmBrep.cpp:2810 (static SmBrep::CreateEdgeEdgeBlend, edge uses of two B-reps, ruled))",
|
||||
"values_compared": 54
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "corner_blend_ang0_one_edgeuse",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#273 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend, tangency tolerance 0: HANG-39 only past the early returns))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "corner_blend_ang0_no_tangency_null_check",
|
||||
"outcome": "pass",
|
||||
"pass": true,
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#274 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend, tangency tolerance 0: HANG-39 only past the early returns))",
|
||||
"values_compared": 2
|
||||
},
|
||||
{
|
||||
"inputs": {
|
||||
"ang": 0.0,
|
||||
"brep": {
|
||||
"file": "plane_circ.smb",
|
||||
"kind": "file",
|
||||
"rebuild": true
|
||||
},
|
||||
"eus": [0, 1, 2],
|
||||
"op": "corner_blend",
|
||||
"tangent": null,
|
||||
"tol": 0.0001
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "corner_blend_ang0_reaches_cross_tangents",
|
||||
"outcome": "rejected",
|
||||
"pass": false,
|
||||
"rejected": "HANG-39: a tangency tolerance below 1e-20 where upstream reaches the cross-tangent approximation (tens of seconds or more): nothing runs on either side",
|
||||
"source": "fixture:fixtures/topology.brep_p1/constructed.json#275 (upstream source/SMLib/src/SmBrep.cpp:2488 (SmBrep::CreateCornerBlend, tangency tolerance 0: HANG-39 only past the early returns))",
|
||||
"values_compared": 0
|
||||
},
|
||||
{
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Mouse_lists_0",
|
||||
@@ -4644,7 +4981,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_parallel_proj_0",
|
||||
@@ -4656,7 +4993,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_parallel_proj_1",
|
||||
@@ -4668,7 +5005,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_parallel_proj_2",
|
||||
@@ -4680,7 +5017,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_parallel_proj_3",
|
||||
@@ -4692,7 +5029,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_parallel_proj_cubic",
|
||||
@@ -5517,7 +5854,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "box_with_large_fillet_find_sector_0",
|
||||
@@ -5529,7 +5866,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "box_with_large_fillet_find_sector_1",
|
||||
@@ -7968,7 +8305,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_find_sector_0",
|
||||
@@ -7980,7 +8317,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_find_sector_1",
|
||||
@@ -8303,7 +8640,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_parallel_proj_0",
|
||||
@@ -8315,7 +8652,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_parallel_proj_1",
|
||||
@@ -8327,7 +8664,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_parallel_proj_2",
|
||||
@@ -8339,7 +8676,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_parallel_proj_3",
|
||||
@@ -8351,7 +8688,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "disk_parallel_proj_cubic",
|
||||
@@ -9487,7 +9824,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "ellips_ts2_parallel_proj_0",
|
||||
@@ -9499,7 +9836,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "ellips_ts2_parallel_proj_1",
|
||||
@@ -9511,7 +9848,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "ellips_ts2_parallel_proj_2",
|
||||
@@ -9523,7 +9860,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "ellips_ts2_parallel_proj_3",
|
||||
@@ -9535,7 +9872,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "ellips_ts2_parallel_proj_cubic",
|
||||
@@ -10364,7 +10701,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_find_sector_0",
|
||||
@@ -10376,7 +10713,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_find_sector_1",
|
||||
@@ -10691,7 +11028,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_parallel_proj_0",
|
||||
@@ -10703,7 +11040,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_parallel_proj_1",
|
||||
@@ -10715,7 +11052,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_parallel_proj_2",
|
||||
@@ -10727,7 +11064,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_parallel_proj_3",
|
||||
@@ -10739,7 +11076,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_circ_parallel_proj_cubic",
|
||||
@@ -11560,7 +11897,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_find_sector_0",
|
||||
@@ -11572,7 +11909,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_find_sector_1",
|
||||
@@ -11887,7 +12224,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_parallel_proj_0",
|
||||
@@ -11899,7 +12236,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_parallel_proj_1",
|
||||
@@ -11911,7 +12248,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_parallel_proj_2",
|
||||
@@ -11923,7 +12260,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_parallel_proj_3",
|
||||
@@ -11935,7 +12272,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "plane_square_parallel_proj_cubic",
|
||||
@@ -22887,17 +23224,18 @@
|
||||
}
|
||||
],
|
||||
"cases_both_errored": 45,
|
||||
"cases_deferred": 465,
|
||||
"cases_deferred": 470,
|
||||
"cases_failed": 0,
|
||||
"cases_passed": 2109,
|
||||
"cases_rejected": 15,
|
||||
"cases_total": 2589,
|
||||
"cases_passed": 2141,
|
||||
"cases_rejected": 16,
|
||||
"cases_total": 2627,
|
||||
"deferred_by_unit": {
|
||||
"curve.crv_on_surf": 4,
|
||||
"geom.tol": 37,
|
||||
"harness:analytic-geometry-export": 217,
|
||||
"intersect.surface_drop_lib_p3": 10,
|
||||
"nurbs.b_spline_surface_n_lib_p2": 5,
|
||||
"query.brep": 71,
|
||||
"surface.surface_cache_p2": 37,
|
||||
"topology.face_p2": 89,
|
||||
"topology.face_p3": 21,
|
||||
"topology.face_p4": 16
|
||||
|
||||
@@ -2136,7 +2136,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "project_t0_Defeature_inset_cube",
|
||||
@@ -2148,7 +2148,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "project_t1_Defeature_inset_cube",
|
||||
@@ -2160,7 +2160,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "project_t2_Defeature_inset_cube",
|
||||
@@ -2172,7 +2172,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "project_t0_Defeature_brep1",
|
||||
@@ -2184,7 +2184,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "project_tols_inset_cube",
|
||||
@@ -13500,10 +13500,10 @@
|
||||
"cases_passed": 839,
|
||||
"cases_total": 1404,
|
||||
"deferred_by_unit": {
|
||||
"geom.tol": 5,
|
||||
"surface.cone_p1": 41,
|
||||
"surface.sphere": 328,
|
||||
"surface.surf_of_extrusion_p2": 10,
|
||||
"surface.surface_cache_p2": 5,
|
||||
"surface.surface_p2": 96,
|
||||
"topology.brep_p2": 19,
|
||||
"topology.face_p2": 58,
|
||||
|
||||
@@ -7268,7 +7268,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_intersect_49",
|
||||
@@ -7304,7 +7304,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_intersect_52",
|
||||
@@ -7340,7 +7340,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_intersect_55",
|
||||
@@ -8032,7 +8032,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_rebuilt_intersect_49",
|
||||
@@ -8068,7 +8068,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_rebuilt_intersect_52",
|
||||
@@ -8104,7 +8104,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_rebuilt_intersect_55",
|
||||
@@ -13676,7 +13676,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_intersect_49",
|
||||
@@ -13712,7 +13712,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_intersect_52",
|
||||
@@ -13748,7 +13748,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_intersect_55",
|
||||
@@ -14440,7 +14440,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_subdomain_intersect_49",
|
||||
@@ -14476,7 +14476,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_subdomain_intersect_52",
|
||||
@@ -14512,7 +14512,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "bilinear_subdomain_intersect_55",
|
||||
@@ -15204,7 +15204,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "triangle_pole_intersect_49",
|
||||
@@ -15240,7 +15240,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "triangle_pole_intersect_52",
|
||||
@@ -15276,7 +15276,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "triangle_pole_intersect_55",
|
||||
@@ -15968,7 +15968,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "biquadratic_intersect_49",
|
||||
@@ -16004,7 +16004,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "biquadratic_intersect_52",
|
||||
@@ -16040,7 +16040,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "biquadratic_intersect_55",
|
||||
@@ -16082,7 +16082,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_00",
|
||||
@@ -16094,7 +16094,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_01",
|
||||
@@ -16106,7 +16106,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_02",
|
||||
@@ -16118,7 +16118,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_03",
|
||||
@@ -16130,7 +16130,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_04",
|
||||
@@ -16142,7 +16142,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_05",
|
||||
@@ -16154,7 +16154,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_06",
|
||||
@@ -16166,7 +16166,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_07",
|
||||
@@ -16178,7 +16178,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_08",
|
||||
@@ -16190,7 +16190,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_09",
|
||||
@@ -16202,7 +16202,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_10",
|
||||
@@ -16214,7 +16214,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_11",
|
||||
@@ -16226,7 +16226,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_12",
|
||||
@@ -16238,7 +16238,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_13",
|
||||
@@ -16250,7 +16250,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_14",
|
||||
@@ -16262,7 +16262,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_15",
|
||||
@@ -16274,7 +16274,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_16",
|
||||
@@ -16286,7 +16286,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_17",
|
||||
@@ -16298,7 +16298,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_18",
|
||||
@@ -16310,7 +16310,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_19",
|
||||
@@ -16322,7 +16322,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_20",
|
||||
@@ -16334,7 +16334,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_21",
|
||||
@@ -16346,7 +16346,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_22",
|
||||
@@ -16358,7 +16358,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_23",
|
||||
@@ -16370,7 +16370,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_24",
|
||||
@@ -16382,7 +16382,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_25",
|
||||
@@ -16394,7 +16394,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_26",
|
||||
@@ -16406,7 +16406,7 @@
|
||||
{
|
||||
"deferred": {
|
||||
"symbol": "SmTol::GetZoneTol3d(const SmObject*)",
|
||||
"unit": "surface.surface_cache_p2"
|
||||
"unit": "geom.tol"
|
||||
},
|
||||
"max_rel_err": 0.0,
|
||||
"name": "Endcap_pairs_intersect_27",
|
||||
@@ -18767,10 +18767,10 @@
|
||||
"cases_passed": 654,
|
||||
"cases_total": 1781,
|
||||
"deferred_by_unit": {
|
||||
"geom.tol": 46,
|
||||
"intersect.curve_class_p2": 210,
|
||||
"intersect.surface_drop_lib_p3": 115,
|
||||
"surface.surf_of_extrusion_p2": 112,
|
||||
"surface.surface_cache_p2": 46,
|
||||
"surface.surface_p2": 228,
|
||||
"topology.face_p2": 148,
|
||||
"topology.face_p4": 268
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Self-hosted runner only: keep the Cargo build directory between jobs, outside the checkout
|
||||
# (actions/checkout's clean deletes bin/), and point CARGO_TARGET_DIR at it for the rest of
|
||||
# the job. Each self-hosted runner has its own /home/runner and runs one job at a time, so the
|
||||
# jobs on one runner share one directory and two runners never share one.
|
||||
set -euo pipefail
|
||||
dir=/home/runner/cargo-target/solidcore
|
||||
# Start over when it has grown past 30 GB: old dependency versions and profiles pile up.
|
||||
if [ -d "$dir" ] && [ "$(du -sm "$dir" | cut -f1)" -gt 30000 ]; then
|
||||
echo "warm-target: $dir is over 30 GB, starting a fresh build"
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
mkdir -p "$dir"
|
||||
echo "CARGO_TARGET_DIR=$dir" >> "$GITHUB_ENV"
|
||||
echo "warm-target: $dir ($(du -sh "$dir" | cut -f1))"
|
||||
+1
-1
@@ -17,7 +17,7 @@ commit date of `HEAD`.
|
||||
| Module pages (`areas/<module>.html`) | `plan/modules.toml` and its history: the same chart as the overview, over that module's units only |
|
||||
| Units (`units/index.html`) | `plan/modules.toml`, `harness/callgraph/units.json`, `reports/difftest/*.json` (`cases_*`, `deferred_by_unit`) |
|
||||
| Unit pages (`units/<id>.html`) | the above, plus the `//! | Rust | Upstream |` table in the module's file header and the unit's status history from the timeline |
|
||||
| Dependency graph (`graph.html`, `assets/graph.json`) | `plan/modules.toml` (`depends_on`, `layer`, status) and claims; lists of ready and most-blocking units are rendered server-side, the graph by `site/assets/graph.js` |
|
||||
| Dependency graph (`graph.html`, `assets/graph.json`) | `plan/modules.toml` (`depends_on`, module, status) and claims, laid out as one force-directed cluster per module; lists of ready and most-blocking units are rendered server-side, the graph by `site/assets/graph.js` |
|
||||
| Upstream issues (`issues.html`) | `plan/upstream-issues.md`, split at `#### <SERIES>-<n>.` headings |
|
||||
| SSI corpus (`ssi.html`) | `reports/ssi-corpus.json` |
|
||||
|
||||
|
||||
+88
-52
@@ -1,5 +1,5 @@
|
||||
// solidcore dependency graph (graph.html): lays out assets/graph.json with d3-force
|
||||
// (vendor/d3-force.bundle.min.js) into an SVG with pan/zoom, hover, search, module filter
|
||||
// (vendor/d3-force.bundle.min.js) as one cluster per module, into an SVG with pan/zoom, hover, search, module filter
|
||||
// and click-to-highlight. Without JS the page keeps its server-rendered lists.
|
||||
(function () {
|
||||
"use strict";
|
||||
@@ -7,7 +7,6 @@
|
||||
var svg = document.getElementById("graph");
|
||||
if (!ui || !svg || typeof d3 === "undefined" || !window.fetch) return;
|
||||
var NS = "http://www.w3.org/2000/svg";
|
||||
var COL = 36, ROW = 20, PAD = 24, LABEL = 150;
|
||||
|
||||
function el(name, attrs, parent) {
|
||||
var e = document.createElementNS(NS, name);
|
||||
@@ -32,47 +31,81 @@
|
||||
});
|
||||
});
|
||||
|
||||
// Rows: one band per module, tall enough for its busiest layer.
|
||||
var bands = [], y = PAD;
|
||||
data.areas.forEach(function (a) {
|
||||
var per = {};
|
||||
nodes.forEach(function (n) { if (n.area === a) per[n.layer] = (per[n.layer] || 0) + 1; });
|
||||
var most = Math.max.apply(null, Object.keys(per).map(function (k) { return per[k]; }).concat([1]));
|
||||
var h = Math.max(2, most) * ROW + ROW;
|
||||
bands.push({ area: a, y0: y, y1: y + h, c: y + h / 2 });
|
||||
y += h;
|
||||
});
|
||||
var bandOf = {};
|
||||
bands.forEach(function (b) { bandOf[b.area] = b; });
|
||||
var maxLayer = Math.max.apply(null, nodes.map(function (n) { return n.layer; }));
|
||||
var W = LABEL + PAD * 2 + COL * maxLayer, H = y + PAD;
|
||||
function lx(layer) { return LABEL + PAD + COL * layer; }
|
||||
function rad(n) { return 3.5 + Math.sqrt(n.lines) / 9; }
|
||||
|
||||
nodes.forEach(function (n, k) {
|
||||
var b = bandOf[n.area];
|
||||
n.x = lx(n.layer);
|
||||
n.y = b ? b.c + ((k % 5) - 2) * 4 : H / 2;
|
||||
// Stage 1: one meta-node per module. Modules repel each other and are pulled
|
||||
// together by the number of dependency edges between them. Starting positions sit on
|
||||
// a circle in the plan's module order, and d3-force's own jiggle uses a fixed-seed
|
||||
// generator, so the layout is the same on every load.
|
||||
var areas = data.areas.map(function (a, k) {
|
||||
var members = nodes.filter(function (n) { return n.area === a; });
|
||||
var mass = members.reduce(function (t, n) { return t + Math.pow(rad(n) + 3, 2); }, 0);
|
||||
return { id: a, k: k, members: members, r: Math.sqrt(mass) * 1.25 + 14 };
|
||||
});
|
||||
var sim = d3.forceSimulation(nodes)
|
||||
.force("x", d3.forceX(function (n) { return lx(n.layer); }).strength(1))
|
||||
.force("y", d3.forceY(function (n) { return bandOf[n.area] ? bandOf[n.area].c : H / 2; }).strength(0.35))
|
||||
.force("link", d3.forceLink(edges).strength(0.0005))
|
||||
.force("collide", d3.forceCollide(function (n) { return rad(n) + 2; }).iterations(2))
|
||||
.stop();
|
||||
for (var t = 0; t < 300; t++) sim.tick();
|
||||
nodes.forEach(function (n) {
|
||||
var b = bandOf[n.area];
|
||||
if (b) n.y = Math.min(b.y1 - rad(n), Math.max(b.y0 + rad(n), n.y));
|
||||
var areaOf = {};
|
||||
areas.forEach(function (c) { areaOf[c.id] = c; });
|
||||
var ring = areas.reduce(function (t, c) { return t + c.r; }, 0) * 1.1 / Math.PI;
|
||||
areas.forEach(function (c) {
|
||||
var ang = 2 * Math.PI * c.k / areas.length - Math.PI / 2;
|
||||
c.x = ring * Math.cos(ang); c.y = ring * Math.sin(ang);
|
||||
});
|
||||
var pair = {};
|
||||
edges.forEach(function (e) {
|
||||
var s = e.source.area, t = e.target.area;
|
||||
if (s === t || !areaOf[s] || !areaOf[t]) return;
|
||||
var key = s < t ? s + "|" + t : t + "|" + s;
|
||||
pair[key] = (pair[key] || 0) + 1;
|
||||
});
|
||||
var metaLinks = Object.keys(pair).sort().map(function (key) {
|
||||
var ab = key.split("|");
|
||||
return { source: areaOf[ab[0]], target: areaOf[ab[1]], n: pair[key] };
|
||||
});
|
||||
d3.forceSimulation(areas)
|
||||
.force("charge", d3.forceManyBody().strength(function (c) { return -40 * c.r; }))
|
||||
.force("link", d3.forceLink(metaLinks)
|
||||
.distance(function (l) { return l.source.r + l.target.r + 50; })
|
||||
.strength(function (l) { return Math.min(1, l.n / 60); }))
|
||||
.force("collide", d3.forceCollide(function (c) { return c.r + 40; }).iterations(3))
|
||||
.force("x", d3.forceX(0).strength(0.03))
|
||||
.force("y", d3.forceY(0).strength(0.03))
|
||||
.stop()
|
||||
.tick(400);
|
||||
|
||||
// Stage 2: units, pulled towards their module's centre; links inside a module pull
|
||||
// tight, links across modules only gently.
|
||||
areas.forEach(function (c) {
|
||||
c.members.forEach(function (n, j) { // phyllotaxis start, deterministic
|
||||
var rr = 6 * Math.sqrt(j + 0.5), th = j * 2.399963;
|
||||
n.x = c.x + rr * Math.cos(th); n.y = c.y + rr * Math.sin(th);
|
||||
});
|
||||
});
|
||||
function same(e) { return e.source.area === e.target.area; }
|
||||
d3.forceSimulation(nodes)
|
||||
.force("x", d3.forceX(function (n) { return areaOf[n.area] ? areaOf[n.area].x : 0; }).strength(0.12))
|
||||
.force("y", d3.forceY(function (n) { return areaOf[n.area] ? areaOf[n.area].y : 0; }).strength(0.12))
|
||||
.force("link", d3.forceLink(edges)
|
||||
.distance(function (e) { return same(e) ? 16 : 80; })
|
||||
.strength(function (e) { return same(e) ? 0.08 : 0.004; }))
|
||||
.force("charge", d3.forceManyBody().strength(-14).distanceMax(90))
|
||||
.force("collide", d3.forceCollide(function (n) { return rad(n) + 1.5; }).iterations(2))
|
||||
.stop()
|
||||
.tick(400);
|
||||
|
||||
function bbox(list, pad) {
|
||||
var b = { x0: Infinity, y0: Infinity, x1: -Infinity, y1: -Infinity };
|
||||
list.forEach(function (n) {
|
||||
var r = rad(n) + 4;
|
||||
b.x0 = Math.min(b.x0, n.x - r); b.x1 = Math.max(b.x1, n.x + r);
|
||||
b.y0 = Math.min(b.y0, n.y - r); b.y1 = Math.max(b.y1, n.y + r);
|
||||
});
|
||||
b.x0 -= pad; b.y0 -= pad; b.x1 += pad; b.y1 += pad;
|
||||
return b;
|
||||
}
|
||||
var all = bbox(nodes, 30);
|
||||
var W = all.x1 - all.x0;
|
||||
|
||||
// ---- drawing
|
||||
var vp = el("g", { "class": "vp" }, svg);
|
||||
var gb = el("g", { "class": "bands" }, vp);
|
||||
bands.forEach(function (b, k) {
|
||||
el("rect", { x: 0, y: b.y0, width: W, height: b.y1 - b.y0, "class": k % 2 ? "band odd" : "band" }, gb);
|
||||
el("text", { x: 8, y: b.c + 4, "class": "blabel" }, gb).textContent = b.area;
|
||||
});
|
||||
var ge = el("g", { "class": "edges" }, vp);
|
||||
edges.forEach(function (e) {
|
||||
e.el = el("line", { x1: e.source.x.toFixed(1), y1: e.source.y.toFixed(1),
|
||||
@@ -86,24 +119,33 @@
|
||||
el("circle", { r: rad(n), "class": "dot" }, g);
|
||||
n.el = g;
|
||||
});
|
||||
var gl = el("g", { "class": "labels" }, vp);
|
||||
areas.forEach(function (c) {
|
||||
if (!c.members.length) return;
|
||||
var cx = 0, cy = 0;
|
||||
c.members.forEach(function (n) { cx += n.x; cy += n.y; });
|
||||
cx /= c.members.length; cy /= c.members.length;
|
||||
el("text", { x: cx.toFixed(1), y: (cy + 5).toFixed(1), "class": "clabel", "text-anchor": "middle" }, gl).textContent = c.id;
|
||||
});
|
||||
|
||||
// ---- view box: pan and zoom
|
||||
var view = { x: 0, y: 0, w: W, h: H };
|
||||
var view = { x: all.x0, y: all.y0, w: W, h: all.y1 - all.y0 };
|
||||
function apply() { svg.setAttribute("viewBox", view.x + " " + view.y + " " + view.w + " " + view.h); }
|
||||
function fit() {
|
||||
function show(b) {
|
||||
var box = svg.getBoundingClientRect();
|
||||
var aspect = box.width / Math.max(1, box.height);
|
||||
view.w = Math.max(W, H * aspect); view.h = view.w / aspect;
|
||||
view.x = (W - view.w) / 2; view.y = (H - view.h) / 2;
|
||||
view.w = Math.max(b.x1 - b.x0, (b.y1 - b.y0) * aspect); view.h = view.w / aspect;
|
||||
view.x = (b.x0 + b.x1 - view.w) / 2; view.y = (b.y0 + b.y1 - view.h) / 2;
|
||||
apply();
|
||||
}
|
||||
function fit() { show(all); }
|
||||
function toView(cx, cy) {
|
||||
var box = svg.getBoundingClientRect();
|
||||
return { x: view.x + (cx - box.left) * view.w / box.width, y: view.y + (cy - box.top) * view.h / box.height };
|
||||
}
|
||||
function zoom(f, cx, cy) {
|
||||
var p = toView(cx, cy);
|
||||
var nw = Math.min(W * 4, Math.max(120, view.w * f));
|
||||
var nw = Math.min(W * 4, Math.max(60, view.w * f));
|
||||
f = nw / view.w;
|
||||
view.x = p.x - (p.x - view.x) * f; view.y = p.y - (p.y - view.y) * f;
|
||||
view.w *= f; view.h *= f;
|
||||
@@ -201,7 +243,7 @@
|
||||
if (n && selected === n) n = null;
|
||||
selected = n;
|
||||
nodes.forEach(function (m) { m.el.classList.remove("sel", "up", "down"); });
|
||||
edges.forEach(function (e) { e.el.classList.remove("up", "down"); });
|
||||
edges.forEach(function (e) { e.el.classList.remove("up", "down", "direct"); });
|
||||
svg.classList.toggle("focus", !!n);
|
||||
info.textContent = "";
|
||||
if (!n) {
|
||||
@@ -217,6 +259,7 @@
|
||||
edges.forEach(function (e) {
|
||||
if ((ups[e.target.id] || e.target === n) && ups[e.source.id]) e.el.classList.add("up");
|
||||
if ((downs[e.source.id] || e.source === n) && downs[e.target.id]) e.el.classList.add("down");
|
||||
if (e.source === n || e.target === n) e.el.classList.add("direct");
|
||||
});
|
||||
var h = document.createElement("p");
|
||||
h.appendChild(link(n.id));
|
||||
@@ -253,16 +296,9 @@
|
||||
q.addEventListener("input", filter);
|
||||
area.addEventListener("change", function () {
|
||||
filter();
|
||||
var b = bandOf[area.value];
|
||||
if (b) {
|
||||
// fit the module's band, from its first to its last unit's column
|
||||
var xs = nodes.filter(function (n) { return n.area === area.value; }).map(function (n) { return n.x; });
|
||||
var x0 = Math.min.apply(null, xs) - COL, x1 = Math.max.apply(null, xs) + COL;
|
||||
var y0 = b.y0 - ROW, y1 = b.y1 + ROW;
|
||||
var box = svg.getBoundingClientRect(), aspect = box.width / Math.max(1, box.height);
|
||||
view.w = Math.max(x1 - x0, (y1 - y0) * aspect); view.h = view.w / aspect;
|
||||
view.x = (x0 + x1 - view.w) / 2; view.y = (y0 + y1 - view.h) / 2;
|
||||
apply();
|
||||
var c = areaOf[area.value];
|
||||
if (c && c.members.length) {
|
||||
show(bbox(c.members, 24));
|
||||
} else fit();
|
||||
});
|
||||
q.addEventListener("keydown", function (ev) {
|
||||
|
||||
@@ -229,10 +229,9 @@ td > a > code, td > code { white-space: nowrap; overflow-wrap: normal; }
|
||||
.graphbox { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
|
||||
overflow: hidden; margin-top: 0.4rem; }
|
||||
#graph { display: block; width: 100%; height: 70vh; min-height: 360px; touch-action: none; cursor: grab; user-select: none; }
|
||||
#graph .band { fill: transparent; }
|
||||
#graph .band.odd { fill: var(--surface-2); }
|
||||
#graph .blabel { fill: var(--text-2); font-size: 26px; font-weight: 600; }
|
||||
#graph .edges line { stroke: var(--muted); stroke-width: 0.6; opacity: 0.12; }
|
||||
#graph .clabel { fill: var(--text); font-size: 15px; font-weight: 650; pointer-events: none;
|
||||
paint-order: stroke; stroke: var(--surface); stroke-width: 4px; stroke-linejoin: round; opacity: 0.85; }
|
||||
#graph .edges line { stroke: var(--muted); stroke-width: 0.4; opacity: 0.1; }
|
||||
#graph .n { cursor: pointer; }
|
||||
#graph .n .dot { fill: var(--todo-bg); stroke: var(--muted); stroke-width: 1.2; }
|
||||
#graph .n.s-green .dot { fill: var(--green); stroke: var(--surface); }
|
||||
@@ -241,14 +240,17 @@ td > a > code, td > code { white-space: nowrap; overflow-wrap: normal; }
|
||||
#graph .n.k-blocked .dot { stroke: var(--bad-ink); stroke-width: 2; }
|
||||
#graph .n .ring { fill: none; stroke: var(--accent); stroke-width: 2.5; }
|
||||
#graph.focus .n, #graph.searching .n { opacity: 0.18; }
|
||||
#graph.focus .edges line { opacity: 0.06; }
|
||||
#graph.focus .edges line { opacity: 0.03; }
|
||||
#graph.focus .clabel { opacity: 0.4; }
|
||||
#graph.focus .n.up, #graph.focus .n.down, #graph.focus .n.sel, #graph.searching .n.hit { opacity: 1; }
|
||||
#graph .n.up .dot { stroke: var(--up); stroke-width: 2.5; }
|
||||
#graph .n.down .dot { stroke: var(--down); stroke-width: 2.5; }
|
||||
#graph .n.sel .dot { stroke: var(--text); stroke-width: 3; }
|
||||
#graph .n.hit .dot { stroke: var(--text); stroke-width: 2.5; }
|
||||
#graph.focus .edges line.up { stroke: var(--up); stroke-width: 1.4; opacity: 0.9; }
|
||||
#graph.focus .edges line.down { stroke: var(--down); stroke-width: 1.4; opacity: 0.9; }
|
||||
#graph.focus .edges line.up { stroke: var(--up); }
|
||||
#graph.focus .edges line.down { stroke: var(--down); }
|
||||
#graph.focus .edges line.up, #graph.focus .edges line.down { stroke-width: 0.8; opacity: 0.55; }
|
||||
#graph.focus .edges line.direct { stroke-width: 1.8; opacity: 1; }
|
||||
#graph .n.out { opacity: 0.06 !important; pointer-events: none; }
|
||||
#graph .edges line.out { opacity: 0.02 !important; }
|
||||
.ginfo { margin: 0.6rem 0 0; padding: 8px 12px; background: var(--surface); border: 1px solid var(--border);
|
||||
|
||||
+2
-2
@@ -544,8 +544,8 @@ def graph_body(g):
|
||||
return f"""
|
||||
<h1>Dependency graph</h1>
|
||||
<p class="muted">{len(nodes)} units and their {fmt_int(g['edges'])} <code>depends_on</code> edges from
|
||||
<code>plan/modules.toml</code> (soft dependencies are not drawn). Columns are the unit's layer, rows group
|
||||
units by module. Data: <a href="assets/graph.json"><code>assets/graph.json</code></a>.</p>
|
||||
<code>plan/modules.toml</code> (soft dependencies are not drawn). Units cluster by module, and dependency
|
||||
edges pull related modules together. Data: <a href="assets/graph.json"><code>assets/graph.json</code></a>.</p>
|
||||
<section class="kpis">{tiles}</section>
|
||||
<div class="graphui" hidden>
|
||||
<div class="filters">
|
||||
|
||||
Reference in New Issue
Block a user